Vocรช vai praticar engenharia reversa pela primeira vez.
“Engenharia reversa”, na รกrea de T.I. refere-se ร engenharia reversa de software, que, a grosso modo, รฉ a prรกtica de entender o funcionamento de um software alheio, “nos mรญnimos detalhes”.
Esse tutorial รฉ uma breve introduรงรฃo ao uso do debugger x64dbg, que รฉ prรฉ-requisito para o prรณximo tutorial.
Esse tutorial foi escrito para os iniciantes, o intuito รฉ lhe preparar para o prรณximo tutorial: Debugando um programa crackme; observe que um รฉ complemento do outro.
Programas “crackme” sรฃo softwares com algum tipo de desafio, como, por exemplo, descobrir uma senha de acesso ao prรณprio crackme.
O maior objetivo disso tudo, รฉ mostrar um pouco desse mundo para pessoas que tรชm interesse em “baixo nรญvel”, mas nรฃo sabem se “isso รฉ para elas”.
Quero lhe ajudar a ter o “primeiro gostinho” desse mundo…
Lista de Conteรบdo
O que รฉ um Debugger
Debugger รฉ um software que serve para “debugar” e testar programas.
“Debugar” รฉ o processo de procurar bugs.
Bugs sรฃo erros ou problemas em um software.
E “testar”, aqui, se define como “fazer oque quisermos com o software”.
O Debugger lhe fornece acesso ao programa compilado.
Em um debugger, vocรช vai ter acesso aos seguintes recursos:
- Valores das suas variรกveis em memรณria – Mapa de memรณria
- Suas linhas de cรณdigo transformadas em instruรงรตes Assembly
- Mรณdulos (dll’s e lib’s) usados
- Threads e Handles
Sobre a Nomenclatura “x64dbg”
Nรฃo se confunda: o nome do programa como um todo รฉ x64dbg.
Ele possui dois APLICATIVOS que sรฃo chamados x64dbg e x32dbg.
Vocรช sempre deve saber qual dos dois deve usar para debugar um programa em especรญfico, dependendo da plataforma para a qual o programa foi compilado:
- o aplicativo chamado x64dbg serve para debugar programas de 64 bits.
- o aplicativo chamado x32dbg serve para debugar programas de 32 bits.
Caso vocรช nรฃo saiba se o seu programa รฉ de 32-bits ou se รฉ de 64-bits, abra o link:
Como saber se um programa รฉ 32 ou 64 bits no windows.
No tutorial a seguir, quando eu disser “x64dbg”, eu estarei me referindo ao programa como um todo, e nรฃo ao aplicativo especรญfico.
Antes de comeรงar
-
Vou trabalhar apenas com Assembly de x86_x64:
Assembly nรฃo รฉ uma linguagem de programaรงรฃo comum, como C, que
vocรช aprende e sai criando programas para “qualquer coisa”:
hรก diversos processadores, e cada um possui uma arquitetura,
que vai dizer como as instruรงรตes sรฃo nomeadas e como vรฃo
funcionar, que dita o nome e funcionamento dos
registradores, etc.
Mais sobre: ISA-Instruction Set Architecture -
Nรฃo รฉ esperado nenhum conhecimento prรฉvio sobre debuggers ou Assembly.
-
ร esperado conhecimento bรกsico em programaรงรฃo, e processo de compilaรงรฃo.
-
Conhecimento sobre fundamentos da computaรงรฃo lhe ajudarรฃo a entender melhor o que se passa aqui. (Nota: Vocรช pode usar um debugger para reforรงar os estudos dos fundamentos da computaรงรฃo, jรก que, dessa forma, irรก ver as coisas acontecendo na prรกtica).
-
O bรกsico sobre sistemas numรฉricos รฉ esperado.
Espero lhe dar um overview de como รฉ usar um debugger, mas tenha em mente que tรณpicos extremamente importantes estรฃo sendo deixados de lado para nรฃo lhe “inundar” de informaรงรตes no inรญcio. Entenda isso como um “Quick Overview”.
Se estiver procurando obter os fundamentos da computaรงรฃo, confira os links deixados na parte final.
Baixando o x64dbg
- Vรก ao site oficial: x64dbg.com
- Clique em Download
- Vocรช serรก redirecionado ao site da Sourceforge. Clique em Download Latest Version
“Instalando” o x64dbg
- Extraia o arquivo zip. Vocรช pode criar uma pasta em qualquer lugar para armazenรก-lo.
- Abra a pasta extraรญda
- Vรก em: release/x32, ache o aplicativo x32dbg e crie um atalho na รกrea de trabalho
- Vรก em: release/x64, ache o aplicativo x64dbg e crie um atalho na รกrea de trabalho
Abrindo o x64dbg
Para abrir qualquer programa no x64dbg:
- Abra o x64dbg
- Clique em Arquivo -> Abrir (ou clique em F3)
- Alternativa: Arraste o programa para um dos atalhos do x64dbg
- Para abrir um programa que estรก rodando, abra o debuger, clique em Arquivo -> Anexar/Attach e escolha o programa.
Mapeando as partes mais usadas da Interface Grรกfica
Botรตes de controle do Debugger
รrea com os botรตes de controle do Debugger. Clique em Debug (ao lado de Exibir) para ver todos os nomes e atalhos dos botรตes nessa seรงรฃo.
- รcones, da esquerda para a direita:
- Abrir Arquivo
- Recarregar programa
- Fechar programa que estรก carregado
- Rodar programa carregado
- Pausar programa carregado
- Step Into: anda, de instruรงรฃo em instruรงรฃo, e entra nas instruรงรตes
call
: instruรงรตescall
chamam outras funรงรตes. “Entrar nelas” quer dizer ir atรฉ a funรงรฃo. - Step Over: anda, de instruรงรฃo em instruรงรฃo, e NรO entra nas instruรงรตes
call
Nรฃo vou comentar sobre os outros botรตes, para saber sobre eles:
https://help.x64dbg.com/en/latest/gui/views/Trace.html
https://help.x64dbg.com/en/latest/introduction/ConditionalTracing.html
Atalhos para Funcionalidades
Atalhos para algumas funcionalidades do x64dbg (nรฃo entrarei em detalhes).
Vou mencionar apenas o quinto, da esquerda para a direita, que รฉ o รญcone de favoritos.
Quando vocรช quiser salvar alguma localizaรงรฃo de instruรงรฃo, use CTRL+D, que a instruรงรฃo selecionada serรก salva nos favoritos. Clique no atalho mencionado para ser direcionado aos favoritos.
Janelas mais usadas
Nessa parte do x64dbg, vocรช tem todas as janelas de funcionalidades do programa.
Sรณ marquei na caixa amarela as que eu vou estar comentando. Para vocรช comeรงar a usar o programa, acredito que sรณ precisa dessas janelas. Mas nรฃo deixe de aprender todas, caso queira prosseguir nos estudos.
Clicando em exibir (ao lado de Arquivo, canto superior esquerdo) vocรช pode habilitar as janelas que nรฃo estiverem aparecendo, e tambรฉm pode ver os atalhos para cada uma delas.
Na imagem acima, se encontra a janela CPU, que serรก comentada no final desta parte sobre janelas.
- Janela Breakpoints: breakpoints sรฃo
pontos de parada, locais em que o programa vai parar
obrigatoriamente. Logo falaremos mais sobre breakpoints.
E nessa janela vocรช tem acesso aos breakpoints que estรฃo
setados no programa todo. Aqui vocรช pode manipular
breakpoints, habilitando-os, desabilitando-os, ou mesmo
removendo-os, e รฉ atรฉ possรญvel editรก-los. Clicando em um
deles, vocรช serรก direcionado atรฉ o local em que ele estรก
setado, na janela CPU.- Janela de Sรญmbolos (Modules): essa รฉ
uma janela de extrema importรขncia para algumas
atividades, jรก que ela nos mostra os mรณdulos importados
pelo programa, inclusive o mรณdulo do prรณprio programa.- Janela Referรชncias: Aqui temos as
referรชncias, que procuramos da seguinte maneira: Dentro
da janela CPU, clique com o botรฃo direito do mouse, bem
no final vocรช vai encontrar “Pesquisar por” e “Encontrar
referรชncia aos”:
Os resultados das pesquisas feitas por essas opรงรตes serรฃo mostrados na janela **Referรชncias**.- Janela Mapa de Memรณria: Como o nome
diz, รฉ um mapa da memรณria do programa todo.
Vocรช pode ver onde um determinado endereรงo se
encontra da seguinte maneira:- Janela CPU: Nos mostra tudo o que
estamos vendo na imagem “mapeada” acima, e por essa ser
a janela principal, todos os comentรกrios ร s marcaรงรตes
com cores a seguir, serรฃo sobre ela.
Mapeando a janela CPU
Vamos passar a maior parte do tempo nessa janela, ela รฉ a janela principal do x64dbg.
Coluna de Endereรงos
Na primeira coluna da grande รกrea, nรณs temos os endereรงos de memรณria (endereรงos de memรณria virtual, Virtual Address – VA).
A marcaรงรฃo verde nos mostra qual a prรณxima instruรงรฃo a ser executada. O destaque em dourado รฉ uma instruรงรฃo marcada como “favoritos” usando CTRL+D.
Para saber mais sobre endereรงos de memรณria: https://learn.microsoft.com/pt-br/windows/win32/memory/virtual-address-space
Coluna de Opcodes
Na segunda coluna da grande รกrea, nรณs temos os Opcodes, que sรฃo cรณdigos de operaรงรฃo, eles ditam uma operaรงรฃo a ser executada pelo processador (por isso do nome OPeration Code);
Aqui estรฃo em hexadecimal. Cada opcode รฉ usado para formar uma instruรงรฃo Assembly. Os opcodes tambรฉm sรฃo chamados de Cรณdigo de Mรกquina, e isso รฉ oque chamamos de Assembly.
Por exemplo, temos a instruรงรฃo chamada add
, que soma dois operandos.
Em Opcode ela รฉ equivalente a um dos seguintes, dependendo do contexto (na imagem, coluna Opcode, lado esquerdo):
Isso รฉ a tabela que nos mostra como a instruรงรฃo add
รฉ montada em arquitetura Intel x86_x64.
Repare as colunas 64-bit Mode, para programas de 64 bits e Compat/Leg Mode para programas de 32 bits. Para saber mais, clique no link:
Manual da Intel para desenvolvedores.
Vamos ver qual opcode obtemos compilando um programa para um sistema de 64 bits:
// Programa em C
int main(){
int primeiro_numero = 3;
int segundo_numero = 2;
int resultado_da_soma;
resultado_da_soma = primeiro_numero + segundo_numero;
return 0;
}
Repare na linha selecionada: o programa estรก com o opcode 03 /r
.
Coluna de Instruรงรตes Assembly
Na terceira coluna da grande รกrea, nรณs vemos as instruรงรตes Assembly. Falamos sobre elas anteriormente, na coluna dos Opcodes.
Coluna de Comentรกrios
Na quarta coluna da grande รกrea, temos a seรงรฃo de comentรกrios.
Podemos ter comentรกrios automรกticos, por exemplo, no caso de instruรงรตes que estรฃo carregando uma string, vamos ter a prรณpria string como comentรกrio. Tambรฉm podemos adicionar nossos comentรกrios, basta clicar na tecla ;
e escrever algo, ao terminar รฉ sรณ dar enter
.
Coluna de Registradores
Aqui, no lado extremo direito, temos os registradores e seus conteรบdos.
Os registradores sรฃo espaรงos de memรณria dentro do processador, e funcionam como variรกveis temporรกrias.
Hรก registradores de propรณsito geral, que sempre vรฃo ser usados para coisas diversas:
Registradores de Propรณsito Geral x64:
- RAX
- RBX
- RCX
- RDX
- RSI
- RDI
- R8, R9, R10, R11, R12, R13, R14 e R15. Em x64 temos esses oito registradores a mais.
Registradores de Propรณsito Geral x86:
Em teoria esses registradores podem ser usados para qualquer coisa, mas hรก situaรงรตes em que RDI/EDI e RSI/ESI sรฃo usados de forma exclusiva por certas instruรงรตes.
Tambรฉm hรก registradores que servem para armazenar coisas especรญficas.
Vou mencionar apenas os que considero mais importantes para o momento.
Para saber mais, nรฃo deixe de ler:
How many registers does an x86-64 cpu have
Alguns Registradores de uso especรญfico (na ordem: x64/x86):
- RSP/ESP – Ponteiro para o topo da stack/pilha
- RBP/EBP – Ponteiro para a base da stack/pilha
- RIP – Ponteiro para a prรณxima instruรงรฃo a ser executada. IP – Instruction Pointer (vai ser mostrado como RIP em x64, e EIP em x86). ร por esse registrador que nรณs sabemos onde estamos dentro do programa, durante o fluxo de execuรงรฃo.
Como ele tem o valor da prรณxima instruรงรฃo a ser executada, estamos exatamente “um passo” atrรกs dele.
*Tambรฉm deixei de mencionar os registradores que lidam com float’s. Mais sobre: https://my.eng.utah.edu/~cs4400/sse-fp.pdf
Stack
Abaixo dos registradores, nรณs temos a Stack, tambรฉm chamada de pilha (em pt-br).
A stack/pilha รฉ um segmento de memรณria que opera com uma estrutura de dados de pilha (stack), por isso do nome.
Aqui nรณs temos os valores de nossas variรกveis locais. Enquanto vocรช estiver dentro de uma funรงรฃo, seus dados locais vรฃo estar ali.
A coluna da esquerda representa o endereรงo da stack/pilha, e a coluna da direita nos mostra o valor armazenado naquele endereรงo.
A stack/pilha รฉ uma estrutura de dados do tipo LIFO – Last In First Out, ou รบltimo a entrar, primeiro a sair. Todo mundo costuma usar o exemplo de uma pilha de pratos para explicar a stack: em uma pilha de pratos, qual prato vocรช tira PRIMEIRO? O รบltimo empilhado, ou o primeiro, que deu inรญcio a pilha?
ร lรณgico que, primeiro, vocรช tira o que estรก no topo, LIFO…
Lembra dos registradores RSP e RBP? Entรฃo, รฉ aqui que eles entram: RSP aponta para o topo da pilha, e RBP aponta para a base da pilha.
ร assim que o layout de memรณria de uma funรงรฃo รฉ delimitado e manipulado, atravรฉs desses registradores.
E isso รฉ que รฉ chamado “stackframe”, รฉ o espaรงo de memรณria reservado para uma funรงรฃo.
Veremos um pouco mais sobre isso em “Noรงรตes bรกsicas sobre funรงรตes em Assembly”.
Dump de Memรณria
Ao lado esquerdo dos registradores, nรณs encontramos um dump da memรณria em hexadecimal.
Vocรช pode clicar com o botรฃo direito do mouse em qualquer instruรงรฃo, e seguir tanto o endereรงo dela, quanto algum endereรงo que ela esteja operando. Tambรฉm รฉ possรญvel fazer o mesmo nos registradores.
Voltando a imagem do Dump, a coluna mais a esquerda mostra o endereรงo respectivo aos dados hexadecimais nas quatro colunas seguintes (quatro colunas na configuraรงรฃo padrรฃo).
Na รบltima coluna, mais a direita, temos a representaรงรฃo ASCII dos dados em memรณria.
Tambรฉm podemos alterar a visualizaรงรฃo dos dados do dump: alรฉm de hexadecimal, ele nos mostra os dados como Inteiros e Floats. Basta clicar com o botรฃo direito do mouse na รกrea de dump e clicar em “Integers” ou em “Floats”.
Na parte de cima nรณs temos vรกrios dumps, para os quais vocรช pode direcionar a visualizaรงรฃo de algo que lhe interessar. Tambรฉm temos outras funรงรตes, mas nรฃo vou mencionรก-las aqui. Para saber mais, leia: Watch Control
Status do programa debugado
Aqui, no canto inferior esquerdo, nos รฉ mostrado em que situaรงรฃo o programa debugado se encontra, como, por exemplo, se ele estรก em execuรงรฃo, ou pausado, e se estiver pausado, o motivo.
Rodando primeiro programa no x64dbg
Bom, agora que vocรช jรก sabe como abrir o seu programa no x64dbg, vamos aprender mais algumas coisas antes de seguirmos para o prรณximo tutorial.
Abra qualquer programa com o x64dbg, de preferรชncia um feito por vocรช mesmo.
Em seguida, abra a janela (em vermelho) da seguinte maneira: Clique em Options -> Preferรชncias
E aรญ desmarque a caixinha apontada pela seta, System Breakpoint. Assim vocรช desativa alguns breakpoints “desnecessรกrios” para nรณs agora (para saber mais sobre System Breakpoints: https://www.youtube.com/watch?v=vdyyg72tc2w).
Ao abrir o programa, ele vai ser mostrado na barra de tarefas somente quando for carregado. Eu estou abrindo um programa simples, ele jรก carrega a janela de primeira.
Se for um programa mais complexo, ele vai carregar outras coisas antes de poder desenhar a janela. Basta clicar em RUN (F9) atรฉ parar em um breakpoint: entry breakpoint, que vocรช vรช ao lado do status do programa:
Sempre acompanhe o status do programa na barra inferior, ao lado do PAUSE.
Vamos tentar encontrar nossas funรงรตes. Se o programa nรฃo foi “cuidadosamente estripado”, achar a funรงรฃo principal, main, nรฃo รฉ tรฃo difรญcil.
Vรก atรฉ a janela Sรญmbolos, que possui nossos mรณdulos, encontre o mรณdulo principal (que possui o nome do prรณprio programa rodando), clique nela e seja direcionado para o inรญcio desse mรณdulo:
Assim , se o programa nรฃo for extremamente complexo, vocรช vai encontrar a main.
Dica: os programas compilados para x86, geralmente mantรชm a funรงรฃo main no topo, entรฃo assim que o programa parar no entry breakpoint, vรก ao topo das instruรงรตes que vocรช encontrarรก a main.
Encontrando Strings
Outro modo de encontrar a main, รฉ quando ela chama alguma string.
Para encontrar as strings dentro do programa รฉ fรกcil:
na janela CPU, clique com o botรฃo direito do mouse no meio da janela, vรก atรฉ
Pesquisar Por -> All User Modules -> Referรชncias String.
Carregando as strings na janela de referรชncias, procure pela que vocรช sabe que รฉ usada na main, e aรญ clique nela. Vocรช serรก redirecionado para o local em que ela aparece no programa, na janela CPU. O inรญcio da funรงรฃo, รฉ o inรญcio da main, a nossa funรงรฃo principal, que o programador escreveu.
Noรงรตes bรกsicas sobre funรงรตes em Assembly
Toda funรงรฃo em Assembly possui um prรณlogo e um epรญlogo.
Normalmente as funรงรตes possuem as seguintes instruรงรตes no inรญcio (o prรณlogo):
push ebp
mov ebp, esp
E a seguinte instruรงรฃo no final (o epรญlogo):
ret
Lembre-se que as instruรงรตes em x64 utilizam os registradores rsp
e rbp
No inรญcio, o programa salva o valor que estรก no registrador EBP/RBP com push ebp
. Esse valor รฉ o endereรงo da base da stack/pilha da funรงรฃo anterior; lembre-se que a stack/pilha possui os valores das variรกveis locais, e que as variรกveis locais sรฃo variรกveis declaradas e/ou definidas dentro das funรงรตes (somente as variรกveis definidas, isto รฉ, variรกveis com valores, vรฃo ser colocadas na stack/pilha).
Apรณs salvar o valor de EBP, um novo stackframe รฉ iniciado; em outras palavras, um novo local (“local” se refere a um bloco de memรณria na stack) para guardar as variรกveis dessa nova funรงรฃo รฉ “delimitado”. Isso รฉ feito com mov ebp, esp
.
Tenha em mente que, para cada nova funรงรฃo, um novo stackframe รฉ mapeado e alocado para ela, assim, cada funรงรฃo lida somente com os valores das suas prรณprias variรกveis.
Vocรช vai precisar saber sobre calling conventions para entender como os argumentos sรฃo passados para as funรงรตes, eu nรฃo irei explicar isso aqui, entรฃo se quiser saber mais, nรฃo deixe de ler:
https://en.wikipedia.org/wiki/X86_calling_conventions
Calling Convention Stack Frame
Atalhos รบteis
Clicando com o botรฃo direito do mouse no meio da janela CPU, vรก atรฉ “Ir Para“, lรก vocรช terรก acesso as seguintes funcionalidades (decore os atalhos):
Os atalho mais รบteis de todos sรฃo o primeiro e o segundo:
- RIP
*
: ele te direciona para onde o seu programa estรก no momento, seguindo o RIP. - Anterior
-
: Volta para a instruรงรฃo executada anteriormente.
Final: Consideraรงรตes e Recomendaรงรตes
Nรฃo deixe de fazer o tutorial prรกtico com o x64dbg [COLOCAR LINK QUANDO PRONTO].
Os debuggers sรฃo poderosos e รบteis para as mais diversas atividades na รกrea da computaรงรฃo. O x64dbg faz muitas coisas, vรกrias delas eu deixei de mencionar aqui, como, por exemplo, alterar as instruรงรตes de um programa, para modificar sua funcionalidade.
Quanto mais vocรช for estudando sobre tรณpicos de engenharia reversa, mais os debuggers se mostrarรฃo รบteis. Vocรช irรก se aprofundar nas diversas funcionalidades conforme a sua necessidade.
Um site muito bom para continuar praticando a leitura de Assembly รฉ o seguinte: godbolt.org Selecione uma linguagem, como C ou C++, escolha um compilador, e comece os testes.
Caso esteja procurando obter os fundamentos da computaรงรฃo, eu sugiro que vocรช confira os links desta รกrea:
Guia de estudos: https://www.mentebinaria.com.br/studying-materials/basico-para-computacao/
Tutorial Gratuito de Assembly pt-br: https://github.com/andreluispy/assembly4noobs
Livro Gratuito de Assembly em pt-br: https://mentebinaria.gitbook.io/assembly/
Fundamentos da Engenharia Reversa pt-br: https://mentebinaria.gitbook.io/engenharia-reversa/
Curso de Engenharia Reversa Online (vรญdeo pt-br): https://www.youtube.com/playlist?list=PLIfZMtpPYFP6zLKlnyAeWY1I85VpyshAA
Livro Em Inglรชs para iniciantes em Engenharia Reversa en: https://beginners.re/
[fluentform id="8"]