Ciao a tutti! È appena finito il ctf HackCon18, quindi possiamo vedere il writeup di questa interessante challenge. Il pwn è basato su due vulnerabilità: la prima è la stringa di formato e la seconda è un semplice buffer overflow, quindi bisognava fare un leak della memoria per ottenere degli indirizzi validi della libc grazie alla stringa di formato (per bypassare l’ASLR), una volta ottenuto un leak calcolare l’indirizzo della system per fare una classica ret2libc.
Il primo step fatto è stato dare un checksec del programma che ci è stato fornito:
Come possiamo vedere è tutto disabilitato tranne per il fatto che lo stack non è eseguibile. Proviamo ora ad eseguire il binario:
Ok, notiamo che il processo ritorna l’input che gli abbiamo fornito, proviamo quindi con una stringa di formato:
infatti ci sono degli indirizzi dello stack del processo. Proviamo ora ad inserire un input più grande:
Il programma è andato in segmentation fault. Esaminiamo ora con radare2 il programma per vedere cosa fa:
semplicemente la funzione main prende un input con la scanf, che va poi in overflow, e lo stampa con la printf così da avere la stringa di formato. Continuiamo la nostra ispezione esaminando ora il core dump creato:
Grazie al core dump ci siamo potuti calcolare la dimensione del buffer prima di andare in overflow. Esaminiamo ora lo stack in cerca di un indirizzo della libc da prendere con la stringa di formato. Per questo scopo facciamo partire il programma in gdb e mettiamo un breakpoint sulla printf poiché noi andremo ad ottenere la porzione dello stack utilizzata dalla printf:
Perfetto, c’è un indirizzo che punta alla libc_start_main, ma c’è anche un problema: se noi inseriamo un input grande (che ci servirà per sovrascrivere l’indirizzo di ritorno), andremo a sovrascrivere anche questo indirizzo! Quindi dobbiamo cercare un altro indirizzo valido da utilizzare. In particolare c’è 0x00007ffff7a6287d che è all’inizio della nostra stringa di formato, ma solo in remoto! (Non ho ancora capito perché ma inserendo %1$p in remoto otteniamo questo indirizzo, mentre in locale otteniamo un misero 0x1, probabilmente dovuta a qualche differenza nella libc utilizzata). Comunque esaminando lo stack sembra essere l’indirizzo della fflush. Calcoliamo ora la differenza tra questo valore e la libc_start_main per ottenere quest’ultima. Facciamo partire il processo in remoto per ottenere questi due valori:
dove %1$p è l’offset per ottenere il nostro indirizzo misterioso e %17$p è l’offset per ottenere libc_start_main. La differenza tra questi due indirizzi è:
Ok, ora abbiamo un indirizzo della libc valido! Ora otteniamo l’indirizzo dell’inizio della libc_start_main e poi cerchiamo l’offset della system e della stringa bin sh. Per questo scopo esaminiamo la libc che ci è stata fornita:
dove 0x21f45 corrisponde al leak della libc_start_main, che è a 245 byte dall’inizio della funzione. Adesso calcoliamo la base della libc e poi la system e la bin sh. Usiamo libc database per ottenere i vari offset:
Ora cerchiamo un gadget per inserire bin sh nel registro rdi:
Ed infine abbiamo tutto il necessario per la scrittura del nostro script:
Ora runniamo lo script:
Scrivi un commento