Why Heap Exploitation Techniques Keep Evolving
Every time a kernel-hardening patch lands, some marketing department fires off a press release about an âunbreakableâ memory allocator. A quarter later, a research team or a red team engagement shows the new scheme just moved the goalposts. The heap isnât a solved problem. Itâs a shifting puzzle where the rules change with each compiler update, each libc revision, and each new hardware-enforced control-flow integrity mechanism. If you work at the hardware-software interface on x86 or ARM64, you already know the allocator isnât a black boxâitâs a battlefield.

The Allocator as a Moving Target
Modern heap exploitation isnât about smashing a static buffer. Itâs about understanding the implicit algorithms that govern chunk allocation, coalescing, and free-list management. The ptmalloc family inside glibc has been aggressively restructured. The arrival of tcache in glibc 2.26 was a performance win that also handed exploit developers a fast, corruption-friendly cache of singly-linked lists. The predictable response: safe-linking in glibc 2.32, which XORs the next pointer with the chunkâs own address shifted right by 12 bits. A neat trick, but it only raises the bar for information leaksâit doesnât erase the fundamental problem of dangling pointers.
On Windows, the Low Fragmentation Heap front-end and the segment heap in recent builds have made generic heap sprays less reliable. Yet the internal structuresâ_HEAP, _HEAP_SEGMENT, _LFH_BLOCKâstill lean on predictable encodings and weak integrity checks. The _HEAP_ENTRY header, with its encoded size and flags, gets forged routinely. The move to HEAP randomization and guard pages is a mitigation, not a fix. It forces attackers to chain multiple vulnerabilities, but the primitives for an arbitrary write stay intact once you leak the heap base and decode the cookie.
Why Mitigations Create New Attack Surface
Hereâs the core irony: every mitigation introduces new metadata, new state transitions, or new performance optimizations that can be corrupted. The tcache in glibc is a textbook example. It was added to speed up single-threaded allocations, but its early lack of integrity checks made it a favorite target. When checks arrived, attackers moved to the fastbin reverse-into-tcache stashing unlink attack. When that got mitigated, the focus shifted to corrupting the tcache_perthread_struct to control the chunk count, enabling double-free scenarios. The pattern is relentless: a new feature or optimization lands, its internal invariants get reverse-engineered, and those invariants become the new exploitation primitives.
ARM64 systemsâespecially Android devices running jemalloc or scudoâarenât immune. Scudoâs quarantines and header canaries raise the bar, but side-channel attacks on the quarantine delay or misaligned chunk metadata can still yield strong primitives. The hardware-software interface is where the most interesting bugs live: cache-coherency issues, speculative execution side effects, and the interaction between the Memory Management Unit and the allocatorâs view of virtual memory. Exploitation isnât just about corrupting a linked list anymore; itâs about understanding the entire memory-ordering model of the platform.

Practical Evolution: From Unlink to Tcache Poisoning
If youâve been in this game for more than a decade, you remember the classic unlink macro exploit. A single write-what-where primitive, born from trusting the forward and backward pointers of a chunk being removed from a doubly-linked list. The mitigationâa simple pointer sanity checkâseemed solid at the time. It only forced attackers to find other metadata to corrupt. The evolution since then has been a masterclass in shifting trust boundaries:
- House of Force: Abusing the top chunk size to relocate the wilderness to an arbitrary address. Mitigated by adding a size check against the systemâs available memory, but the concept of corrupting the top chunk remains relevant in constrained scenarios.
- House of Spirit: Forcing a free on a crafted fake chunk to gain an arbitrary allocation. Mitigations focused on validating the chunkâs size and alignment, but the technique persists in allocators with weaker checks, such as certain embedded or real-time systems.
- Fastbin Dup: Double-freeing a fastbin chunk to create a cycle in the singly-linked list, leading to overlapping allocations. The
tcacheinitially made this trivial; the addition of akeyfield to detect double-frees was bypassed by clearing the key, then by usingcallocto bypass the tcache, and later by corrupting the tcache count to drain chunks into the fastbin. - Tcache Poisoning: The modern classic. Overwriting the next pointer of a freed tcache chunk to achieve an arbitrary write. Safe-linking made this harder, but a heap leak (often from a partial overwrite or an uninitialized read) defeats it. The technique is now standard in capture-the-flag competitions and real-world exploits alike.
Each of these techniques isnât just a trick; itâs a response to a specific set of constraints imposed by the allocator. The evolution isnât random. It follows the path of least resistance through the allocatorâs internal data structures.
Why the Hardware-Software Interface Matters
On x86 and ARM64, the heap isnât an isolated software construct. It interacts with the Translation Lookaside Buffer, cache-coherency protocols, and the memory model. For example, the order in which a chunkâs header fields are written back to memory can create a window for a race condition if another thread is concurrently freeing an adjacent chunk. These arenât theoretical concerns. Real-world exploits have used cache-timing side channels to leak heap addresses, bypassing Address Space Layout Randomization without a direct information leak.
ARM64âs Pointer Authentication adds another layer. A signed pointer stored in a heap metadata field can be forged if you can leak the signing key or if the signature algorithm has a collision. The allocatorâs use of PAC is often an afterthought, bolted onto existing structures. This creates mismatches: a pointer is authenticated, but the size field it protects is not, or the authentication is only checked on the fast path, not during coalescing. These gaps are where the next generation of exploitation techniques will emerge.

Why the âUnbreakableâ Claims Are Noise
Every few years, a new allocator design gets hyped as the end of heap exploitation. Partition allocators, type-based allocators, garbage-collected heapsâthey all reduce the attack surface for certain bug classes, but they introduce new ones. A type-based allocator that separates allocations by size and type prevents a use-after-free on a string from corrupting a function pointer, but it does nothing to stop a use-after-free on two objects of the same type. The real world is messy. Complex applications mix custom allocators with system allocators, and the interaction between them is a rich source of bugs.
Consider the Android ecosystem. The introduction of Scudo as the default native allocator was a significant hardening step. Yet researchers quickly found ways to bypass its checks by targeting the metadata stored in the header of each chunk, or by exploiting race conditions in the quarantine. The lesson isnât that Scudo is weak; itâs that any allocator with a complex internal state is vulnerable to logic bugs. The only truly secure heap is one that doesnât existâand since we need dynamic memory allocation, weâre stuck with this arms race.
What This Means for Your Work
If youâre writing exploits, treat the allocator as a puzzle box that changes with every patch. Your techniques must be modular. The core primitivesâleaking a heap address, achieving an arbitrary write, controlling the allocation sizeâare the building blocks. The specific allocator state transitions you corrupt are just the current meta. If youâre on the defensive side, stop pretending that a single mitigation is a solution. You need defense in depth: randomizing heap bases, adding canaries, enabling guard pages, and using hardware features like ARMâs Memory Tagging Extension are all layers, not silver bullets.
MTE is particularly interesting. It assigns a 4-bit tag to each 16-byte granule of memory and checks the tag on each load and store. This can catch linear overflows and use-after-free bugs with high probability. But itâs not foolproof. The tag space is small, so a determined attacker can brute-force it, and it does nothing to stop corruption of the metadata that stores the tags themselves. The hardware-software interface is still the weak point.
FAQ
Why do heap exploitation techniques change so frequently?
Because the internal implementation of allocators isnât stable. Performance optimizations, new security features, and changes in the underlying hardware all alter the layout and behavior of heap metadata. Each change breaks existing techniques and creates new opportunities for corruption. The fundamental primitivesâarbitrary write, information leak, control of allocation sizeâremain constant, but the path to achieving them shifts with every libc or kernel update.
Is there a single allocator that is immune to exploitation?
No. Every allocator that manages dynamic memory must maintain metadata to track free and used chunks. That metadata is a target. Even in garbage-collected environments, the collectorâs internal structures can be corrupted. The question isnât whether an allocator can be exploited, but how much effort is required. Hardened allocators raise the cost, but they donât eliminate the risk.
How does hardware like ARMâs MTE change the game?
MTE provides probabilistic detection of spatial and temporal memory errors by assigning tags to memory regions and pointers. It can catch many common heap bugs, but itâs not a complete solution. The tag space is limited, so attackers can brute-force tags. MTE doesnât protect against corruption of the tag storage itself or against logic errors that misuse a correctly tagged pointer. Itâs a powerful layer, but it must be combined with sound allocator design and other mitigations.
Where Do We Go From Here?
The next frontier is the intersection of heap exploitation and speculative execution. Allocators that use pointer authentication or memory tagging rely on the assumption that the hardware will correctly enforce these checks. But microarchitectural side channels can leak the tag values or authentication codes, effectively bypassing the hardware protections. This isnât a theoretical concern; researchers have already demonstrated Spectre-type attacks that leak PAC keys. The heap is just another surface for these attacks.
For the practitioner, this means the skill set must expand. You canât just know glibc internals; you need to understand the branch predictor, the cache hierarchy, and the specifics of the ARM or x86 memory model. The days of simple buffer overflows are long gone. Todayâs heap exploitation is a systems-level discipline that requires patience, precision, and a healthy dose of cynicism toward any vendorâs security claims.
If youâre building a career in this niche, focus on the primitives, not the tricks. Learn to read allocator source code as fluently as you read disassembly. And never, ever trust a patch note that says a heap is now âsecure.â