Explorando buffer overflow em C
Destrinchando o exemplo 0x320 do livro Hacking: The Art of Exploitation e vendo na prática como um strcpy sem limite sobrescreve a memória vizinha.
A velha guarda antes dos GC
Em tempos de GC nos anos 80/90 código em alto nível como C sempre era um problema se o programador não souber o que estava fazendo com a integridade dos dados pois é crucial a necessidade de alocar da maneira mais segura possível e com tradeoff bem afiado para não desenvolver um monstro e deixar tudo a cargo do compilador que eventualmente irá deixar seu binário de aplicação lerdo.
Explorando Buffer Overflow 0x320

Estou indo para a 3 vez em que leio esse livro ele é antigo eu gosto mais dele por como ele se aprofunda em programação C, ASM, ShellScript do que realmente hacking.
No capitulo 0x320 somos introduzido ao exemplo:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int value = 5;
char primeiro_buffer[8], segundo_buffer[8];
strcpy(primeiro_buffer, "um"); /* Coloca "one" em primeiro_buffer. */
strcpy(segundo_buffer, "dois"); /* Coloca "two" em segundo_buffer. */
printf("[BEFORE] segundo_buffer está em %p e contém '%s'\n", segundo_buffer, segundo_buffer);
printf("[BEFORE] primeiro_buffer está em %p e contém '%s'\n", primeiro_buffer, primeiro_buffer);
printf("[BEFORE] value está em %p e é %d (0x%08x)\n", &value, value, value);
printf("\n[STRCPY] copiando %d bytes para segundo_buffer\n\n", strlen(argv[1]));
strcpy(segundo_buffer, argv[1]); /* Copia o primeiro argumento para segundo_buffer. */
printf("[AFTER] segundo_buffer está em %p e contém '%s'\n", segundo_buffer, segundo_buffer);
printf("[AFTER] primeiro_buffer está em %p e contém '%s'\n", primeiro_buffer, primeiro_buffer);
printf("[AFTER] value está em %p e é %d (0x%08x)\n", &value, value, value);
}
Vamos destrinchar o código por partes:

- Aqui nós iniciamos uma variável value um inteiro com valor 5.
- E aqui o mais importante abrimos dois arrays de Strings-buffers com tamanho fixo de 8.
Logo se o tamanho do array é 8 então abaixo podemos colocar strings dentro deles podem até ser maior como na foto usamos a lib strcpy ( não recomendada ) e atribuímos Strings ao nosso buffer

Agora vamos para o meio do código:
![Linhas de printf [BEFORE] com os especificadores %p e %s destacados](/_astro/20260114173847.DYIqxpAU_2wUimw.webp)
Para simplificar o exemplo usa printf hardcoded para ser prático mas é possível ver tudo isso pelo GBD. Vamos as legendas
- VERMELHO: %p esse parâmetro no printf mostra aonde está o ponteiro/endereço de memoria.
- VERDE: %s esse parâmetro mostra Strings. E por ultimo vemos aquele inteiro de valor 5 só de referencia.
Se a gente rodar o código com os parâmetros 123456789 é assim que fica o output:

Aqui nada fora do normal o segundo buffer está no ponteiro com final 69c com a string ‘abcdefg’ e o primeiro buffer está no ponteiro com final 6a4 com a string ‘um’.
( Lembre desse valores vamos voltar neles )
Não é uma boa prática se referencia apenas pelo final do ponteiro mas para ser didático e como eles são do mesmo tipo de dados não vai ter muita diferença no endereço só o final.
![]()
Agora vamos para a sacanagem primeiro é um print usando strlen para contar quantos parâmetros tem nosso argv que é passado na hora de executar o código. No nosso caso é ‘1234567890’ 10 espaços.
![Saída: [STRCPY] copiando 10 bytes para segundo_buffer](/_astro/20260114180123.CzoneMyo_Z1SnUem.webp)
E embaixo usando strcpy injetamos os 10 itens para um array/buffer de apenas 8 espaços, e nos perguntamos e agora o que acontece?? ( Vamos ver na proxima foto )
Antes de mostrar o resto do codigo e o resultado nós temos que pensar como se fosse os anos 80/90 aonde não existe um GC inteligente que não deixe você rodar um codigo assim ou no caso de linguagens interpretadas python quebrar a execução sem terminar a execução.
![Linhas finais do código com os printf [AFTER]](/_astro/20260114180024.tGYt5KNs_uyNPL.webp)
Aqui é o finalzinho do código nada novo é só para nós conseguirmos ver as alterações nos valores do ponteiro.
Olha como seria uma execução normal respeitando o tamanho do array.

O valor continua normalmente no primeiro buffer e atribuímos o valor do tamanho normal ao segundo buffer.

Agora olha que incrível se a gente atribuir 10 bytes ao segundo buffer sobra os 2 bytes que literalmente sobrescreve o próximo ponteiro em memoria que pela ordem é o primeiro buffer e assim de valor string ‘um’ se torna ‘90’.
Aqui vemos como um “BUG” de um usuário mal intencionado ou apenas mal informado pode corromper não só a execução do seu programa como também pode até sobrescrever dados.
Imagina se a gente conseguisse fazer isso no banco e adicionar 90$ a uma conta com valor 0$. Eu acredito que bancos não funcionam assim, mas eu lembro que no livro mais para frente temos um exemplo estourando buffer e criando créditos de um script em C de caça-níquel que eu achei muito dahora e talvez eu traga para o blog. ( Depende do engajamento =! esforço )