Pular para o conteúdo
Todos os conceitos

Desmontar e descompilar

Um executável é código de máquina. O desmontador mostra esse código em assembly, e o descompilador tenta voltar a algo parecido com C.

Um programa compilado, como um executável de Linux (formato ELF) ou de Windows (formato PE), não traz o código-fonte: traz instruções de máquina. Para entender o que ele faz sem rodá-lo, há duas ferramentas:

  • o desmontador (disassembler) traduz cada instrução para assembly, uma forma legível do código de máquina: objdump -d -M intel programa no Linux;
  • o descompilador (decompiler) tenta reconstruir funções parecidas com C: Ghidra, IDA, Binary Ninja. O Dogbolt (abre em nova aba) roda vários descompiladores no navegador e mostra o resultado lado a lado.

Algumas instruções de x86-64 que aparecem o tempo todo:

Instrução O que faz Em Python, mais ou menos
mov eax, 0x5 copia um valor eax = 5
add eax, 1 / sub eax, 1 soma, subtrai eax += 1
cmp eax, 0x57 e je 1322 compara e pula se for igual if eax == 0x57: goto 1322
call rand chama uma função rand()
ret volta, com o resultado em eax return eax

Exemplo. Este trecho

call   rand                      ; eax = rand()
mov    edx,eax
mov    eax,edx
sar    eax,0x1f                  ; estas cinco linhas calculam
shr    eax,0x1e                  ; edx = eax % 4, com um ajuste
add    edx,eax                   ; para números negativos
and    edx,0x3
sub    edx,eax
mov    eax,edx
add    eax,0x1                   ; eax = rand() % 4 + 1
cmp    DWORD PTR [rbp-0x4],eax   ; compara com o argumento d
sete   al                        ; al = 1 se forem iguais, senão 0

quer dizer return d == rand() % 4 + 1.

o desmontador mostra call rand mov edx,eax mov eax,edx sar eax,0x1f shr eax,0x1e add edx,eax and edx,0x3 sub edx,eax mov eax,edx add eax,0x1 cmp DWORD PTR [rbp-0x4],eax sete al o que quer dizer rand() rand() % 4 com ajuste para negativos rand() % 4 + 1 d == rand() % 4 + 1 return d == rand() % 4 + 1
Cada grupo de instruções vira um pedaço da expressão: call rand é rand(), as linhas seguintes fazem o % 4, add soma 1, e cmp com sete comparam com d.

Dicas para não se perder:

  • Comece pelas strings (strings programa): mensagens como "wrong" ou "correct" apontam para a função que decide.
  • Os símbolos (objdump -t programa) dão o nome das funções e variáveis globais, mesmo quando os nomes são embaralhados.
  • main não é o começo de tudo. As funções listadas na seção .init_array (objdump -s -j .init_array programa) rodam antes de main, e programas maliciosos escondem código ali.

Se for executar o programa para conferir, faça isso numa máquina virtual ou num container sem rede: é código desconhecido.

Aparece nestes desafios