Il mio primo pwn Arm14 min read

Recentemente ho voluto provare per la prima volta un pwn su Arm per vedere le principali differenze con un normale binario su una macchina non Arm. Per questo esperimento ho scritto un semplice programmino in C vulnerabile a buffer overflow per poi exploitarlo, vediamo ora i passi che ho seguito! Qui puoi scaricare il binario ed il suo codice sorgente.

Il primo controllo che ho fatto, abbastanza inutile dato che l’ho scritto e compilato io ma almeno ci teniamo in forma anche con queste piccolezze :P, è stato un checksec per vedere le protezioni implementate dal binario:

Copy to Clipboard

Ecco il risultato:

Copy to Clipboard

Ok, come ci aspettavamo è un Arm 32 bit, con Partial RELRO, stack non eseguibile, niente canarino e niente pie. Vediamo ora l’esecuzione del binario. Per eseguirlo sulla mia macchina (Ubuntu 16.04 a 64 bit) ho usato qemu-arm per simulare un ambiente Arm, usando le librerie situate nella directory /usr/arm-linux-gnueabihf:

Copy to Clipboard

Ecco il risultato dell’esecuzione:

Copy to Clipboard

Ok, probabilmente il programma va a leggere un file di testo chiamato root.txt e confronta con quello che gli passiamo noi, per esserne sicuri esaminiamo il binario con radare2:

Copy to Clipboard

Digitiamo “vv” per vedere le funzioni del binario:

Copy to Clipboard

Come possiamo notare c’è una funzione chiamata “get_password”, probabilmente è questa che apre il file “root.txt”, andiamo a vedere in dettaglio cosa fa sempre con radare:

Copy to Clipboard

Infatti come possiamo vedere essa apre il file “/root/pwn/root.txt”. Proviamo ora a creare questo file nella nostra “/root” locale e rieseguire il binario:

Copy to Clipboard

Ok funziona, proviamo ora ad eseguire il binario con un grande input:

Copy to Clipboard

Come possiamo notare il programma è andato in errore di segmentazione, ora possiamo finalmente esaminare lo stato della memoria durante il crash del programma utilizzando gdb:

Copy to Clipboard

Yeah, come possiamo vedere, il program counter punta ad un indirizzo fasullo 0x41414140 che corrisponde a “AAA@” ossia esattamente alle A che gli abbiamo passato in input. Proviamo ora ad exploitarlo utilizzando la tecnica della ret2libc. Nota: l’exploit verrà infine testato su un Raspberry Pi che ha un processore Arm a 32 bit.

Prima di proseguire ricordiamo i punti salienti della ret2libc:

  • Primo step: facciamo il leak di un indirizzo della libc, poiché è buona regola assumere sempre che l’aslr sia abilitato (a meno che non ci venga esplicitamente detto che esso è disabilitato). Per questo scopo possiamo sfruttare la printf o la puts e passargli come argomento l’indirizzo di memoria di una funzione che sta all’interno della tabella GOT, per esempio la puts stessa.
  • Secondo step: adesso, utilizzando l’indirizzo ottenuto dal leak, possiamo determinare la versione della libc, utilizzando ad esempio libc database, ma in questo caso è opzionale poiché abbiamo accesso al Raspberry e quindi anche alla sua libc!
  • Una volta ottenuta la libc dobbiamo calcolarci gli offset della system e della stringa “/bin/sh” dall’inizio della libc.
  • Come ultimo step non ci resta che mettere insieme tutti questi concetti.

Ricordiamoci che il binario è a 32 bit, quindi possiamo utilizzare anche la tecnica del bruteforce per bypassare la protezione dell’aslr. Esaminiamo quindi il binario utilizzando gdb sul Raspberry:

Copy to Clipboard

Cool, ora abbiamo l’indirizzo della system che è a 0x76eba598, ora non ci resta che cercare l’indirizzo della bin sh:

Copy to Clipboard

Ok, bin sh si trova a 0x76fabed0. Ora il prossimo step è utilizzare dei gadget per saltare sulla system. Normalmente, in un binario a 64 bit, gli argomenti vengono inseriti nel registro rdi e l’istruzione “ret” salta sull’indirizzo al top dello stack. In un binario Arm l’indirizzo di ritorno deve essere nel registro “pc” e l’argomento nel registro “r0”. Utilizziamo ora ROPGadget per vedere se ci sono dei gadget per il nostro exploit:

Copy to Clipboard

Ci sono diversi gadget, ma i più interessanti sono i seguenti:

Copy to Clipboard

Come mai questi tre? Perché con pop {r3,pc} mettiamo in r3 l’indirizzo della system e nel registro pc l’indirizzo del prossimo gadget 0x00010788. Con il secondo gadget mettiamo in r7 l’indirizzo della bin sh e in pc l’indirizzo dell’ultimo gadget 0x00010778. infino spostiamo l’indirizzo della stringa bin sh in r0 (da r7) e saltiamo all’indirizzo specificato in r3 (ossia l’indirizzo della system) utilizzando blx r3 (l’equivalente di call r3). Con questa sequenza possiamo alterare il flusso del programma e aprire una shell!

Scriviamo ora uno script per questo scopo:

Copy to Clipboard

Nota: abbiamo aggiunto 0xFFFFFFFF nel nostro payload come dummy data, richiesti dal secondo gadget. Ora andiamo sul Raspberry e facciamo partire lo script.

Copy to Clipboard

Come possiamo vedere abbiamo utilizzato un while true per bypassare l’aslr. Finalmente, dopo alcune iterazioni, otteniamo una shell!

Copy to Clipboard

Pwned it! 😉

Recent Tweets

For privacy reasons Twitter needs your permission to be loaded.
I Accept
2018-08-15T09:11:00+00:00

About the Author:

Dottore in Informatica. Da sempre appassionato di Linux, reti informatiche, sicurezza e, in modo amatoriale, all’elettronica. Il mio intento è quello di trasmettere le mie conoscenze ad altri appassionati.

Leave A Comment

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.