| name | double-free-exploitation |
| description | How to identify, understand, and exploit double-free heap vulnerabilities in C programs. Use this skill whenever the user mentions double-free, heap corruption, memory allocator attacks, fast bin dup, tcache poisoning, or any heap-based vulnerability in C code. Also trigger when users are working on CTF challenges involving heap exploitation, analyzing malloc/free patterns, or debugging memory corruption issues. |
Double-Free Heap Exploitation
A skill for understanding and exploiting double-free vulnerabilities in C programs.
What is a Double-Free?
A double-free occurs when the same memory block is freed more than once. This corrupts the heap allocator's internal data structures and can lead to:
- Memory corruption: Allocator metadata gets corrupted
- Overlapping pointers: Two pointers reference the same memory location
- Arbitrary writes: Attacker can control memory through one pointer affecting another
- Code execution: Can lead to ROP chains or shellcode execution
How It Works
The Mechanism
- First free: Memory block goes into a free list (fast bin or tcache)
- Second free: If another chunk is freed in between, the double-free check is bypassed
- Result: The same block appears twice in the free list
- Exploitation: When reallocating, you get overlapping pointers
Fast Bin Dup (Classic Double-Free)
free(a); free(b); free(c); free(d); free(e); free(f); free(g);
free(h);
free(i);
free(h);
char *i1 = malloc(10);
char *i2 = malloc(10);
Tcache Poisoning Variant
When tcache is involved, you can use null-byte overflows to corrupt size fields:
- Allocate chunks A, B, C of size 0x110
- Free B, then free A
- Reallocate A and overflow with null byte
- B's size becomes 0x100 instead of 0x111
- Free B again - now you have two tcache entries pointing to same address
Identifying Double-Free Vulnerabilities
Code Patterns to Look For
void *ptr = malloc(100);
free(ptr);
free(ptr);
if (condition) {
free(ptr);
}
free(ptr);
void process(void *data) {
free(data);
}
Debugging with GDB/Pwndbg
break free
watch *(void **)ptr
heap
heap chunks
vmmap
Exploitation Techniques
Technique 1: Fast Bin Dup for Address Disclosure
When you can't directly overwrite __malloc_hook:
- Fill tcache with 7 freed chunks of the same size
- Double-free a chunk (with intervening free)
- Reallocate to get overlapping pointers
- Write PIE address through one pointer
- Read through other pointer to leak address
- Calculate base address and proceed with ROP
Technique 2: Fast Bin Dup for Code Execution
- Target main_arena (contains PIE addresses, near
__malloc_hook)
- Allocate chunk at specific offset of main_arena
- Continue allocating until reaching
__malloc_hook
- Overwrite __malloc_hook with shellcode address
- Trigger malloc to execute shellcode
Technique 3: Tcache Poisoning
- Create double-free in tcache (not fast bin)
- Use overlapping pointers to corrupt tcache fd pointer
- Redirect malloc to arbitrary address
- Overwrite GOT entry or function pointer
Practical Example
Vulnerable Code Analysis
#include <stdio.h>
#include <stdlib.h>
int main() {
char *a = malloc(10);
char *b = malloc(10);
char *c = malloc(10);
free(a);
free(b);
free(a);
char *a1 = malloc(10);
char *a2 = malloc(10);
strcpy(a1, "controlled");
return 0;
}
Exploitation Steps
- Identify the double-free: Look for
free(ptr) called twice on same pointer
- Verify with debugger: Check if addresses overlap after reallocation
- Plan the attack: Decide what you want to overwrite (GOT, function pointer, etc.)
- Craft the payload: Write through one pointer to affect the other
- Trigger the exploit: Call the function or trigger the code path
Common CTF Patterns
Dragon Army (HTB)
- Can only allocate fast-bin-sized chunks except 0x70
- Can't directly overwrite
__malloc_hook
- Use PIE addresses (start with 0x56) as target
- Target
main_arena offset to reach __malloc_hook
Zero to Hero (PicoCTF)
- Uses tcache bins with null-byte overflow
- Corrupts size field from 0x111 to 0x100
- Creates double-free in tcache
- Leverages tcache poisoning for exploitation
Prevention and Mitigation
For Developers
void *ptr = malloc(100);
free(ptr);
ptr = NULL;
std::unique_ptr<char[]> ptr(new char[100]);
For Security Testing
- Static analysis: Use tools like AddressSanitizer
- Dynamic analysis: Run with ASan to detect double-frees
- Code review: Look for all
free() calls and trace pointer ownership
References
Quick Reference
| Technique | When to Use | Key Requirement |
|---|
| Fast Bin Dup | Classic double-free | 7 freed chunks to fill tcache |
| Tcache Poisoning | Modern glibc | Tcache enabled, size field corruption |
| Address Disclosure | PIE binaries | Need to leak addresses first |
| Code Execution | Full control | Can overwrite function pointers |