
Windows x86 PoC: Estouro de buffer baseado em pilha com shellcode personalizado no Windows 32 bits legado.
Este é um tutorial simples e autocontido sobre exploits de buffer overflow baseados em pilha para Windows 32 bits. Nenhum guia externo é necessário — tudo que você precisa está aqui.
vulnerable.c: Um programa simples com uma função gets() insegura.messageBox.asm: Um pequeno payload em assembly que executaria após o overflow.exploit.c: Um exemplo de como o overflow pode ser acionado.Este projeto ensina uma ideia central: a leitura insegura de entrada pode permitir que um atacante sobrescreva o endereço de retorno e redirecione a execução.
gets() não tem limite de tamanhoEm vulnerable.c, o programa faz isto:
char buffer[32];
gets(buffer);
O programa reserva 32 bytes para buffer e então chama gets() para ler a entrada.
O problema: gets() não verifica o tamanho do buffer.
Ele continua lendo caracteres até encontrar uma nova linha.
Se o usuário digitar 40 ou 50 caracteres, os caracteres extras transbordam para além do buffer de 32 bytes.
Quando uma função C é executada, a pilha (uma região de memória) armazena:
buffer)EBP salvo (ponteiro base da função chamadora)Visualize assim:
Lower addresses (top of stack as drawn)
[ buffer (32 bytes) ]
[ saved EBP (4 bytes) ]
[ return address (4 bytes) ]
Higher addresses (bottom)
Quando gets() transborda buffer com muita entrada, os bytes extras sobrescrevem o EBP salvo e depois o endereço de retorno.
Se criarmos cuidadosamente o overflow para colocar um endereço específico no campo do endereço de retorno, a CPU saltará para esse endereço quando a função tentar retornar.
buffer[32] na pilha.gets(buffer) para ler uma linha de entrada do usuário.gets() não tem verificação de tamanho, então escreve todos os 50 bytes no buffer.buffer e sobrescrevem o EBP salvo e o endereço de retorno.Esta é a forma mais simples de execução de código através de um buffer overflow.
messageBox.asm é um pequeno trecho de código projetado para executar após o overflow.
Ele faz o seguinte:
LoadLibraryA com a string "USER32.DLL" para garantir que a biblioteca esteja na memória.ExitProcess para encerrar o programa com segurança.O ponto chave: este é um código executável que é executado após o overflow redirecionar a execução para ele. Quando a caixa de mensagem aparece na tela, ela prova três coisas:
Em um ataque real, esse payload poderia fazer qualquer coisa: roubar dados, criar um usuário, baixar malware, etc. A caixa de mensagem é apenas uma forma visível e segura de demonstrar que a execução de código arbitrário ocorreu.
Este payload específico usa endereços de memória fixos para MessageBoxA (0x751D8830) e ExitProcess (0x7437ADB0).
Esses endereços são específicos de um sistema. O payload precisaria ser ajustado para uma versão ou sistema Windows diferente.

O Windows moderno possui vários recursos de segurança que impedem este exploit:
Para este exercício de aprendizado, desabilitamos todos eles.
Use o MSVC (Microsoft Visual C++) com flags específicas:
cl /c /GS- /W3 /Zl vulnerable.c
link /SUBSYSTEM:CONSOLE /DYNAMICBASE:NO /NXCOMPAT:NO vulnerable.obj /OUT:vulnerable.exe
Significado das flags:
/GS- desabilita a proteção contra estouro de buffer na pilha./DYNAMICBASE:NO desabilita a Randomização de Layout do Espaço de Endereço (ASLR)./NXCOMPAT:NO desabilita o DEP, permitindo que o código na pilha seja executado.Se você já possui o executável, pode desabilitar as proteções com editbin:
editbin /NXCOMPAT:NO /DYNAMICBASE:NO vulnerable.exe
vulnerable.exe.Este README explica:
gets() e por que é inseguro (sem limite de tamanho).Agora você entende todo o fluxo do exploit de buffer overflow. Leia os arquivos de código e compare-os com esta explicação para solidificar seu entendimento.
Este exemplo é apenas para aprendizado. Não use esta técnica contra sistemas que você não possui ou para os quais não tem permissão explícita para testar. O acesso não autorizado a sistemas de computador é ilegal.