The House of Water is a sophisticated technique for converting a Use-After-Free (UAF) vulnerability into complete tcache metadata control. This modified variant uses small bins instead of the original unsorted bin approach, eliminating the need for 4-bit brute-forcing even without the ability to increment integers.The technique provides leakless control over the tcache_perthread_struct, allowing arbitrary tcache bin manipulation without address leaks.
Allocate the ‘relative chunk’ immediately after tcache metadata. This chunk shares the same ASLR-controlled second nibble (0x2) as the fake chunk location we’ll target in the tcache structure.
2
Create Fake Tcache Entries
Use double-free or UAF to create fake tcache entries in the 0x320 and 0x330 size bins. These will act as fake forward (FWD) and backward (BCK) pointers pointing to chunk headers.
3
Setup Small Bin List
Free three chunks (small_start, relative_chunk, small_end) into unsorted bin, then trigger a large allocation to sort them into the small bin as a linked list.
4
LSB Overwrite
Use UAF to overwrite the LSB of small_start’s fd and small_end’s bk pointers with 0x00. This redirects both pointers to the fake tcache chunk in the tcache structure.
5
Drain Tcache and Allocate
Drain the tcache for the target size, forcing malloc to use small bins. The first allocation returns small_start and moves remaining chunks to tcache. The second returns small_end. The third returns the fake chunk, giving control over tcache_perthread_struct.
The original House of Water used unsorted bins and required 4-bit brute-forcing because of ASLR randomization in heap addresses.The small bin variant improves on this by:
Using small bin’s doubly-linked list structure
Leveraging the deterministic relationship between chunk addresses in the same page
Only requiring LSB overwrite (0x00) instead of partial pointer
Because the relative_chunk is allocated right after tcache metadata, it shares the same second nibble (0x2). By overwriting just the LSB to 0x00, we redirect pointers to offset 0x200 in the same page - which falls inside the tcache structure!
Fake FWD and BCK Pointers
The clever trick is creating fake tcache entries at 0x320 and 0x330 size classes:
When we create fake chunks of size 0x321 and 0x331 overlapping small_start and small_end, then free them, the tcache stores pointers to these “chunks” at the calculated offsets.These pointers then act as pre-placed FWD/BCK pointers when we construct our small bin fake chunk!
The LSB Overwrite Magic
After setting up small bins and fake tcache entries: