Overview
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 thetcache_perthread_struct, allowing arbitrary tcache bin manipulation without address leaks.
Glibc Version Compatibility
Compatible with: glibc 2.32 and later (all modern versions)Best suited for: glibc 2.36+ where tested
Requirements
- Use-After-Free or Double-Free: Ability to use a freed chunk
- Heap Control: Ability to allocate/free chunks and control sizes
- LSB Overwrite: Ability to overwrite at least the LSB of pointers
- No Leaks Required: The technique is completely leakless!
What It Achieves
The House of Water enables:- Tcache Metadata Control: Gain arbitrary read/write to
tcache_perthread_struct - Arbitrary Allocation: Return arbitrary pointers from malloc
- Leakless Exploitation: No address leaks needed
- Tcache Bin Manipulation: Control all tcache freelists
Technical Details
Attack Flow
1
Allocate Relative Chunk
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.Source Code
This implementation shows the modified small-bin variant which is more reliable than the original.
Walkthrough
Why Small Bin Variant?
Why Small Bin Variant?
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
Fake FWD and BCK Pointers
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
The LSB Overwrite Magic
After setting up small bins and fake tcache entries:The fake chunk in tcache structure has:
- FWD pointer (at tcache+0x390): points to small_start
- BCK pointer (at tcache+0x398): points to small_end
Visual Representation
CTF Challenges
Featured in:See the modified variant writeup for detailed application.
References
Related Techniques
- House of Botcake - Another overlapping technique
- [Tcache Poisoning/techniques/tcache/tcache-poisoning) - Direct tcache manipulation
- [Safe Link Double Protect/techniques/advanced/safe-link-double-protect) - Related leakless technique
