Introduzione alle tecniche di
Exploit
IFOA
24 Luglio 2003
Luigi Mori
Network Security Manager
Intrinsic
lm@intrinsic.it
Agenda
• Memory layout di un processo
Win2000
• Stack Frame
• Exploit
• Shellcode
• Note finali
Processo Win2000
• Lo spazio di indirizzamento è flat
• Suddiviso in due regioni principali
– System space (Kernel)
– User space (Programma e DLL)
• All’interno dello user space la memoria
può essere suddivisa in ulteriori sezioni
– Codice
– Stack
– Dati inizializzati
– Dati non inizializzati
Memory layout
User Space
(Programma, DLL, Dati, Stack,
Ambiente)
System Space
(Kernel, Executive, Driver)
0x80000000
L’interfaccia fra i due spazi è la NTDLL.DLL
User Space
• Diviso in una serie di regioni
• Ogni regione ha dei permessi di
accesso
– codice: XR
– dati non inizializzati: RWX
– dati inizializzati: RX
– stack: RWX
Esempio User Space
stack code
dati
init
dati code
dati
init
dati
prova.exe NTDLL.DLL
Stack Frame di una funzione C
int
f(char *s)
{
char c[16];
int i;
i = 1;
…
return i;
}
push ebp
mov ebp, esp
sub esp,20h
mov [ebp-20],1
...
Stack Frame di una funzione C
Registri salvati
Variabili locali
Frame ptr
Ret Address
Argomenti
• Registri Salvati. Sono i registri
salvati dalla calling conv
usata
• Frame pointer. E’ il valore
salvato del registro usato
per indirizzare le variabili
locali (EBP)
• Ret Address. Indirizzo di
ritorno
• Argomeni. Argomenti
passati
Stack Frame di f
s
Ret Address
Frame ptr
c
i
• Nessun registro salvato
• Le variabili locali sono
contigue
Agenda Exploit
• Buffer overflow
– classico
– frame pointer
– heap
• Format String Vulnerabilities
• Integer overflow
Buffer overflow classico
• Il padre di tutti i buffer overflow
• Ideato da Aleph1 nell’articolo
“Smashing the stack for fun and
profit” nella e-zine Phrack #49
Funzione f
int
f(char *s)
{
char c[16];
int i;
i = 1;
strcpy(c,s);
return i;
}
• La funzione strcpy copia i
dati da s in c senza
controllare la dimensione
• Se la stringa puntata da s
è più lunga di 16 byte ci
sono dei problemi
Problemi per f
• Se s è abbastanza
lunga può andare a
sovrascrivere frame
pointer, return address
e altro ancora
• Questo può essere
sfruttato da un
attaccantea
Ret Address
Frame ptr
c
i
Problemi per f
• Se s è abbastanza
lunga può andare a
sovrascrivere frame
pointer, return address
e altro ancora
• Questo può essere
sfruttato da un
attaccantea
Ret Address
Frame ptr
c
i
s
Attacco ad f
• Posso costruire s in
modo che la parte
che va a sovrascrivere
l’indirizzo di ritorno
punti all’interno dei
dati iniettati
• Quando f finsice il suo
lavoro invece di
saltare indietro nella
funzione chiamante
salta nel buffer
a
Ret Address
Frame ptr
c
i
Attacco ad f
• Posso costruire s in
modo che la parte
che va a sovrascrivere
l’indirizzo di ritorno
punti all’interno dei
dati iniettati
• Quando f finsice il suo
lavoro invece di
saltare indietro nella
funzione chiamante
salta nel buffer
a
Ret Address
Frame ptr
c
i
s
Nuovo ret
Anatomia di un exploit
Cuscino di NOP
Addr codice
payload
a
Ret Address
Frame ptr
c
i
Anatomia di un exploit
• Il cuscino di NOP iniziale serve per
non dover essere eccessivamente
precisi nello specificare l’indirizzo di
jump
• Il creatore dell’exploit deve prestare
attenzione ai check fatti sull’input
(alfanumerico, solo 7bit, …)
• Il payload è la parte dell’exploit che
compie l’azione vera e propria
Frame pointer overflow
• Buffer overflow in cui è possibile
sovrascrivere solo il primo byte del
frame pointer
• Vengono detti off-by-one
• Spesso sono dovuti a differenti
implementazioni di una funzione su
più piattaforme (strncpy su Linux,
Win32, …)
Frame pointer overflow
• Solamente un byte del
frame pointer viene
sovrascritto
• Dovuti ad errori nel
controllo della lunghezza
(<= invece di un < stretto)
Registri salvati
Variabili locali
Frame ptr
Ret Address
Argomenti
Frame pointer overflow
• Solamente un byte del
frame pointer viene
sovrascritto
• Dovuti ad errori nel
controllo della lunghezza
(<= invece di un < stretto)
Registri salvati
Variabili locali
Frame ptr
Ret Address
Argomenti
Come è possibile ?
g()
{
…
f();
…
}
• La funzione f è attaccabile
• Molte funzioni hanno all’inizio un
codice del tipo:
• Al termine invece:
• Se dentro f il frame pointer viene
cambiato al termine di g viene
modificato lo stack pointer
push ebp
mov ebp, esp
mov esp, ebp
pop ebp
Difese da attacchi allo stack
• Stack non eseguibile
– Al segmento di stack vengono rimossi i
diritti di esecuzione, i dati presenti sullo
stack non possono essere eseguiti
– Alcuni compilatori usano lo stack per
creare trampolini verso altro codice
– Il codice per l’exploit potrebbe già
trovarsi all’interno del programma è
sufficiente passargli i dati giusti
Difese da attacchi allo stack
• Canarino
– Il compilatore viene modificato in
modo da inserire un valore tra Frame
Pointer e variabili in entrata ad ogni
funzione
– All’uscita da ogni funzione si controlla
se il canarino è ancora vivo (intatto)
– Il canarino può essere un valore
casuale oppure semplicemente 0
Difendersi con il canarino
• Il canarino viene inserito in
entrata alla funzione
• Viene controllato in uscita
• Se non è intatto significa
che è stato sovrascritto e
l’esecuzione viene interrotta
• Si evita di eseguire il codice
dell’exploit
Registri salvati
Variabili locali
Frame ptr
Ret Address
Argomenti
Canarino
Heap-based overflow
• Fino ad ora abbiamo visto solo
attacchi allo stack
• E’ possibile anche attaccare buffer
presenti nell’area dati (heap)
Heap-based overflow
• Una volta sovrascritto il
buffer è necessario
trovare un modo per
saltarci dentro
• L’idea è di
sovrascrivere un
puntatore al codice in
modo da farlo puntare
dentro al buffer
buffer
altre variabili
codice
Heap-based overflow
• Una volta sovrascritto il
buffer è necessario
trovare un modo per
saltarci dentro
• L’idea è di
sovrascrivere un
puntatore al codice in
modo da farlo puntare
dentro al buffer
buffer
altre variabili
codice
exploit
Esempio di programma affetto
void
g()
{
}
void
main(int argc, char **argv)
{
static struct {
char buffer[10];
void (*f)();
} s;
s.f = g;
argv++;
strcpy(&s.buffer,*argv);
printf("%08x %08xn",
&s.f, &s.buffer);
s.f();
}
• Dando un
argomento
abbastanza lungo
è possibile
sovrascrivere il
puntatore a
funzione f e
direttore il flusso
del programma
Situazioni tipiche di exploit
• Classi C++ (mix di puntatori a
funzioni e dati)
• Funzioni di libreria che contengono
puntatori statici a funzioni (atexit, …)
• ...
Format String Exploits
• Sfruttano funzioni tipo printf
• Quando la format string può essere
influenzata dall’utente è possibile
che sia presente una Format String
Vulnerability
printf(format_string, arg1, arg2, ….)
Format String Functions
• Le funzioni tipo printf accettano una
format string ed un numero variabile
di argomenti
• In output viene generata una
versione trasformate della format
string
Esempio
void
f()
{
int i;
i = 5;
printf(“prova %d %08xn”,
i, &i);
}
output
prova 5 00130000
Format functions stack frame
• Il chiamante conosce il
numero di argomenti
passati, il chiamato no
• Il primo argomento è la
format string
• Il chiamato deduce dalla
format string il numero di
argomenti
Registri salvati
Variabili locali
Frame ptr
Ret Address
Arg1
Frmat str addr
...
Esempio funzione vulnerabile
void
f(char *s)
{
char buff[512];
char outbuff[512];
sprintf(buff,”Err: %s”,
s);
sprintf(outbuff,buff);
}
• Con il primo sprintf
viene creata la
format string per il
secondo
• Passando alla
funzione una stringa
che funzioni da
format string
possiamo
sovrascrivere lo stack
Esempio di
format string exploit
• Passo alla funzione f una stringa tipo
“%s%s%s%s”
• Dopo il primo sprintf ho nel buffer
buff la stringa
• Nel secondo sprintf questa stringa
viene usata come format string
“Err: %s%s%s%s”
Esempio di format string
exploit
• La funzione sprintf si aspetta
di trovare 4 argomenti sullo
stack (uno per ogni %s)
• Quando cerca di accedere
a questi argomenti va a
toccare il frame della
funzione chiamante, in
questo caso f
• sprintf andrà a stampare
valori “casuali” della
memoria del processo. Crash
del programma
Registri salvati
Variabili locali
Frame ptr
Ret Address
Frmat str addr
Frame di f
Eseguire codice arbitrario
• Sfruttando una format string
vulnerability è possibile anche far
eseguire codice arbitrario al
processo
• Il procedimento è abbastanza
delicato ma lo scopo ultimo è
sempre lo stesso: far saltare
l’esecuzione all’interno del buffer
riempito con il codice dell’exploit
Integer overflow
• Sono gli errori più difficili da sfruttare
• Sfruttano una delle caratteristiche
fondamentali dell’aritmetica dei
calcolatori
Interi e linguaggio C
• Nel linguaggio ci sono diversi tipi di interi
• Ogni tipo di intero è rappresentato da
una variabile con un certo numero di bit
• Esempio su piattaforma Win32
– int è un intero a 32 bit
– short è un intero a 16 bit
• Ogni intero può avere un valore massimo
pari a 2^(dimensione in bit)-1
Esempio di funzione
vulnerabile
int
catvars(char *buf1, char *buf2,
int len1, int len2)
{
char buff[256];
if ((len1+len2) > 256)
return -1;
memcpy(buff,buf1,len1);
memcpy(buff+len1,buf2,len2);
…
return 0;
}
Il controllo (len1+len2) non
tiene conto di un possibile
integer overflow. Al memcpy
è quindi possibile
sovrascrivere lo stack e si
ricade nel classico stack-
based buffer overflow
Idea base degli exploit
• Tutti le tecniche di exploit che abbiamo
visto si dividono in due parti:
– iniezione del codice arbitrario in un buffer
– dirottamento del programma verso quel
buffer
• E’ il dirottamento la parte più delicata e
che differenzia una tecnica dall’altra
Codice iniettato
• Viene detto il payload dell’exploit
• E’ il codice che ha il compito di
compromettere il sistema
• Scrivere questo codice è complesso
e delicato
• In genere il suo obbiettivo è quello
di aprire una porta di accesso al
sistema (shellcode)
Come funziona ?
• Uno scrittore di shellcode deve
affrontare diversi problemi
• Il principale è la differenza tra le
varie versioni del sistema operativo
• Il secondo è ottenere tutte le
funzioni che servono per svolgere il
lavoro
Sotto Win32
• Sotto Win32 le funzioni di sistema
sono suddivisi in librerie caricate
dinamicamente dal programma
(DLL)
• Gli indirizzi delle funzioni all’interno
delle librerie cambiano da versione
a versione
Import & Export Tables
foo.exe kernel32.dll
import table di foo.exe import table di kernel32.dll
export table di kernel32.dll
Import & Export Tables
• In ogni eseguibile sotto Win32 (PE) ci
sono una import ed una export
table
• Nella Import Table ci sono le librerie
e le funzioni necessarie al
funzionamento del programma
• Nella Export Table ci sono gli indirizzi
delle funzioni dell’eseguibile
accessibili agli altri programmi
Import & Export Table
• Al momento dell’esecuzione il
loader di Win32 si occupa di
caricare tutte le DLL necessarie
• Completa quindi la Import Table dei
vari componenti con il contenuto
delle altre Export Table
Accesso alle funzioni run-time
• Il codice iniettato deve avere un modo
per accedere alle funzioni run-time
• Non può usare un indirizzo fisso perché
potrebbe cambiare da versione a
versione
• Può utilizzare le funzioni GetProcAddress e
LoadLibrary
• Con queste chiamate può avere
accesso a tutte le altre funzioni
• Per usarle però deve trovare il loro
indirizzo
Shellcode Win32
(IAT scanning)
• Per prima cosa il payload scandisce
la IAT del suo eseguibile per trovare
le chiamate LoadLibrary e
GetProcAddress
• Sfrutta quindi queste due funzioni
per ottenere l’indirizzo di tutte quelle
che gli servono
Altre tecniche
• Ci sono altre tecniche usate dagli
scrittori di exploit:
– PEB
– SEH
• Il problema che devono risolvere è
sempre lo stesso: trovare una
costante tra le varie versioni del
sistema operativo
Riflessioni
• Abbiamo visto una serie di attacchi
che possono essere portati verso
programmi con errori di
programmazione
• Il problema è che questi errori non
sono macroscopici ma spesso sono
inezie
• Basta poco per rendere un
programma vulnerabile
Sistemi di Tipi
• Il Tipo di una variabile definisce
l’insieme dei valori che può assumere
durante l’esecuzione
• I linguaggi di programmazione si
possono classificare in base al loro
sistema di tipi e alle sue caratteristiche
Language Safety
• Gli errori run-time possono essere distinti
in due classi
– trapped errors. Gli errori che vengono
rilevati
– untrapped errors. Errori che non vengono
rilevati
• Un buon sistema di tipi può eliminare
completamente la seconda classe di
errori rendendo il linguaggio safe
Exploit e sistemi di tipi
• Un exploit che sfrutta un qualche
overflow genera un untrapped error
• E’ possibile eliminare questo tipo di
errori utilizzando linguaggi di
programmazione safe
• Il linguaggio C non è safe
Bibliografia
• Memory layout Win2000
– Solomon, Russanovich “Inside Microsoft Windows 2000”, Microsoft
Press
– Articoli di Matt Pietrek su MSJ
• Stack overflow
– Aleph1 “Smashing the stack for fun and profit”, Phrack Magazine
49
– Dark Spyrit “Win32 Buffer Overflows”, Phrack Magazine 55
– Dark Spyrit “Klog - The Frame Pointer overwrite, Phrack Magazine
55
• Heap overflow
– Matt Conover “Heap overflows”
• Sistemi di tipi
– Luca Cardelli “Type Systems”

More Related Content

PDF
Sfida CTF: Phoenix/Heap0
PPT
05 1 intro-struttura
PPTX
06 3 struct
PDF
12 - Programmazione: Array dinamici e puntatori
PDF
14 - Programmazione: Stream e File
PPT
13 Puntatori E Memoria Dinamica
PDF
Lezione 5 (7 marzo 2012)
PPT
05 2 integrali-conversioni-costanti-preproc-inclusione
Sfida CTF: Phoenix/Heap0
05 1 intro-struttura
06 3 struct
12 - Programmazione: Array dinamici e puntatori
14 - Programmazione: Stream e File
13 Puntatori E Memoria Dinamica
Lezione 5 (7 marzo 2012)
05 2 integrali-conversioni-costanti-preproc-inclusione

What's hot (20)

PPT
06 1 array_stringhe_typedef
PDF
11 - Programmazione: Tipi di dato strutturati pt. 2
PDF
10 - Programmazione: Tipi di dato strutturati
PDF
Lezione 11 (26 marzo 2012)
PPT
Inferno Limbo Italian
PDF
Spyppolare o non spyppolare
PDF
Esercitazione 1 (27 febbraio 2012)
PDF
07 - Programmazione: Tipi di base e conversioni
PPTX
Python@Unina - Theory
PDF
Ruby in 25 minuti
PDF
Cell Programming 2
PDF
2006 Py03 intermedio
PPT
Realizzazione di filtri adattativi su fpga
PDF
Le basi di Pytthon 3 - Fondamenti n.1
PDF
Algoritmo probabilistico di tipo montecarlo per il list decoding
PDF
Algoritmo probabilistico di tipo montecarlo per il list decoding elaborato
PPTX
06 2 vector_matrici
PDF
Puntatori e Riferimenti
PPTX
Puntatori in C++
PDF
Reactive programming con RxJS
06 1 array_stringhe_typedef
11 - Programmazione: Tipi di dato strutturati pt. 2
10 - Programmazione: Tipi di dato strutturati
Lezione 11 (26 marzo 2012)
Inferno Limbo Italian
Spyppolare o non spyppolare
Esercitazione 1 (27 febbraio 2012)
07 - Programmazione: Tipi di base e conversioni
Python@Unina - Theory
Ruby in 25 minuti
Cell Programming 2
2006 Py03 intermedio
Realizzazione di filtri adattativi su fpga
Le basi di Pytthon 3 - Fondamenti n.1
Algoritmo probabilistico di tipo montecarlo per il list decoding
Algoritmo probabilistico di tipo montecarlo per il list decoding elaborato
06 2 vector_matrici
Puntatori e Riferimenti
Puntatori in C++
Reactive programming con RxJS
Ad

Viewers also liked (12)

PDF
Ef3e uppint quicktest_05
PDF
Ef3e uppint quicktest_03_marking_overlay
PDF
Ef3e uppint quicktest_08
PDF
Ef3e uppint quicktest_10_marking_overlay
PDF
Ef3e uppint quicktest_09
PDF
Ef3e uppint quicktest_01
PDF
Ef3e uppint quicktest_07
PDF
Ef3e uppint quicktest_03
PDF
Ef3e uppint quicktest_10
PDF
Ef3e uppint quicktest_02
PDF
Ef3e uppint quicktest_04
PDF
Ef3e uppint quicktest_06
Ef3e uppint quicktest_05
Ef3e uppint quicktest_03_marking_overlay
Ef3e uppint quicktest_08
Ef3e uppint quicktest_10_marking_overlay
Ef3e uppint quicktest_09
Ef3e uppint quicktest_01
Ef3e uppint quicktest_07
Ef3e uppint quicktest_03
Ef3e uppint quicktest_10
Ef3e uppint quicktest_02
Ef3e uppint quicktest_04
Ef3e uppint quicktest_06
Ad

Similar to [Ebook ita - security] introduzione alle tecniche di exploit - mori - ifoa - 2003 (20)

PPT
Corso c++
PPTX
Introduzione a TypeScript
PDF
Sistemi Operativi: Il kernel linux - Lezione 06
PDF
Vulnerabilità exploit
PPT
Riepilogo Java C/C++
PDF
Lezione 16 (2 aprile 2012)
PPTX
Rest sdk
PDF
DotNetToscana - Sessione TypeScript
PDF
Let's give it a GO!
PDF
Lezione 11 (26 marzo 2012)
PDF
13 - Programmazione: Compendio C - C++
PDF
Lezione 21 (2 maggio 2012)
PDF
Devianze
PDF
MOOC Piattaforme digitali per la gestione del territorio - 4.4
PPTX
OrientDB & Big Data
PDF
Penetration Testing con Python - Network Sniffer
PPTX
Low Level Software Security
ODP
Javaday 2006: Java 5
PDF
Webbit 2004: Tiger, java
PDF
15 - Programmazione: Algoritmi
Corso c++
Introduzione a TypeScript
Sistemi Operativi: Il kernel linux - Lezione 06
Vulnerabilità exploit
Riepilogo Java C/C++
Lezione 16 (2 aprile 2012)
Rest sdk
DotNetToscana - Sessione TypeScript
Let's give it a GO!
Lezione 11 (26 marzo 2012)
13 - Programmazione: Compendio C - C++
Lezione 21 (2 maggio 2012)
Devianze
MOOC Piattaforme digitali per la gestione del territorio - 4.4
OrientDB & Big Data
Penetration Testing con Python - Network Sniffer
Low Level Software Security
Javaday 2006: Java 5
Webbit 2004: Tiger, java
15 - Programmazione: Algoritmi

More from UltraUploader (20)

PDF
DOC
01 intro
DOC
01 le 10 regole dell'hacking
DOC
00 the big guide sz (by dr.to-d)
PDF
[E book ita] php manual
PDF
[Ebook ita - database] access 2000 manuale
DOC
(E book) cracking & hacking tutorial 1000 pagine (ita)
DOC
(Ebook ita - inform - access) guida al database access (doc)
PDF
(Ebook computer - ita - pdf) fondamenti di informatica - teoria
PDF
Broadband network virus detection system based on bypass monitor
PDF
Botnetsand applications
PDF
Bot software spreads, causes new worries
PDF
Blended attacks exploits, vulnerabilities and buffer overflow techniques in c...
PDF
Blast off!
PDF
Bird binary interpretation using runtime disassembly
PDF
Biologically inspired defenses against computer viruses
PDF
Biological versus computer viruses
PDF
Biological aspects of computer virology
PDF
Biological models of security for virus propagation in computer networks
PDF
Binary obfuscation using signals
01 intro
01 le 10 regole dell'hacking
00 the big guide sz (by dr.to-d)
[E book ita] php manual
[Ebook ita - database] access 2000 manuale
(E book) cracking & hacking tutorial 1000 pagine (ita)
(Ebook ita - inform - access) guida al database access (doc)
(Ebook computer - ita - pdf) fondamenti di informatica - teoria
Broadband network virus detection system based on bypass monitor
Botnetsand applications
Bot software spreads, causes new worries
Blended attacks exploits, vulnerabilities and buffer overflow techniques in c...
Blast off!
Bird binary interpretation using runtime disassembly
Biologically inspired defenses against computer viruses
Biological versus computer viruses
Biological aspects of computer virology
Biological models of security for virus propagation in computer networks
Binary obfuscation using signals

[Ebook ita - security] introduzione alle tecniche di exploit - mori - ifoa - 2003

  • 1. Introduzione alle tecniche di Exploit IFOA 24 Luglio 2003 Luigi Mori Network Security Manager Intrinsic [email protected]
  • 2. Agenda • Memory layout di un processo Win2000 • Stack Frame • Exploit • Shellcode • Note finali
  • 3. Processo Win2000 • Lo spazio di indirizzamento è flat • Suddiviso in due regioni principali – System space (Kernel) – User space (Programma e DLL) • All’interno dello user space la memoria può essere suddivisa in ulteriori sezioni – Codice – Stack – Dati inizializzati – Dati non inizializzati
  • 4. Memory layout User Space (Programma, DLL, Dati, Stack, Ambiente) System Space (Kernel, Executive, Driver) 0x80000000 L’interfaccia fra i due spazi è la NTDLL.DLL
  • 5. User Space • Diviso in una serie di regioni • Ogni regione ha dei permessi di accesso – codice: XR – dati non inizializzati: RWX – dati inizializzati: RX – stack: RWX
  • 6. Esempio User Space stack code dati init dati code dati init dati prova.exe NTDLL.DLL
  • 7. Stack Frame di una funzione C int f(char *s) { char c[16]; int i; i = 1; … return i; } push ebp mov ebp, esp sub esp,20h mov [ebp-20],1 ...
  • 8. Stack Frame di una funzione C Registri salvati Variabili locali Frame ptr Ret Address Argomenti • Registri Salvati. Sono i registri salvati dalla calling conv usata • Frame pointer. E’ il valore salvato del registro usato per indirizzare le variabili locali (EBP) • Ret Address. Indirizzo di ritorno • Argomeni. Argomenti passati
  • 9. Stack Frame di f s Ret Address Frame ptr c i • Nessun registro salvato • Le variabili locali sono contigue
  • 10. Agenda Exploit • Buffer overflow – classico – frame pointer – heap • Format String Vulnerabilities • Integer overflow
  • 11. Buffer overflow classico • Il padre di tutti i buffer overflow • Ideato da Aleph1 nell’articolo “Smashing the stack for fun and profit” nella e-zine Phrack #49
  • 12. Funzione f int f(char *s) { char c[16]; int i; i = 1; strcpy(c,s); return i; } • La funzione strcpy copia i dati da s in c senza controllare la dimensione • Se la stringa puntata da s è più lunga di 16 byte ci sono dei problemi
  • 13. Problemi per f • Se s è abbastanza lunga può andare a sovrascrivere frame pointer, return address e altro ancora • Questo può essere sfruttato da un attaccantea Ret Address Frame ptr c i
  • 14. Problemi per f • Se s è abbastanza lunga può andare a sovrascrivere frame pointer, return address e altro ancora • Questo può essere sfruttato da un attaccantea Ret Address Frame ptr c i s
  • 15. Attacco ad f • Posso costruire s in modo che la parte che va a sovrascrivere l’indirizzo di ritorno punti all’interno dei dati iniettati • Quando f finsice il suo lavoro invece di saltare indietro nella funzione chiamante salta nel buffer a Ret Address Frame ptr c i
  • 16. Attacco ad f • Posso costruire s in modo che la parte che va a sovrascrivere l’indirizzo di ritorno punti all’interno dei dati iniettati • Quando f finsice il suo lavoro invece di saltare indietro nella funzione chiamante salta nel buffer a Ret Address Frame ptr c i s Nuovo ret
  • 17. Anatomia di un exploit Cuscino di NOP Addr codice payload a Ret Address Frame ptr c i
  • 18. Anatomia di un exploit • Il cuscino di NOP iniziale serve per non dover essere eccessivamente precisi nello specificare l’indirizzo di jump • Il creatore dell’exploit deve prestare attenzione ai check fatti sull’input (alfanumerico, solo 7bit, …) • Il payload è la parte dell’exploit che compie l’azione vera e propria
  • 19. Frame pointer overflow • Buffer overflow in cui è possibile sovrascrivere solo il primo byte del frame pointer • Vengono detti off-by-one • Spesso sono dovuti a differenti implementazioni di una funzione su più piattaforme (strncpy su Linux, Win32, …)
  • 20. Frame pointer overflow • Solamente un byte del frame pointer viene sovrascritto • Dovuti ad errori nel controllo della lunghezza (<= invece di un < stretto) Registri salvati Variabili locali Frame ptr Ret Address Argomenti
  • 21. Frame pointer overflow • Solamente un byte del frame pointer viene sovrascritto • Dovuti ad errori nel controllo della lunghezza (<= invece di un < stretto) Registri salvati Variabili locali Frame ptr Ret Address Argomenti
  • 22. Come è possibile ? g() { … f(); … } • La funzione f è attaccabile • Molte funzioni hanno all’inizio un codice del tipo: • Al termine invece: • Se dentro f il frame pointer viene cambiato al termine di g viene modificato lo stack pointer push ebp mov ebp, esp mov esp, ebp pop ebp
  • 23. Difese da attacchi allo stack • Stack non eseguibile – Al segmento di stack vengono rimossi i diritti di esecuzione, i dati presenti sullo stack non possono essere eseguiti – Alcuni compilatori usano lo stack per creare trampolini verso altro codice – Il codice per l’exploit potrebbe già trovarsi all’interno del programma è sufficiente passargli i dati giusti
  • 24. Difese da attacchi allo stack • Canarino – Il compilatore viene modificato in modo da inserire un valore tra Frame Pointer e variabili in entrata ad ogni funzione – All’uscita da ogni funzione si controlla se il canarino è ancora vivo (intatto) – Il canarino può essere un valore casuale oppure semplicemente 0
  • 25. Difendersi con il canarino • Il canarino viene inserito in entrata alla funzione • Viene controllato in uscita • Se non è intatto significa che è stato sovrascritto e l’esecuzione viene interrotta • Si evita di eseguire il codice dell’exploit Registri salvati Variabili locali Frame ptr Ret Address Argomenti Canarino
  • 26. Heap-based overflow • Fino ad ora abbiamo visto solo attacchi allo stack • E’ possibile anche attaccare buffer presenti nell’area dati (heap)
  • 27. Heap-based overflow • Una volta sovrascritto il buffer è necessario trovare un modo per saltarci dentro • L’idea è di sovrascrivere un puntatore al codice in modo da farlo puntare dentro al buffer buffer altre variabili codice
  • 28. Heap-based overflow • Una volta sovrascritto il buffer è necessario trovare un modo per saltarci dentro • L’idea è di sovrascrivere un puntatore al codice in modo da farlo puntare dentro al buffer buffer altre variabili codice exploit
  • 29. Esempio di programma affetto void g() { } void main(int argc, char **argv) { static struct { char buffer[10]; void (*f)(); } s; s.f = g; argv++; strcpy(&s.buffer,*argv); printf("%08x %08xn", &s.f, &s.buffer); s.f(); } • Dando un argomento abbastanza lungo è possibile sovrascrivere il puntatore a funzione f e direttore il flusso del programma
  • 30. Situazioni tipiche di exploit • Classi C++ (mix di puntatori a funzioni e dati) • Funzioni di libreria che contengono puntatori statici a funzioni (atexit, …) • ...
  • 31. Format String Exploits • Sfruttano funzioni tipo printf • Quando la format string può essere influenzata dall’utente è possibile che sia presente una Format String Vulnerability printf(format_string, arg1, arg2, ….)
  • 32. Format String Functions • Le funzioni tipo printf accettano una format string ed un numero variabile di argomenti • In output viene generata una versione trasformate della format string
  • 33. Esempio void f() { int i; i = 5; printf(“prova %d %08xn”, i, &i); } output prova 5 00130000
  • 34. Format functions stack frame • Il chiamante conosce il numero di argomenti passati, il chiamato no • Il primo argomento è la format string • Il chiamato deduce dalla format string il numero di argomenti Registri salvati Variabili locali Frame ptr Ret Address Arg1 Frmat str addr ...
  • 35. Esempio funzione vulnerabile void f(char *s) { char buff[512]; char outbuff[512]; sprintf(buff,”Err: %s”, s); sprintf(outbuff,buff); } • Con il primo sprintf viene creata la format string per il secondo • Passando alla funzione una stringa che funzioni da format string possiamo sovrascrivere lo stack
  • 36. Esempio di format string exploit • Passo alla funzione f una stringa tipo “%s%s%s%s” • Dopo il primo sprintf ho nel buffer buff la stringa • Nel secondo sprintf questa stringa viene usata come format string “Err: %s%s%s%s”
  • 37. Esempio di format string exploit • La funzione sprintf si aspetta di trovare 4 argomenti sullo stack (uno per ogni %s) • Quando cerca di accedere a questi argomenti va a toccare il frame della funzione chiamante, in questo caso f • sprintf andrà a stampare valori “casuali” della memoria del processo. Crash del programma Registri salvati Variabili locali Frame ptr Ret Address Frmat str addr Frame di f
  • 38. Eseguire codice arbitrario • Sfruttando una format string vulnerability è possibile anche far eseguire codice arbitrario al processo • Il procedimento è abbastanza delicato ma lo scopo ultimo è sempre lo stesso: far saltare l’esecuzione all’interno del buffer riempito con il codice dell’exploit
  • 39. Integer overflow • Sono gli errori più difficili da sfruttare • Sfruttano una delle caratteristiche fondamentali dell’aritmetica dei calcolatori
  • 40. Interi e linguaggio C • Nel linguaggio ci sono diversi tipi di interi • Ogni tipo di intero è rappresentato da una variabile con un certo numero di bit • Esempio su piattaforma Win32 – int è un intero a 32 bit – short è un intero a 16 bit • Ogni intero può avere un valore massimo pari a 2^(dimensione in bit)-1
  • 41. Esempio di funzione vulnerabile int catvars(char *buf1, char *buf2, int len1, int len2) { char buff[256]; if ((len1+len2) > 256) return -1; memcpy(buff,buf1,len1); memcpy(buff+len1,buf2,len2); … return 0; } Il controllo (len1+len2) non tiene conto di un possibile integer overflow. Al memcpy è quindi possibile sovrascrivere lo stack e si ricade nel classico stack- based buffer overflow
  • 42. Idea base degli exploit • Tutti le tecniche di exploit che abbiamo visto si dividono in due parti: – iniezione del codice arbitrario in un buffer – dirottamento del programma verso quel buffer • E’ il dirottamento la parte più delicata e che differenzia una tecnica dall’altra
  • 43. Codice iniettato • Viene detto il payload dell’exploit • E’ il codice che ha il compito di compromettere il sistema • Scrivere questo codice è complesso e delicato • In genere il suo obbiettivo è quello di aprire una porta di accesso al sistema (shellcode)
  • 44. Come funziona ? • Uno scrittore di shellcode deve affrontare diversi problemi • Il principale è la differenza tra le varie versioni del sistema operativo • Il secondo è ottenere tutte le funzioni che servono per svolgere il lavoro
  • 45. Sotto Win32 • Sotto Win32 le funzioni di sistema sono suddivisi in librerie caricate dinamicamente dal programma (DLL) • Gli indirizzi delle funzioni all’interno delle librerie cambiano da versione a versione
  • 46. Import & Export Tables foo.exe kernel32.dll import table di foo.exe import table di kernel32.dll export table di kernel32.dll
  • 47. Import & Export Tables • In ogni eseguibile sotto Win32 (PE) ci sono una import ed una export table • Nella Import Table ci sono le librerie e le funzioni necessarie al funzionamento del programma • Nella Export Table ci sono gli indirizzi delle funzioni dell’eseguibile accessibili agli altri programmi
  • 48. Import & Export Table • Al momento dell’esecuzione il loader di Win32 si occupa di caricare tutte le DLL necessarie • Completa quindi la Import Table dei vari componenti con il contenuto delle altre Export Table
  • 49. Accesso alle funzioni run-time • Il codice iniettato deve avere un modo per accedere alle funzioni run-time • Non può usare un indirizzo fisso perché potrebbe cambiare da versione a versione • Può utilizzare le funzioni GetProcAddress e LoadLibrary • Con queste chiamate può avere accesso a tutte le altre funzioni • Per usarle però deve trovare il loro indirizzo
  • 50. Shellcode Win32 (IAT scanning) • Per prima cosa il payload scandisce la IAT del suo eseguibile per trovare le chiamate LoadLibrary e GetProcAddress • Sfrutta quindi queste due funzioni per ottenere l’indirizzo di tutte quelle che gli servono
  • 51. Altre tecniche • Ci sono altre tecniche usate dagli scrittori di exploit: – PEB – SEH • Il problema che devono risolvere è sempre lo stesso: trovare una costante tra le varie versioni del sistema operativo
  • 52. Riflessioni • Abbiamo visto una serie di attacchi che possono essere portati verso programmi con errori di programmazione • Il problema è che questi errori non sono macroscopici ma spesso sono inezie • Basta poco per rendere un programma vulnerabile
  • 53. Sistemi di Tipi • Il Tipo di una variabile definisce l’insieme dei valori che può assumere durante l’esecuzione • I linguaggi di programmazione si possono classificare in base al loro sistema di tipi e alle sue caratteristiche
  • 54. Language Safety • Gli errori run-time possono essere distinti in due classi – trapped errors. Gli errori che vengono rilevati – untrapped errors. Errori che non vengono rilevati • Un buon sistema di tipi può eliminare completamente la seconda classe di errori rendendo il linguaggio safe
  • 55. Exploit e sistemi di tipi • Un exploit che sfrutta un qualche overflow genera un untrapped error • E’ possibile eliminare questo tipo di errori utilizzando linguaggi di programmazione safe • Il linguaggio C non è safe
  • 56. Bibliografia • Memory layout Win2000 – Solomon, Russanovich “Inside Microsoft Windows 2000”, Microsoft Press – Articoli di Matt Pietrek su MSJ • Stack overflow – Aleph1 “Smashing the stack for fun and profit”, Phrack Magazine 49 – Dark Spyrit “Win32 Buffer Overflows”, Phrack Magazine 55 – Dark Spyrit “Klog - The Frame Pointer overwrite, Phrack Magazine 55 • Heap overflow – Matt Conover “Heap overflows” • Sistemi di tipi – Luca Cardelli “Type Systems”