Hacktricks-skills house-of-orange-exploit
House of Orange heap exploitation technique for glibc < 2.26. Use this skill whenever the user mentions heap exploitation, glibc vulnerabilities, malloc_printerr abuse, _IO_FILE structure forgery, or needs to exploit a heap overflow in older libc versions. This skill guides users through the complete House of Orange attack chain including top chunk manipulation, unsorted bin attacks, and fake _IO_FILE structure creation for arbitrary code execution.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/binary-exploitation/libc-heap/house-of-orange/SKILL.MDHouse of Orange Exploitation
A heap exploitation technique that abuses
malloc_printerr in glibc versions before 2.26 to achieve arbitrary code execution through fake _IO_FILE structure forgery.
When to Use This Skill
Use this skill when:
- You have a heap overflow vulnerability in a program linked against glibc < 2.26
- You need to exploit a heap corruption bug without calling
free - You want to abuse
for code executionmalloc_printerr - You need to forge
structures for libc exploitation_IO_FILE - You're working on CTF challenges involving heap exploitation
Requirements
Before attempting this attack, verify:
- glibc version < 2.26 (the vulnerability was patched in 2.26)
- Heap overflow that can overwrite the top chunk size
- Libc leak to get base address
- Heap leak to get heap base address
- No ASLR or ability to bypass it
Background
In older glibc versions,
malloc_printerr iterates through _IO_FILE structs stored in _IO_list_all and executes instruction pointers in those structs. This attack forges a fake _IO_FILE struct, writes it to _IO_list_all, and causes malloc_printerr to execute arbitrary code.
Attack Flow
Step 1: Set Up the Top Chunk
- Allocate a chunk to create the top chunk
- Overflow the allocated chunk to modify the top chunk size
- Ensure top chunk + size is page-aligned
- Ensure the prev_inuse bit of the top chunk is set
Step 2: Force Top Chunk into Unsorted Bin
- Allocate a chunk larger than the new top chunk size (but smaller than
, default 128K)mmap_threshold - This moves the old top chunk into the unsorted bin
- Note:
is never called in this attackfree
Step 3: Leak Libc Addresses
- Read data from the old top chunk in the unsorted bin
- Extract libc addresses from the chunk metadata
- Calculate the address of
_IO_list_all
Step 4: Perform Unsorted Bin Attack
- Use the overflow to write
topChunk->bk->fwd = _IO_list_all - 0x10 - When a new chunk is allocated, the old top chunk is split
- A pointer to the unsorted bin is written into
_IO_list_all
Step 5: Shrink the Old Top Chunk
- Adjust the size of the old top chunk to 0x61
- This serves two purposes:
- Insertion into Small Bin 4: The chunk ends up at the head of small bin 4, which is the location of the FD pointer of
_IO_list_all - Triggering Malloc Check: The size manipulation causes
to perform internal checks, triggeringmalloc
when it sees a zero forward chunkmalloc_printerr
- Insertion into Small Bin 4: The chunk ends up at the head of small bin 4, which is the location of the FD pointer of
Step 6: Set Up Fake _IO_FILE
Structure
_IO_FILE- Forge a fake
structure that overlaps with the old top chunk_IO_FILE - Set key fields to pass libc internal checks:
and_IO_write_base
must be set correctly_IO_write_ptr- Create a jump table with instruction pointer pointing to
or similarsystem
- Include a pointer to a command (e.g., "/bin/sh")
Step 7: Trigger Code Execution
- Allocate a chunk to trigger the attack
- The manipulated
structure causes arbitrary code execution_IO_FILE - Typically results in shell spawn or payload execution
Helper Scripts
Use the bundled scripts to assist with the attack:
Generate Fake _IO_FILE Structure
python scripts/generate_fake_io_file.py --help
This script generates a properly formatted fake
_IO_FILE structure with the correct field values for the attack.
Calculate Offsets
python scripts/calc_offsets.py --help
This script calculates the necessary offsets for
_IO_list_all, _IO_FILE fields, and other libc structures.
Example Exploit Structure
from pwn import * # Connect to target p = process('./vulnerable_program') # Step 1: Leak libc and heap addresses # ... (implementation depends on vulnerability) # Step 2: Calculate addresses io_list_all = libc.address + libc.symbols['_IO_list_all'] system = libc.address + libc.symbols['system'] bin_sh = next(libc.search(b'/bin/sh\x00')) # Step 3: Generate fake _IO_FILE structure fake_io_file = generate_fake_io_file(system, bin_sh) # Step 4: Perform the attack # ... (heap overflow to set up conditions) # Step 5: Trigger execution # ... (final malloc call) p.interactive()
Common Pitfalls
- glibc version: Verify the target uses glibc < 2.26
- Page alignment: Ensure top chunk + size is page-aligned
- prev_inuse bit: Must be set on the top chunk
- _IO_FILE field values: Must pass libc internal checks
- mmap_threshold: Keep allocations under 128K to avoid mmap
References
- CTF Wiki - House of Orange
- GuyInATuxedo - House of Orange
- how2heap - House of Orange Example
- glibc Patch
Test Cases
To verify this skill works correctly, try these prompts:
- "I have a heap overflow in a program with glibc 2.23. How do I use House of Orange to get a shell?"
- "Generate a fake _IO_FILE structure for House of Orange exploitation targeting system('/bin/sh')"
- "Explain the House of Orange attack step by step for a CTF writeup"
- "Calculate the offsets needed for House of Orange on glibc 2.23 with libc base 0x7ffff7c00000"