Heap - Fastbin Dup
Introduction
Fastbin duplication is a classic heap exploitation technique that leverages from the way glibc's malloc implementation manages small memory chunks. This post demonstrates the attack step-by-step using pwndbg to visualize heap internals.
Vulnerable Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// compile with
// gcc -no-pie -Wl,-z,norelro -z now -ggdb test.c -o test
// Get this code from https://www.bordergate.co.uk/heap-fastbin-exploitation/
struct test {
char test[30];
} tests;
struct user {
char username[16];
char target[16];
} users;
int main () {
strcpy( users.target, "TARGET");
char *m_array [8];
m_array[0] = (char *)0x0;
m_array[1] = (char *)0x0;
m_array[2] = (char *)0x0;
m_array[3] = (char *)0x0;
m_array[4] = (char *)0x0;
m_array[5] = (char *)0x0;
m_array[6] = (char *)0x0;
m_array[7] = (char *)0x0;
setvbuf(stdout,(char *)0x0,2,0);
printf("Enter username: ");
read(STDIN_FILENO, users.username, 0x10);
int i;
int ChunkNumber = 0;
for (i = 1; i < 20; ++i)
{
int selection;
printf( "Target : %s\n", users.target);
printf("Next chunk number: %d/7 \n", ChunkNumber);
printf("1) malloc\n");
printf("2) free\n");
printf("3) quit\n");
printf(">");
scanf("%d", &selection);
fflush (stdin);
switch(selection){
int mallocSize;
char inputData[256];
case 1:
printf ("malloc size: \n");
scanf("%d", &mallocSize);
printf ("input data: \n");
scanf("%s", inputData);
// Allocate heap memory chunk. Size based on previous user input
char *heapChunk;
m_array[ChunkNumber] = (char *) malloc(mallocSize);
strcpy(m_array[ChunkNumber],inputData);
printf("chunk allocated: %d/7 \n", ChunkNumber);
ChunkNumber++;
break;
case 2:
printf("Select chunk to free: ");
scanf("%d", &selection);
printf("Freeing chunk: %d\n", selection);
free(m_array[selection]);
break;
case 3:
exit(0);
break;
default:
printf("Invalid selection\n");
break;
}
}
return(0);
}Target Code Analysis
Our target is to overwrite users.target (initially "Target") with arbitrary data, ultimately achieving code execution.
Vulnerability
The code has several critical vulnerabilities:
No bounds checking on malloc size.
Use-after-free-chunks can be freed but pointers remain in
m_arrayDouble-free - same chunk can be freed multiple times.
Heap overflow -
strcpyhas no size validation.
Understanding Fastbins
What are Fastbins?
Fastbins are singly-linked lists that cache small freed chunks (16-80 bytes on x64) for quick reallocation. Key characteristics:
LIFO structure (Last In, First Out)
No coalescing with adjacent chunks
Fast allocation/deallocation
Single-linked list using fd (forward) pointer
Fastbin Structure
Exploitation Steps
Step 1: Initial Setup
Start the program and enter username:

Step 2: Allocate Chunks in Fastbin Range
Allocate three chunks of size 0x18 bytes (fastbin size):

pwndbg inspection:

Step 3: Create Fastbin Dup
Free chunk 0, then chunk 1, then chunk 0 again:

pwndbg after double-free:
Step 4: Arbitrary Write Setup
Now we have chunk 0 appearing twice in the fastbin. Next allocations will return:
First malloc → Chunk 0
Second malloc → Chunk 1
Third malloc → Chunk 0 again!
Allocate chunk 0 and overwrite its fd pointer with target address:


Step 5: Overwrite Target

pwndbg verification:

Code Execution
Final exploit script:
This exploit performs a fastbin dup attack to overwrite __malloc_hook with a one_gadget address, giving you a shell when malloc is called.
Detailed Breakdown
1. Chunk Size: 0x68 (104 bytes)
0x68 (104 bytes)Why 0x68?
User requests 0x68 (104) bytes
Malloc adds 0x10 (16) bytes of metadata (prev_size + size)
Total chunk size = 0x68 + 0x10 = 0x78 (120 bytes)
This falls into the 0x70 fastbin (fastbin sizes: 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80)
We chose this size strategically to:
Stay in fastbin range (faster, less security checks)
Match a fake chunk size near
__malloc_hook
2. Offset: -35 bytes
-35 bytes

Finding the offset:
The value 0x7f (127 in decimal) appears naturally in libc memory, and it matches fastbin size 0x70!
Calculation:
__malloc_hookis at offset+0x10from chunk start (after metadata)We need to point to where size field (
0x7f) appearsIf
0x7fis at__malloc_hook - 0x23(35 bytes before)Then our fake chunk starts at
__malloc_hook - 0x23 - 0x10=__malloc_hook - 0x33
But since we target the fd pointer location (which is at chunk + 0x10), we use __malloc_hook - 35
3. Payload Size: 0x13 (19 bytes)
0x13 (19 bytes)Math:
__malloc_hookis at offset0x23(35 bytes) from fake chunk startUser data starts at offset
0x10(16 bytes)Distance =
0x23 - 0x10 = 0x13(19 bytes)So we need 19 bytes of junk, then our one_gadget address
4. One_gadget: 0xe1fa1
0xe1fa1What is this?
This is a one_gadget RCE - a single gadget in libc that executes execve("/bin/sh", NULL, NULL) when called.
How to find it:

The exploit uses 0xe1fa1 because it has constraints that are satisfied when malloc is called.
And with this we get a shell:

pwndbg Commands Cheat Sheet
Conclusion
Fastbin dup exploitation demonstrates the importance of proper memory management. While modern mitigations make these attacks harder, understanding the fundamentals helps in both offensive security and defensive programming.
References
Last updated

