Stack Pivoting - EBP2Ret - EBP chaining
Informazioni di base
Questa tecnica sfrutta la capacità di manipolare il Base Pointer (EBP) per concatenare l'esecuzione di funzioni multiple attraverso un uso attento del registro EBP e della sequenza di istruzioni leave; ret
.
Come promemoria, leave
significa fondamentalmente:
E poiché l'EBP è nello stack prima dell'EIP è possibile controllarlo controllando lo stack.
EBP2Ret
Questa tecnica è particolarmente utile quando puoi modificare il registro EBP ma non hai un modo diretto per cambiare il registro EIP. Sfrutta il comportamento delle funzioni quando terminano l'esecuzione.
Se, durante l'esecuzione di fvuln
, riesci a iniettare un falso EBP nello stack che punta a un'area in memoria dove è situato l'indirizzo del tuo shellcode (più 4 byte per tener conto dell'operazione pop
), puoi controllare indirettamente l'EIP. Quando fvuln
ritorna, l'ESP è impostato su questa posizione creata, e l'operazione pop
successiva diminuisce l'ESP di 4, facendo in modo che punti effettivamente a un indirizzo memorizzato dall'attaccante lì dentro.
Nota come devi conoscere 2 indirizzi: Quello dove andrà l'ESP, dove dovrai scrivere l'indirizzo puntato dall'ESP.
Costruzione dell'Exploit
Prima devi conoscere un indirizzo dove puoi scrivere dati / indirizzi arbitrari. L'ESP punterà qui e eseguirà il primo ret
.
Poi, devi conoscere l'indirizzo usato da ret
che eseguirà codice arbitrario. Potresti usare:
Un indirizzo valido di ONE_GADGET.
L'indirizzo di
system()
seguito da 4 byte di spazzatura e l'indirizzo di"/bin/sh"
(bit x86).L'indirizzo di un gadget
jump esp;
(ret2esp) seguito dal shellcode da eseguire.Una catena ROP
Ricorda che prima di questi indirizzi nella parte controllata della memoria, devono esserci 4
byte a causa della parte pop
dell'istruzione leave
. Sarebbe possibile abusare di questi 4B per impostare un secondo falso EBP e continuare a controllare l'esecuzione.
Exploit Off-By-One
Esiste una variante specifica di questa tecnica nota come "Exploit Off-By-One". Viene utilizzata quando puoi modificare solo il byte meno significativo dell'EBP. In tal caso, la posizione di memoria che memorizza l'indirizzo a cui saltare con il ret
deve condividere i primi tre byte con l'EBP, consentendo una manipolazione simile con condizioni più vincolate.
Di solito si modifica il byte 0x00 per saltare il più lontano possibile.
Inoltre, è comune utilizzare un RET sled nello stack e inserire la vera catena ROP alla fine per rendere più probabile che il nuovo ESP punti all'interno del RET SLED e la catena ROP finale venga eseguita.
EBP Chaining
Pertanto, inserendo un indirizzo controllato nell'ingresso EBP
dello stack e un indirizzo a leave; ret
in EIP
, è possibile spostare l'ESP
all'indirizzo EBP
controllato dallo stack.
Ora, l'ESP
è controllato puntando a un indirizzo desiderato e l'istruzione successiva da eseguire è un RET
. Per sfruttare ciò, è possibile inserire in questo indirizzo ESP controllato quanto segue:
&(prossimo falso EBP)
-> Carica il nuovo EBP a causa dipop ebp
dall'istruzioneleave
system()
-> Chiamato daret
&(leave;ret)
-> Chiamato dopo che system termina, sposterà ESP al falso EBP e ricomincerà&("/bin/sh")
-> Parametro persystem
In questo modo è possibile concatenare diversi falsi EBPs per controllare il flusso del programma.
Questo è simile a un ret2lib, ma più complesso senza un beneficio apparente ma potrebbe essere interessante in alcuni casi limite.
Inoltre, qui hai un esempio di una sfida che utilizza questa tecnica con un leak dello stack per chiamare una funzione vincente. Questo è il payload finale dalla pagina:
EBP potrebbe non essere utilizzato
Come spiegato in questo post, se un binario è compilato con alcune ottimizzazioni, l'EBP non arriva mai a controllare ESP, quindi, qualsiasi exploit che funziona controllando EBP fallirà essenzialmente perché non ha alcun effetto reale. Questo perché il prologo e l'epilogo cambiano se il binario è ottimizzato.
Non ottimizzato:
Ottimizzato:
Altri modi per controllare RSP
Gadget pop rsp
pop rsp
In questa pagina puoi trovare un esempio che utilizza questa tecnica. Per questa sfida è stato necessario chiamare una funzione con 2 argomenti specifici, ed è stato trovato un gadget pop rsp
e c'è un leak dallo stack:
Gadget xchg <reg>, rsp
jmp esp
Controlla la tecnica ret2esp qui:
pageRet2esp / Ret2regRiferimenti ed Altri Esempi
64 bit, sfruttamento off by one con una catena rop che inizia con un ret sled
64 bit, no relro, canary, nx e pie. Il programma fornisce un leak per lo stack o pie e un WWW di una qword. Prima ottenere il leak dello stack e utilizzare il WWW per tornare indietro e ottenere il leak di pie. Quindi utilizzare il WWW per creare un loop eterno abusando delle voci di
.fini_array
+ chiamare__libc_csu_fini
(più informazioni qui). Sfruttando questa scrittura "eterna", viene scritta una catena ROP nel .bss e si finisce chiamandola pivotando con RBP.
ARM64
In ARM64, le prologhe ed epiloghe delle funzioni non memorizzano e recuperano il registro SP nello stack. Inoltre, l'istruzione RET
non ritorna all'indirizzo puntato da SP, ma all'indirizzo all'interno di x30
.
Pertanto, di default, sfruttando solo l'epilogo non sarai in grado di controllare il registro SP sovrascrivendo alcuni dati nello stack. E anche se riesci a controllare lo SP, avresti comunque bisogno di un modo per controllare il registro x30
.
prologo
epilogo
Il modo per eseguire qualcosa di simile allo stack pivoting in ARM64 sarebbe essere in grado di controllare lo SP
(controllando qualche registro il cui valore viene passato a SP
o perché per qualche motivo SP
sta prendendo il suo indirizzo dallo stack e abbiamo un overflow) e quindi abusare dell'epilogo per caricare il registro x30
da uno SP
controllato e RET
ad esso.
Inoltre nella pagina seguente puoi vedere l'equivalente di Ret2esp in ARM64:
pageRet2esp / Ret2regLast updated