Parte: 5 — Explotación de sistemas y binarios · Fuente: The Shellcoder's Handbook · how2heap (Shellphish) ⏱️ Duración estimada: 140 min · Nivel: Experto
Explotar dos de las corrupciones de heap más frecuentes: use-after-free (UAF), donde se usa un
puntero a memoria ya liberada, y double free, donde se libera dos veces el mismo chunk. Verás cómo
el UAF permite leer/escribir datos ajenos y secuestrar punteros de función, y cómo un double free en
tcache (tcache poisoning) logra escritura arbitraria para redirigir malloc a una dirección elegida.
⚠️ Ética: solo en laboratorio propio o CTF autorizado.
Al finalizar, el alumno podrá:
malloc a una dirección arbitraria (p. ej. __free_hook/GOT).| # | Tema | Por qué importa |
|---|---|---|
| 1 | Puntero colgante (dangling) | Raíz del UAF |
| 2 | Reasignación del chunk | Cómo se solapan objetos |
| 3 | Secuestro de vtable/punteros | UAF → control de flujo |
| 4 | Double free en tcache | Base del poisoning |
| 5 | tcache key (mitigación) | Detección de double free en glibc ≥2.29 |
| 6 | tcache poisoning | Escritura del next → malloc arbitrario |
| 7 | Objetivos: __free_hook, GOT | Convertir en RCE |
| 8 | Detección con ASan | Cazar el bug en desarrollo |
free. Clave: CWE-416; si el chunk se reasigna, escribes
sobre otro objeto.free. Clave: no ponerlo a NULL es la causa
típica.next de un chunk en tcache. Clave: el siguiente
malloc de ese tamaño devuelve la dirección que elijas.pip install pwntools
# ASan para detección:
gcc -fsanitize=address -g uaf.c -o uaf_asan
ldd --version | head -1 # conocer la versión de glibc y sus mitigaciones
Entorno propio.
uaf.c:c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *a = malloc(0x40);
free(a); // a queda colgante
char *b = malloc(0x40); // reutiliza el mismo chunk
strcpy(b, "datos de b");
printf("a ahora lee: %s\n", a); // UAF: a y b son la misma memoria
}
Ejecuta y observa que a "ve" lo que escribió b.
Detecta el bug con ASan: ./uaf_asan reporta heap-use-after-free con backtrace.
Double free / tcache poisoning en pwndbg (glibc que lo permita):
next del chunk en tcache con la dirección objetivo:python
from pwn import *
# ...interacción con el binario de reto...
# tras el double free, escribimos el next del chunk liberado:
edit(idx, p64(target_addr)) # target_addr = &__free_hook o entrada GOT
malloc(size) # saca el chunk falso al frente
malloc(size) # este malloc devuelve target_addr
Escribe en el chunk devuelto para colocar system en __free_hook (o el equivalente moderno) y
dispara un free sobre un chunk que contenga "/bin/sh".
Verifica en GDB que malloc devolvió tu dirección objetivo (vis_heap_chunks, bins).
Comenta cómo la tcache key de glibc moderna obligaría a un paso extra para el double free.
uaf.c poniendo el puntero a NULL tras free y confirma con ASan.tcache key y cómo detecta el double free.En un binario de reto con UAF/double free, logra que un malloc devuelva una dirección que tú elijas
mediante tcache poisoning.
Criterio de aceptación: demuestras en GDB que un malloc retorna la dirección objetivo, y (si el
reto lo permite) obtienes ejecución de código o lectura de la flag.
| Síntoma / mensaje | Causa y cómo arreglar |
|---|---|
free(): double free detected in tcache 2 |
tcache key activa; falséala o usa fastbin |
| El poisoning no cambia malloc | El next mal alineado o tamaño de bin incorrecto |
| Crash al liberar chunk falso | Metadatos inválidos; ajusta size y alineación |
__free_hook no existe |
glibc ≥2.34; apunta a GOT/estructuras alternativas |
| ASan no detecta nada | No compilaste con -fsanitize=address |
❓ ¿UAF siempre da RCE? No siempre; depende de si el objeto reasignado contiene punteros de función o datos sensibles.
❓ ¿Sigue funcionando el ataque a __free_hook? No en glibc ≥2.34 (los hooks fueron eliminados);
hay que buscar objetivos modernos.
❓ ¿Cómo evito estos bugs al programar? Pon punteros a NULL tras free, usa smart pointers en
C++ y compila con ASan en CI.
Clase 126 — Explotación de heap: fundamentos