Fastbins are the lazy bin: chunks pile up there without consolidating. But the
moment malloc needs a non-fast chunk, malloc_consolidate sweeps the whole
fastbin array into the unsorted bin — trusting each chunk's size on the way. The
House of Rabbit forges one of those sizes to be enormous, so the sweep produces a
giant free chunk sitting on top of memory that's still in use.
- arch
- amd64-64-little
- libc
- 2.27
- technique
- forge fastbin chunk size -> malloc_consolidate -> giant overlapping chunk
- needs
- edit one freed fastbin chunk + a way to trigger consolidation
the sweep that trusts your size#
malloc_consolidate runs when a request can't be served from the fastbins/tcache
and have_fastchunks is set — in practice, allocating a larger chunk triggers
it. For each fastbin chunk it merges with neighbours and links the result into the
unsorted bin, reading the size field to find where each chunk ends.
So: free a fastbin chunk, edit its size to something huge, and trigger the sweep.
00000000 00 00 00 00 00 00 00 00 01 10 00 00 00 00 00 00 |................|
|
why a giant chunk is a win#
That 0x1000 free chunk overlaps every allocation that lived after a. Allocate it
back and you hold a writable window over other live chunks' data and metadata — the
same overlap position that unlocks tcache poisoning, fake
sizes, and libc-pointer recovery. You manufactured it from a single size edit and a
large malloc, with no double-free and no leak.
The second flavour of the technique edits a fastbin chunk's fd instead of its
size: point it at a fake chunk, and malloc_consolidate links your fake chunk into
the unsorted bin for you — a fastbin-fd poison that survives into the sorted bins.
where it goes
Reclaim the giant chunk, overwrite the overlapped chunk's fd to __free_hook,
poison, system:
segfault{c0ns0l1d4t3_th3_wh0l3_h34p}
the sweep is fragile
malloc_consolidate walks chunk-by-chunk using the sizes it reads, so the chunk
at a + forged_size must look like a real chunk (sane size, sane PREV_INUSE)
or the sweep faults mid-merge. Lay a fake header there first, and single-step the
consolidating malloc in pwndbg — this technique crashes loudly when an offset
is wrong, which at least makes it easy to debug.
Next, the finale for the cruellest challenges — the House of Corrosion, which builds a libc leak and a shell out of nothing, no info-leak bug required.