Continuando con la serie Protostar, in questo articolo andremo ad analizzare una tecnica più avanzata rispetto allo Stack Buffer Overflow. Per questo motivo ho deciso di dividere in più articoli la serie Heap, facendo un livello per articolo.
Quando un programma viene eseguito, viene allocata dinamicamente della memoria per contenere i dati dello stesso. Lo heap è quindi un blocco di memoria assegnato ad un processo di dimensione definita a run-time.
L’allocazione della memoria in C avviene tramite diverse funzioni, tra le principali:
Per una descrizione più approfondita consiglio questo articolo.
Queste funzioni, se non gestite in maniera corretta, possono essere suscettibili ad overflow nel caso in cui si possa inserire una quantità di dati superiore alla memora allocata e di conseguenza andare a sovrascrivere aree di memoria adiacenti. La differenza con lo stack, dal punto di vista dell’attaccante, è che nell’area heap sono memorizzati solo puntatori e di conseguenza bisogna creare una chain di shellcode per ottenere un exploit funzionante.
[Per comprendere meglio su GDB i processi interni ho deciso di installare PwnGDB e Peda-Heap, che consiglio vivamente]
In questo caso l’esercizio è molto simile alla serie stack, in quanto a riga 36 possiamo vedere come la funzione strcpy copi la variabile passata a linea di comando all’interno di name (che fa parte della struct data) senza nessun controllo. Di conseguenza, sarà possibile andare a sovrascrivere il puntatore fp ed inserire al suo posto il puntatore a winner.
Se proviamo ad inserire un breakpoint alla fine ed eseguirlo con un semplice AAAA, possiamo analizzare cosa succede dietro le quinte.
Come si può vedere, la variabile _data _e fp risiedono nello heap e fp è assegnato alla funzione nowinner (che ha stampato Level has not been passed). Andando a guardare nel dettaglio
Con il primo comando analizziamo la struttura dati del processo, con il secondo gli indirizzi di memoria dello heap (dove vediamo il nostro AAAA), mentre con il terzo il contenuto di fp.
Avendo capito il giro, ora ci basterà:
Trovare l’offset per andare a sovrascrivere il puntatore a nowinner e modificarlo con winner. Questo lo otteniamo con il comando
osboxes@osboxes:~/Desktop/Protostar$ echo $((0x804b050 - 0x804b008))
72
Trovare l’indirizzo della variabile winner da gdb
gdb-peda$ p *winner
$1 = {void ()} 0x804849b
Unendo le due cose, possiamo eseguire il programma con il payload cosi formato
Vediamo come ora la situazione sia cambiata, e ESP punta a winner
La sovrascrittura ha funzionato perfettamente e abbiamo puntato ad una funzione diversa rispetto a quella originale.
Possiamo ovviamente fare lo stesso giro direttamente fuori da GDB
Sebbene questo esercizio sia molto simile ai precedenti, abbiamo iniziato a scalfire solo la punta dell’iceberg. Esistono diversi attacchi allo heap, e nel prossimo esercizio il discorso sarà già molto più approfondito e con una metodologia decisamente diversa. Come approfondimento per ora consiglio solo questo piccolo libro, in modo tale da avere le idee chiare per il prossimi esercizio