Skip to main content

Overview

The House of Tangerine is a modern heap exploitation technique that serves as the successor to House of Orange for glibc 2.26+. Like its predecessor, it exploits the top chunk (wilderness) without calling free() directly, but uses tcache poisoning instead of FILE structure exploitation to achieve arbitrary allocation.
This technique was inspired by the PicoCTF 2024 challenge “High Frequency Troubles” and represents the modern evolution of top chunk exploitation.

Glibc Version Compatibility

No patches exist for this technique - it remains viable on all modern glibc versions.

What This Technique Achieves

The House of Tangerine enables:
  • Arbitrary allocation without free(): Force malloc to return any malloc-aligned pointer
  • Heap corruption via malloc only: Exploit using only malloc() calls
  • Tcache control: Inject arbitrary addresses into tcache freelist
  • Modern compatibility: Works on latest glibc with safe linking

Prerequisites and Constraints

This technique requires:
  1. Heap overflow/OOB write: Ability to corrupt top chunk size (twice)
  2. Heap leak (glibc 2.32+): Required for safe linking bypass
  3. Size control: Ability to control malloc sizes precisely
  4. Multiple allocations: Requires 5-6 malloc calls
  5. Target alignment: Target address must be malloc-aligned (16 bytes on x64)

How It Works

1

Corrupt first top chunk

Overflow to corrupt the top chunk size to be page-aligned but smaller than a large allocation.
2

Trigger sysmalloc and _int_free

Allocate a large chunk to force sysmalloc to free the old top chunk.
3

Corrupt second top chunk

Use overflow again to corrupt the new top chunk size.
4

Trigger second _int_free

Allocate another large chunk to free the second corrupted top chunk.
5

Poison tcache with target address

Corrupt the tcache fd pointer to point to target (with safe linking).
6

Retrieve poisoned tcache entries

Make two allocations to get the target address.

Complete Source Code

Technical Deep Dive

The _int_free in sysmalloc

The key to House of Tangerine is this code path in sysmalloc:
This happens when:
  1. We corrupt top chunk size to be smaller than allocation
  2. malloc calls sysmalloc to get more memory
  3. New memory is mmapped at a different location
  4. Old top chunk can’t merge with new memory
  5. _int_free is called on old top chunk
No direct free() call needed!

Size Calculation Strategy

The technique requires precise size calculations:
The math ensures that after allocation, the remaining top chunk size (when corrupted and freed) equals CHUNK_SIZE_1.

Page Alignment Bypass

Why keep page alignment bits?
By keeping the page-aligned bits (0x1000, 0x2000, etc.), we:
  1. Avoid triggering size validation checks
  2. Make the corrupted size look “reasonable”
  3. Still control the lower bits for precise freed size

Safe Linking Bypass

For glibc 2.32+, tcache uses safe linking:
We need a heap leak to know current_fd_address, then XOR with target.

Double Top Chunk Free

Why free the top chunk twice?
  1. First free: Gets a freed chunk of size CHUNK_SIZE_1 into tcache
  2. Second free: Creates another freed chunk whose fd pointer we can corrupt
Without the second free, we’d need a different method to corrupt the tcache fd pointer.

CTF Challenge

Challenge: Signal processing application with controlled heap allocationsVulnerability:
  • Could trigger allocations of controlled sizes
  • Had out-of-bounds write to corrupt heap metadata
  • No direct free() function available
Exploitation:
  1. Leaked heap address via observation of allocation patterns
  2. Corrupted top chunk size to force sysmalloc
  3. Triggered large allocation to free old top chunk
  4. Repeated process to get second freed top chunk
  5. Corrupted tcache fd pointer with safe linking bypass
  6. Got arbitrary allocation near target data structure
  7. Overwrote flag verification logic
Challenge Link: PicoCTF 2024 - High Frequency TroublesSignificance: This challenge popularized the technique and demonstrated its practicality.

Common Pitfalls

Size Alignment Errors: The most complex part is calculating size_2 correctly. Remember to apply both PAGE_MASK and MALLOC_MASK to ensure proper alignment.
Safe Linking Without Heap Leak: On glibc 2.32+, attempting tcache poisoning without a heap leak will result in corruption that crashes on allocation.
Target Misalignment: The target address must be malloc-aligned (16 bytes on x64). Use (addr + 0xF) & ~0xF to align.
Forgetting Fencepost: The freed size is (top_size - FENCEPOST) & MALLOC_MASK, not just top_size. Account for the 0x20 byte fencepost.

Advantages Over House of Orange

Exploitation Strategy

Phase 1: Information Gathering

  1. Leak heap address (required for safe linking on 2.32+)
  2. Determine target address and ensure malloc alignment
  3. Calculate initial top chunk size (or probe it)

Phase 2: First Top Chunk Free

  1. Allocate chunk of size_2 (precisely calculated)
  2. Overflow to corrupt top chunk size (keep page bits)
  3. Allocate large chunk to trigger sysmalloc and _int_free
  4. First top chunk is now in tcache

Phase 3: Second Top Chunk Free

  1. Overflow to corrupt new top chunk size
  2. Calculate location of freed tcache entry
  3. Allocate large chunk to trigger second _int_free
  4. Second top chunk is now in tcache

Phase 4: Tcache Poisoning

  1. Corrupt second freed chunk’s fd pointer
  2. Apply safe linking: target ^ (fd_addr >> 12)
  3. Allocate once to get corrupted tcache entry
  4. Allocate again to get target address

House of Orange

Predecessor technique for glibc < 2.26

Tcache Poisoning

Core technique used for arbitrary allocation

House of Force

Alternative top chunk exploitation (patched in 2.29)

See Also