Skip to main content

Overview

The House of Orange is a legendary heap exploitation technique that achieves arbitrary code execution by corrupting the _IO_list_all pointer and exploiting the FILE structure mechanism. This technique is notable for achieving code execution without ever calling free(), making it powerful in constrained environments.
Patch Status: This technique was patched in glibc 2.26 when malloc_printerr was changed to no longer call _IO_flush_all_lockp.

Glibc Version Compatibility

Critical Patches:
Ret2 Wargames Practice: Try this technique hands-on at House of Orange Interactive Challenge

What This Technique Achieves

The House of Orange enables:
  • Code execution without free(): Exploit purely through malloc() calls
  • FILE structure exploitation: Hijack the FILE vtable mechanism
  • Abort() exploitation: Turn a crash into code execution
  • Unsorted bin manipulation: Force the old top chunk into unsorted bin

Prerequisites and Constraints

This technique requires:
  1. Heap leak: Must know heap addresses to corrupt pointers
  2. Libc leak: Must know libc addresses for _IO_list_all and system()
  3. Top chunk overflow: Ability to corrupt the top chunk’s size field
  4. Allocation control: Ability to trigger specific malloc sizes
  5. Glibc < 2.26: Technique is patched in newer versions
  6. Glibc < 2.24: For original technique (or vtable bypass for 2.24-2.25)

How It Works

1

Corrupt top chunk size

Overflow into the top chunk and set its size to a value that satisfies page alignment but is smaller than a large allocation.
2

Trigger sysmalloc and _int_free

Allocate a chunk larger than the corrupted top chunk size. This forces sysmalloc to mmap new memory and free the old top chunk.
3

Corrupt the freed top chunk

Use overflow to corrupt the old top chunk’s fd and bk pointers, and set its size.
4

Create fake FILE structure

Set up a fake FILE structure in the old top chunk with proper fields.
5

Trigger malloc error and abort

Make a small allocation that triggers bin sorting and causes a size check to fail, calling abort().

Complete Source Code

Technical Deep Dive

Phase 1: Freeing the Top Chunk

The top chunk is normally never freed, but we can force it:
  1. Corrupt top chunk size to be smaller than available space
  2. Allocate large chunk (> corrupted size)
  3. sysmalloc() is called to get more memory
  4. Old top chunk doesn’t merge with new memory
  5. _int_free() is called on old top chunk

Phase 2: Corrupting _IO_list_all

When malloc sorts the unsorted bin:
By setting victim->bk = _IO_list_all - 0x10, we write a main_arena pointer to _IO_list_all.

Phase 3: Fake FILE Structure

The _IO_FILE structure must pass several checks:
We need:
  1. fp->_mode <= 0
  2. fp->_IO_write_ptr > fp->_IO_write_base
  3. Valid vtable pointer
  4. _IO_OVERFLOW points to our function

Phase 4: The Exploit Chain

Why Size 0x61?

The size 0x61 (97 bytes) is chosen because:
  • It’s in the smallbin range
  • It goes to smallbin[4]
  • smallbin[4] is at offset +0x68 from main_arena
  • This offset becomes the fake FILE’s fd pointer in _IO_list_all traversal

CTF Challenge

Challenge: Orange management system with heap overflow but no free()Vulnerability:
  • Heap overflow via orange description field
  • No free() function available
  • Had to exploit purely through malloc()
Exploitation Steps:
  1. Leaked heap address via overlapping chunks
  2. Leaked libc address via unsorted bin pointers
  3. Corrupted top chunk size to 0xc01
  4. Allocated large chunk to free old top
  5. Corrupted old top chunk’s bk to _IO_list_all - 0x10
  6. Set up fake FILE structure with system() address
  7. Triggered abort() via small allocation
  8. Got shell when system(“/bin/sh”) was called
Writeup: Hitcon 2016 House of Orange WriteupHistorical Significance: This challenge introduced the technique and gave it its name.

Common Pitfalls

Top Chunk Size Validation: The top chunk size must be page aligned (LSBs = 0x001) and have PREV_INUSE set. Use 0xc01, 0x1c01, etc.
FILE Structure Alignment: The fake FILE structure must be properly aligned. Using size 0x61 ensures it lands in smallbin[4] at the right offset.
Missing Leaks: You need both heap and libc leaks. Without them, you can’t calculate _IO_list_all or system() addresses.
vtable Validation: On glibc 2.24+, vtables are validated against a whitelist. The technique requires a vtable bypass or doesn’t work.

The Patches

Patch 1: vtable Validation (glibc 2.24)

This validates that vtable pointers are in the proper libc regions.

Patch 2: malloc_printerr (glibc 2.26)

Modern Alternatives

House of Tangerine

Modern technique for glibc 2.26+ using sysmalloc _int_free

House of Apple

Advanced FILE structure exploitation for modern glibc

House of Kiwi

Alternative FILE-based technique for code execution

Learning Resources

See Also