Buffer Overflow
Par Israël Hallé
Adapté par Olivier Arteau
Réadapté par Israël Hallé
int hello(int a, int* b, int c) { int hello_var = 0xdeadbeef; return 0xf00; } int main() { int main_var = 0x0; int result = hello(main_var, &main_var, 0x123456); return 0; }
main
hello
int hello(int a, int* b, int c);
hello(main_var, &main_var, 0x123456);
0x7fffffff
+ +----------+
Main return address | |0x00804e00|
| +----------+
Saved base stack | |0x7fff3ed0| <--+
| +----------+ |
Main local vars | |... | |
| +----------+ |
c | |0 | |
| +----------+ |
b | |0x7fff3ebc| |
| +----------+ |
a | |0x12345678| |
| +----------+ |
hello return address | |0x00804f56| |
| +----------+ |
Saved base stack | |0x7fff3ea0| ---+
| +----------+
Hello local vars | |... |
v +----------+
0x00000000
Registre 64 bits:
RIP, RBP, RSP, RDI, RSI, RAX, RBX, RCX, RDX, R10, R8-15
Appel de fonction (Linux)
Arguments passé via registre:
RDI, RSI, RDX, RCX, R8, R9, stack
Pointeur 8 bytes
int main() { int some_var = 0; char buffer[12]; fgets(buffer, 9001, stdin); return 0; }
0x7fffffff + +---------+ | |Saved RIP| ^ | +---------+ | | |Saved RBP| | | +---------+ | | |some_var | | | +---------+ | | | | | | | | | | |buffer | + fgets(buffer, ...) v +---------+ 0x00000000
0x7fffffff + +---------+ | |AAAA | ^ | +---------+ | | |AAAA | | | +---------+ | | |AAAA | | | +---------+ | | |AAAA | | | |AAAA | | | |AAAA | | fgets(buffer, ...) v +---------+ 0x00000000
strcpy(src, dst); gets(dst); scanf("%s", dst)
x > z
z + y < z ??
0xffffffff > 0x1000 (32 bits)
0xffffffff + 1 < 0x1000 (32bits)
if ( x < 0x1000) memcpy(src, dst, x); // x = -1, woops
Examples:
pop rdi;
pop esi; pop rdx; ret;
void a(int a1, int a2, int a3) {}
void b() {}
void c(int c1, int c2) {}
8048455: 83 c4 0c add esp,0xc 8048458: 5b pop ebx
8048459: 5e pop esi
804845a: 5f pop edi
804845b: 5d pop ebp
804845c: c3 ret
Objectif: Exécuter les fonctions dans l'ordre suivant:
Suite d'outils en python très complète fais spécialement pour les CTFs et l'exploit
https://github.com/Gallopsled/pwntools
Code de base
from pwn import *
context(arch = 'amd64', os = 'linux')
r = remote('192.168.4.178', 1239)
data = r.readline() # Réception
r.send(data) # Envoie
r.interactive() # Le terminal devient l'entrée et la sortie
Baby step: Dump ./flag.txt
Bonus: Pop a shell