Overview
Poison Null Byte is a sophisticated heap exploitation technique that exploits an off-by-one vulnerability with a null byte to create overlapping chunks. This technique manipulates chunk metadata to bypass glibc’s heap consistency checks and gain control over memory layout.Glibc Compatibility: This technique works on the latest glibc versions with appropriate adaptations. The example shown works on Ubuntu 20.04 with glibc 2.32+.
What It Achieves
The Poison Null Byte technique allows an attacker to:- Create overlapping heap chunks from a single null byte overflow
- Bypass heap metadata consistency checks
- Gain arbitrary read/write primitives through chunk overlap
- Exploit off-by-one vulnerabilities that only write a null byte
The Vulnerability
The core vulnerability is a single null byte overflow that corrupts the size field of an adjacent chunk:Full Source Code
Step-by-Step Walkthrough
Allocate Padding Chunk
Allocate a large padding chunk to ensure the fake chunk’s address has
\x00 as the second lowest byte. This avoids needing to bruteforce 4 bits during exploitation.Allocate Adjacent Chunks
Create two adjacent chunks:
prev (0x500) and victim (0x4f0). These will be the targets for creating the overlap.Link into Largebin
Free chunks of varying sizes to populate the largebin. This sets up the
fd_nextsize and bk_nextsize pointers that will become our fake chunk’s fd/bk pointers.Construct Fake Chunk
Reallocate
prev and construct a fake chunk inside it with carefully crafted size metadata.Bypass Unlink Checks
Manipulate residual pointers in chunks a and b to satisfy the unlink corruption checks:
P->fd->bk == P && P->bk->fd == P.Trigger the Vulnerability
Perform the off-by-one null byte overflow into the victim chunk’s size field.
Why This Is Advanced
The Poison Null Byte technique is considered advanced because it requires:- Precise Heap Layout Control: Multiple allocations and frees must be orchestrated to set up the exact heap state
- Largebin Manipulation: Understanding of how glibc sorts chunks by size in the largebin
- Fake Chunk Construction: Creating a fake chunk that passes multiple consistency checks
- Unlink Protection Bypass: Crafting pointers to satisfy
P->fd->bk == P && P->bk->fd == P - Size Field Understanding: Knowing exactly which bytes to overwrite and how size/prev_size interact
Deep Dive: The Unlink Check
Deep Dive: The Unlink Check
The unlink macro in glibc performs this critical check:To bypass this, we must ensure:
fake_chunk->fd->bk == fake_chunk(achieved by manipulating chunk a)fake_chunk->bk->fd == fake_chunk(achieved by manipulating chunk b)
Related CTF Challenges
This technique has been used in several high-profile CTF challenges:- PlaidCTF 2015 - plaiddb: Classic poison null byte exploitation
- BalsnCTF 2019 - PlainNote: Modern adaptation with additional mitigations
Ret2 Wargames: Practice this technique interactively at Ret2 Wargames - Poison Null Byte
Implementation Notes
- On glibc 2.32+, safe-linking adds XOR obfuscation to tcache/fastbin pointers, but doesn’t affect this technique
- The padding calculation is critical to avoid ASLR bruteforce
- Barrier chunks prevent unwanted consolidation during setup
- The technique works best when you can trigger the vulnerability multiple times
See Also
- House of Einherjar - Another single null byte technique
- Overlapping Chunks - Related overlap techniques
- [Unsafe Unlink/techniques/bins/unsafe-unlink) - Understanding unlink exploitation
