Ir para conteúdo
  • Editando executáveis com o GNU poke - Parte 1

       (1 análise)

    Fernando Mercês

    Ano passado eu assisti à uma palestra sobre esse novo utilitário da suíte GNU chamado poke. Ele é um editor de dados binários de linha de comando bem diferente dos que costumo usar (HT Editor, Hiew, etc). Hoje decidi testá-lo e curti bastante. Tá em mega beta, então não tá nem perto de ter pacote disponível nos repositórios oficiais das distros Linux, mas consegui compilar e neste artigo vou dar as instruções, que podem variar em cada ambiente, até porque o poke está em constante desenvolvimento. Usei um ambiente Debian testing aqui.

    Instalando as dependências

    A dependência mais chatinha de instalar foi a gettext, porque o pacote pronto dela não foi suficiente. Então tive que clonar e compilar:

    $ sudo apt install perf fp-compiler fp-units-fcl groff build-essential git
    $ git clone https://git.savannah.gnu.org/git/gettext.git
    $ cd gettext
    $ ./gitsub.sh pull
    $ ./autogen.sh
    $ ./configure
    $ make
    $ sudo make install

    Com a gettext instalada, agora podemos partir para as demais dependências do poke:

    $ sudo apt install build-essential libgc-dev libreadline-dev flex libnbd-dev help2man texinfo

    Só então podemos seguir para a compilação do poke.

    Compilando o poke

    $ git clone git://git.savannah.gnu.org/poke.git
    $ cd poke
    $ ./bootstrap
    $ ./configure
    $ make
    $ sudo make install

    Criando links para as bibliotecas

    Como instalei as bibliotecas do poke em /usr/local e o meu sistema não tinha este diretório configurado para que o loader busque as bibliotecas, precisei criar dois links para elas em /usr/lib:

    $  sudo ln -s /usr/local/lib/libpoke.so.0 /usr/lib/libpoke.so.0
    $  sudo ln -s /usr/local/lib/libtextstyle.so.0 /usr/lib/libtextstyle.so.0

    Sei que há outras maneiras de resolver isso, mas fiz assim pra acelerar, afinal eu queria mexer no poke logo! ?

    Abrindo um binário PE no poke

    Baixei o executável do PuTTY para brincar um pouco e abri assim:

    $ poke putty.exe
         _____
     ---'   __\_______
                ______)  GNU poke 0.1-beta
                __)
               __)
     ---._______)
    
    Copyright (C) 2019, 2020 Jose E. Marchesi.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    Powered by Jitter 0.9.212.
    Perpetrated by Jose E. Marchesi.
    
    hserver listening in port 47209.
    
    For help, type ".help".
    Type ".exit" to leave the program.
    (poke)

    Gerenciando os arquivos abertos

    O poke permite trabalhar com múltiplos arquivos de uma vez. Você pode ver a lista de arquivos abertos com o seguinte comando:

    (poke) .info ios
      Id	Mode	Size		Name
    * #0	rw	0x0010b990#B	./putty.exe

    ios signifca "IO Spaces". Não tem nada a ver com o SO da Cisco ou com o da Apple. hehe

    Se quiser abrir outro arquivo, pode usar o comando .file <arquivo> e aí pode selecionar em qual você quer trabalhar com o comando .ios #n onde n é o número que identifica o arquivo, mas vou seguir o artigo com somente um arquivo aberto mesmo, então só teremos a tag #0.

    Dumpando dados

    Um dos principais comandos do poke é o dump (perceba este não começa com um ponto) que basicamente visualiza o conteúdo do arquivo, mas este tem várias opções. Vamos à mais básica:

    poke_dump.png.a306fee9e691569c325d5357f46cffc3.png

    A primeira linha na saída acima é só uma régua pra te ajudar a encontrar os bytes.

    Fiz questão de colar uma captura de tela aí acima pra você ver que o poke colore a saída, mas nos exemplos seguintes vou colar a saída em texto pelo bem da sua largura de banda. ?

    Por padrão, o dump exibe 128 bytes do arquivo, começando do seu primeiro byte. O número de bytes pode ser alterado na própria linha de comando:

    (poke) dump :size 64#B
    76543210  0011 2233 4455 6677 8899 aabb ccdd eeff  0123456789ABCDEF
    00000000: 4d5a 7800 0100 0000 0400 0000 0000 0000  MZx.............
    00000010: 0000 0000 0000 0000 4000 0000 0000 0000  ........@.......
    00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
    00000030: 0000 0000 0000 0000 0000 0000 7800 0000  ............x...

    A sintaxe pode parecer um pouco estranha no início, mas você acostuma rápido. O sufixo #B diz que a unidade usada é bytes. Você pode testar outros valores como 2#KB ou 1#MB por exemplo.  ?

    Dumpando a partir de posições específicas

    Para dumpar a partir de uma posição específica, podemos usar a opção :from do comando dump:

    (poke) dump :from 0x30#B :size 32#B
    76543210  0011 2233 4455 6677 8899 aabb ccdd eeff  0123456789ABCDEF
    00000030: 0000 0000 0000 0000 0000 0000 7800 0000  ............x...
    00000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 7468  ........!..L.!th

    No comando acima eu pedi para o poke me mostrar 32 bytes a partir da posição 0x30. Seria o equivalente a fazer hd -n 32 -s 0x30 <arquivo>.

    O poke mantém um ponteiro de leitura no arquivo, por isso se você comandar somente dump novamente, o dump ocorrerá a partir da última posição lida (no caso, 0x30). Se quiser voltar o ponteiro para a posição zero, é a mesma sintaxe: dump :from 0#B.

    Interpretando dados

    O dump sempre te entrega uma saída em hexadecimal, mas e se quisermos interpretar os dados e exibi-los de maneiras diferentes? Para  isso a gente larga de mão o comando dump e começa a operar com o jeito do poke de ler e interpretar especificamente, assim:

    (poke) byte @ 0#B
    77UB

    O sufixo UB significa Unsigned Byte.

    Se eu quiser a saída em hexa por exemplo, basta eu setar a variável obase (output base):

    (poke) .set obase 16
    (poke) byte @ 0#B
    0x4dUB

    Eu poderia querer ler 2 bytes. Tranquilo:

    (poke) byte[2] @ 0#B
    [0x4dUB,0x5aUB]

    Posso interpretar o conteúdo como número também:

    (poke) uint16 @ 0#B
    0x4d5aUH

    O prefixo UH significa Unsigned Half (Integer). Perceba que o poke sabe que um uint16 tem 2 bytes e por isso os lê sem a necessidade que especifiquemos o número de bytes a serem lidos.

    À essa altura você já sacou que equivalentes aos tipos padrão da linguagem C (da inttypes.h na real) estão disponíveis para uso né? Fique à vontade pra testar off64, int64, int32, etc.

    Lendo strings

    Além dos tipos numéricos, o poke tem o tipo string, onde ele lê até encontrar um nullbyte:

    (poke) dump
    76543210  0011 2233 4455 6677 8899 aabb ccdd eeff  0123456789ABCDEF
    00000000: 4d5a 7800 0100 0000 0400 0000 0000 0000  MZx.............
    00000010: 0000 0000 0000 0000 4000 0000 0000 0000  ........@.......
    00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
    00000030: 0000 0000 0000 0000 0000 0000 7800 0000  ............x...
    00000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468  ........!..L.!Th
    00000050: 6973 2070 726f 6772 616d 2063 616e 6e6f  is program canno
    00000060: 7420 6265 2072 756e 2069 6e20 444f 5320  t be run in DOS
    00000070: 6d6f 6465 2e24 0000 5045 0000 4c01 0700  mode.$..PE..L...
    
    (poke) string @ 0x4d#B
    "!This program cannot be run in DOS mode.$"

    Patch simples

    Vamos fazer um patch simples: alterar o "T" desta string acima de maiúsculo para minúsculo. Basicamente é só colocar à esquerda o jeito que acessamos uma determinada posição do arquivo e igualar ao que a gente quer. Sabendo que para converter maiúsculo para minúsculo na tabela ASCII basta somar 32 (0x20), podemos fazer:

    (poke) byte @ 0x4e#B = 0x74

    Perceba que fui na posição 0x4e, porque na 0x4d temos o '!' e não o 'T'. Só pra checar se funcionou:

    (poke) string @ 0x4d#B
    "!this program cannot be run in DOS mode.$"
    (poke)

    Legal né? Mas dá pra ficar melhor. O poke suporta char, então podemos meter direto:

    (poke) char @ 0x4e#B = 't'
    (poke) string @ 0x4d#B
    "!this program cannot be run in DOS mode.$"

    Por hora é só. Fica ligado aí que postarei a parte 2 em breve, onde vou mostrar mais recursos do poke que tô achando bem úteis para engenharia reversa. Até lá! ?



    Feedback do Usuário

    Participe da conversa

    Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.
    Nota: Sua postagem exigirá aprovação do moderador antes de ficar visível.

    Visitante

    • Isso não será mostrado para outros usuários.
    • Adicionar um análise...

      ×   Você colou conteúdo com formatação.   Remover formatação

        Apenas 75 emojis são permitidos.

      ×   Seu link foi automaticamente incorporado.   Mostrar como link

      ×   Seu conteúdo anterior foi restaurado.   Limpar o editor

      ×   Não é possível colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Conteúdo Similar

×
×
  • Criar Novo...