Como aprender exploração de binários e desenvolvimento de exploits
Para quem curte segurança da informação e baixo nível, estudar sobre exploração de binários e desenvolvimento de exploits acaba sendo um interesse natural. E nesse artigo vou recomendar alguns materiais (alguns criados por mim) para quem tem interesse em estudar sobre o assunto e precisa de um "roadmap" como guia para saber o que estudar.
Nota: os tópicos abaixo não precisam necessariamente serem seguidos nessa ordem. 😄
0. Tenha fundamentos
Creio que isso seja óbvio mas vale mencionar, só por garantia, caso você tenha caído aqui de paraquedas: é obrigatório ter fundamentos de computação antes de sequer pensar em estudar sobre exploração de binários.
Sem isso você vai ficar completamente perdido. Então estou supondo que quem está lendo isso já entende bem coisas como: programação, sistemas numéricos, complemento de 2, estruturas de dados etc.
1. Aprenda Assembly
Antes de qualquer coisa é importante ter uma boa base de Assembly para realmente conseguir entender como um binário funciona. Sem essa base é tecnicamente impossível entender como vulnerabilidades em binários ocorrem.
Além disso ao explorar binários muitas vezes também será necessário escrever shellcodes (que são códigos injetados e executados na memória de um binário), que por regra serão escritos em Assembly.
Eu escrevi um livro gratuito em Português sobre Assembly e ele é publicado online como um projeto do Mente Binária. Você pode lê-lo aqui: https://mentebinaria.gitbook.io/assembly/
Se quiser ler um conteúdo bem mais avançado, porém em Inglês e muito menos amigável para iniciantes, sugiro ler diretamente os manuais para desenvolvedores da Intel. Você pode baixá-los diretamente aqui: https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
São mais de 5 mil páginas porém você não precisa (nem sugiro) ler os manuais linearmente como um livro de romance. Ao invés disso pode usá-lo para consulta.
2. Aprenda C
Claro que você pode estudar/explorar binários escritos em outras linguagens, porém ter uma boa base de C facilita bastante o entendimento de muita coisa à respeito de binários de um ponto de vista de uma linguagem de alto nível. Além disso se você usar um descompilador, muito provavelmente ele irá gerar código em pseudo-C.
O Mente Binária tem um treinamento gratuito sobre C no YouTube: https://www.youtube.com/playlist?list=PLIfZMtpPYFP5qaS2RFQxcNVkmJLGQwyKE
3. Estude sobre sistemas operacionais
É de suma importância ter a base teórica sobre sistemas operacionais para conseguir entender apropriadamente como binários funcionam.
Para obter essa base sugiro ler o livro do Andrew S. Tanembaum Sistemas Operacionais Modernos (ISBN: 978-8543005676).
Mas também é possível encontrar material gratuito (em Inglês) na internet. Como esse daqui: https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/
4. Estude sobre compiladores
Por mais que não seja "obrigatório" você entender sobre compiladores para estudar sobre exploração de binários, entender isso vai facilitar bastante sua vida.
Sugiro o livro Compiladores: Princípios, Técnicas e Ferramentas (ISBN: 978-8588639249).
5. Estude sobre binários executáveis
É importante entender como binários são carregados e executados pelo sistema operacional. Para entender isso, sugiro estudar:
- O formato do binário no sistema operacional (ELF, PE etc.)
- Como o binário é carregado pelo sistema operacional. O código que faz isso pode ser chamado de dynamic linker, dynamic loader ou apenas de loader.
- Arquivo objeto, como vários arquivos objetos são "combinados" em um binário só e como bibliotecas estáticas são "linkadas" ao binário. Estude sobre o linker.
- Como bibliotecas dinâmicas/compartilhadas são carregadas e como seus símbolos são resolvidos pelo dynamic linker.
- Convenções de chamada e ABI (Application Binary Interface)
- Como o binário é executado. Coisas como: stack, páginas de memória, seções/segmentos, entrypoint, threads etc.
Eu já escrevi um artigo que fala sobre hook de funções no Linux. O artigo não é focado nesse tema mas ele dá uma boa base sobre como funciona o dynamic linker e o carregamento de bibliotecas dinâmicas no Linux. Leia-o aqui: https://freedev.medium.com/hook-de-fun%C3%A7%C3%B5es-no-linux-fafa51c966b1
Sobre convenções de chamada há conteúdo à respeito no meu livro de Assembly no capítulo Programando junto com C.
Sobre o formato de executáveis, veja:
6. Estude o código compilado na linguagem alvo
É imprescindível entender como o compilador gera o código em Assembly da linguagem do binário explorado (que na grande maioria das vezes será em C). Você pode usar ferramentas online como o godbolt mas você também pode (e é o que eu faço) simplesmente compilar o código e ler o Assembly de saída. Com o GCC isso pode ser feito assim:
$ gcc example.c -o example.s -S
Onde a opção -S
faz com o que o GCC apenas compile o código, sem fazer o assembling e linkagem. No arquivo de saída ele escreverá o Assembly. Você também pode usar a opção -masm=intel
para usar sintaxe da Intel (por padrão usa sintaxe AT&T) e a opção -fno-asynchronous-unwind-tables
para desabilitar a geração de diretivas de depuração que o GCC insere no código, assim melhorando a leitura. Ficando algo como:
$ gcc example.c -o example.s -S -masm=intel -fno-asynchronous-unwind-tables
7. Estude sobre alocação dinâmica de memória
A gigantesca maioria das vulnerabilidades em binários reportadas no CVE são relacionadas a memória. Então entender como a memória de um binário funciona é essencial para o entendimento da gigantesca maioria das vulnerabilidades.
Já escrevi um artigo explicando como isso funciona na linguagem C: https://www.mentebinaria.com.br/artigos/entendendo-malloc-e-heap-na-glibc-r70/
Consulte as referências do artigo para mais materiais à respeito.
8. Aprenda sobre depuradores e como usar eles
É muito bom entender como depuradores funcionam, e é obrigatório aprender a usar um.
No meu livro de Assembly tem um capítulo exclusivo para falar sobre depuração de código. Além de dar uma boa base de como depuradores funcionam, também ensina a usar o GDB. E sugiro ver a extensão do GDB pwndbg que foi feito especificamente para desenvolvimento de exploits.
Também existe o radare2 que é uma framework de ferramentas para engenharia reversa, incluindo um depurador que é excelente para esse tipo de tarefa. O Mente Binária tem um treinamento gratuito ensinando a usar o radare2.
Veja aqui: https://www.youtube.com/playlist?list=PLIfZMtpPYFP7P50b0IKfB-wbjZr7yZxwY
9. Estude sobre falhas e técnicas de exploração
Finalmente após ter toda a base é importante também estudar as próprias falhas de segurança presentes em binários, proteções que esse binário pode ter (como ASLR ou stack canary, por exemplo) e técnicas de exploração para aprender a burlar essas proteções.
Para isso o Mente Binária também tem um treinamento gratuito bem aqui: https://www.youtube.com/playlist?list=PLIfZMtpPYFP4MaQhy_iR8uM0mJEs7P7s3
Nota: também sugiro estudar sobre ROP (Return-oriented Programming) e ROP-chain. Não tenho certeza se esse tópico é abordado no treinamento acima.
Além disso também sugiro ler todas as edições da H2HC Magazine. Apesar da revista não ser focada exclusivamente nesse tema, tem bastante conteúdo à respeito e também sobre engenharia reversa.
Leia aqui: https://github.com/h2hconference/H2HCMagazine
Também sugiro consultar o Common Weakness Enumeration: https://cwe.mitre.org/
EDIT: como foi me recomendado no LinkedIn, também sugiro aqui conteúdo produzido pelo Hélvio Júnior (M4v3r1cK) sobre desenvolvimento de exploits.
- Vídeos: https://www.youtube.com/playlist?list=PLClhW-HXRs75E-msoB1NbC62P0DA9oa2i
- Artigos: https://www.helviojunior.com.br/category/it/security/criacao-de-exploits/
Na playlist acima há, inclusive, conteúdo sobre ROP. 😄
10. Pratique
Existem alguns desafios que você pode fazer para praticar a exploração de binários. Inclusive eu mesmo fiz alguns desafios e publiquei no meu GitHub.
O repositório: https://github.com/Silva97/exploit-me
Mas você também pode ver o Pwnable que tem muitos desafios sobre exploração de binários. Veja: https://pwnable.tw/