BROP - Blind Return Oriented Programming
Last updated
Last updated
Impara e pratica Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
L'obiettivo di questo attacco è essere in grado di abuse un ROP tramite un buffer overflow senza alcuna informazione sul binario vulnerabile. Questo attacco si basa sul seguente scenario:
Una vulnerabilità nello stack e conoscenza di come attivarla.
Un'applicazione server che si riavvia dopo un crash.
Puoi trovare ulteriori informazioni su questi processi qui (BF Forked & Threaded Stack Canaries) e qui (BF Indirizzi nello Stack).
Questo gadget consente fondamentalmente di confermare che qualcosa di interessante è stato eseguito dal gadget ROP perché l'esecuzione non è andata in crash. Di solito, questo gadget sarà qualcosa che ferma l'esecuzione ed è posizionato alla fine della catena ROP quando si cercano gadget ROP per confermare che un gadget ROP specifico è stato eseguito.
Questa tecnica utilizza il gadget ret2csu. E questo perché se accedi a questo gadget nel mezzo di alcune istruzioni ottieni gadget per controllare rsi
e rdi
:
Questi sarebbero i gadget:
pop rsi; pop r15; ret
pop rdi; ret
Nota come con questi gadget è possibile controllare 2 argomenti di una funzione da chiamare.
Inoltre, nota che il gadget ret2csu ha una firma molto unica perché andrà a poppare 6 registri dallo stack. Quindi inviando una catena come:
'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP
Se il STOP viene eseguito, questo significa fondamentalmente che è stato utilizzato un indirizzo che sta poppando 6 registri dallo stack. Oppure che l'indirizzo utilizzato era anche un indirizzo STOP.
Per rimuovere questa ultima opzione, viene eseguita una nuova catena come la seguente e non deve eseguire il gadget STOP per confermare che il precedente ha effettivamente poppato 6 registri:
'A' * offset + canary + rbp + ADDR
Conoscendo l'indirizzo del gadget ret2csu, è possibile inferire l'indirizzo dei gadget per controllare rsi
e rdi
.
La tabella PLT può essere cercata da 0x400000 o dall'indirizzo RIP rivelato dallo stack (se PIE è in uso). Le voci della tabella sono separate da 16B (0x10B), e quando una funzione viene chiamata il server non va in crash anche se gli argomenti non sono corretti. Inoltre, controllare l'indirizzo di una voce nella PLT + 6B non va in crash poiché è il primo codice eseguito.
Pertanto, è possibile trovare la tabella PLT controllando i seguenti comportamenti:
'A' * offset + canary + rbp + ADDR + STOP
-> nessun crash
'A' * offset + canary + rbp + (ADDR + 0x6) + STOP
-> nessun crash
'A' * offset + canary + rbp + (ADDR + 0x10) + STOP
-> nessun crash
La funzione strcmp
imposta il registro rdx
sulla lunghezza della stringa che viene confrontata. Nota che rdx
è il terzo argomento e abbiamo bisogno che sia maggiore di 0 per poter utilizzare successivamente write
per rivelare il programma.
È possibile trovare la posizione di strcmp
nella PLT in base al suo comportamento utilizzando il fatto che ora possiamo controllare i 2 primi argomenti delle funzioni:
strcmp(<non read addr>, <non read addr>) -> crash
strcmp(<non read addr>, <read addr>) -> crash
strcmp(<read addr>, <non read addr>) -> crash
strcmp(<read addr>, <read addr>) -> no crash
È possibile controllare questo chiamando ciascuna voce della tabella PLT o utilizzando il PLT slow path che consiste fondamentalmente nel chiamare una voce nella tabella PLT + 0xb (che chiama dlresolve
) seguita nello stack dal numero di voce che si desidera sondare (partendo da zero) per esaminare tutte le voci PLT dalla prima:
strcmp(<non read addr>, <read addr>) -> crash
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
-> Andrà in crash
strcmp(<read addr>, <non read addr>) -> crash
b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
strcmp(<read addr>, <read addr>) -> no crash
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
Ricorda che:
BROP + 0x7 punta a pop RSI; pop R15; ret;
BROP + 0x9 punta a pop RDI; ret;
PLT + 0xb punta a una chiamata a dl_resolve.
Avendo trovato strcmp
, è possibile impostare rdx
su un valore maggiore di 0.
Nota che di solito rdx
ospiterà già un valore maggiore di 0, quindi questo passaggio potrebbe non essere necessario.
Infine, è necessario un gadget che esfiltri dati per esfiltrare il binario. E a questo punto è possibile controllare 2 argomenti e impostare rdx
maggiore di 0.
Ci sono 3 funzioni comuni che potrebbero essere abusate per questo:
puts(data)
dprintf(fd, data)
write(fd, data, len(data)
Tuttavia, il documento originale menziona solo la funzione write
, quindi parliamone:
Il problema attuale è che non sappiamo dove si trova la funzione write all'interno della PLT e non conosciamo un numero fd per inviare i dati al nostro socket.
Tuttavia, sappiamo dove si trova la tabella PLT ed è possibile trovare write in base al suo comportamento. E possiamo creare diverse connessioni con il server e utilizzare un FD alto sperando che corrisponda a alcune delle nostre connessioni.
Firme di comportamento per trovare quelle funzioni:
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Se ci sono dati stampati, allora è stata trovata puts
'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Se ci sono dati stampati, allora è stata trovata dprintf
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Se ci sono dati stampati, allora è stata trovata write
Documento originale: https://www.scs.stanford.edu/brop/bittau-brop.pdf
Impara e pratica Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)