Parte: 5 — Explotación de sistemas y binarios · Fuente: The Shellcoder's Handbook · glibc malloc internals ⏱️ Duración estimada: 130 min · Nivel: Avanzado
Entender cómo funciona el heap de glibc (ptmalloc2): chunks, cabeceras de tamaño, bins y arenas.
Sin este modelo mental, las técnicas de explotación de heap (UAF, double free, tcache poisoning) son
magia negra. Aprenderás a inspeccionar el heap en vivo con pwndbg y a razonar sobre cómo malloc/free
reorganizan la memoria.
⚠️ Ética: solo en laboratorio propio.
Al finalizar, el alumno podrá:
prev_size, size, flags, datos.heap, bins, vis_heap_chunks de pwndbg.malloc/free reutilizan memoria.| # | Tema | Por qué importa |
|---|---|---|
| 1 | Arena y heap | Estructura global del asignador |
| 2 | Chunk: size y flags (PREV_INUSE) | Metadatos que se corrompen |
| 3 | tcache (glibc ≥ 2.26) | Bin más explotado hoy |
| 4 | fastbins | Listas LIFO de chunks pequeños |
| 5 | unsorted/small/large bins | Reciclaje y consolidación |
| 6 | top chunk | Frontera del heap |
| 7 | Herramientas pwndbg de heap | Ver todo en vivo |
| 8 | Fuentes de corrupción | Base de UAF/double free/overflow |
size) y datos. Clave: el bit PREV_INUSE
indica si el chunk previo está en uso.next
manipulable → tcache poisoning.fd/bk).size habilita
el "house of force".pip install pwntools
# pwndbg incluye comandos de heap; verifica versión de glibc:
ldd --version | head -1
Compila un programa de práctica que reserve y libere chunks con malloc/free.
Entorno propio.
heapdemo.c:c
#include <stdlib.h>
#include <string.h>
int main(){
char *a = malloc(0x30); strcpy(a,"AAAA");
char *b = malloc(0x30); strcpy(b,"BBBB");
free(a); free(b);
char *c = malloc(0x30); // reutiliza el último liberado (tcache LIFO)
return 0;
}
malloc/free:gdb
pwndbg> break main
pwndbg> run
pwndbg> heap # muestra la lista de chunks
pwndbg> vis_heap_chunks
Tras los dos free, observa bins y verás a y b en el tcache del tamaño 0x40.
Comprueba el orden LIFO: c reutiliza la dirección de b (el último liberado).
Examina la cabecera de un chunk con x/4gx <dir_chunk-0x10> e identifica prev_size y size
(con el bit PREV_INUSE).
Repite reservando chunks grandes (0x500) para verlos ir al unsorted/large bin y nota los punteros
fd/bk hacia libc (útiles para leaks en clases siguientes).
size de cada uno.size en vis_heap_chunks.next de un chunk en tcache (dónde apunta).Con un programa que reserve y libere varios chunks, demuestra en pwndbg que el tcache es LIFO
prediciendo qué dirección devolverá el siguiente malloc.
Criterio de aceptación: predices correctamente la dirección devuelta por un malloc posterior
basándote en el estado del tcache mostrado por bins.
| Síntoma / mensaje | Causa y cómo arreglar |
|---|---|
| No ves tcache | glibc antigua (<2.26); revisa versión |
size "raro" (+1) |
El bit PREV_INUSE está puesto; enmascara con & ~0x7 |
| Chunks no se consolidan | tcache/fastbin no consolidan; usa tamaños mayores |
| Direcciones cambian | ASLR; desactívalo para estudiar el layout |
| Confundir datos con metadatos | El usuario ve el puntero a datos, no a la cabecera |
❓ ¿Por qué estudiar glibc y no otro asignador? Es el más común en Linux/CTF. jemalloc/tcmalloc tienen internals distintos.
❓ ¿El tamaño que pido es el tamaño del chunk? No: se redondea e incluye metadatos; malloc(0x30)
suele dar un chunk de 0x40.
❓ ¿Necesito memorizar todos los bins? Domina tcache y fastbins primero; son los más explotados en glibc moderna.
Clase 125 — Vulnerabilidades de format string