源代码 演示了double free
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main() 5 { 6 fprintf(stderr, "This file demonstrates a simple double-free attack with fastbins.\n"); 7 8 fprintf(stderr, "Allocating 3 buffers.\n"); 9 int *a = malloc(8); 10 int *b = malloc(8); 11 int *c = malloc(8); 12 13 fprintf(stderr, "1st malloc(8): %p\n", a); 14 fprintf(stderr, "2nd malloc(8): %p\n", b); 15 fprintf(stderr, "3rd malloc(8): %p\n", c); 16 17 fprintf(stderr, "Freeing the first one...\n"); 18 free(a); 19 20 fprintf(stderr, "If we free %p again, things will crash because %p is at the top of the free list.\n", a, a); 21 // free(a); 22 23 fprintf(stderr, "So, instead, we'll free %p.\n", b); 24 free(b); 25 26 fprintf(stderr, "Now, we can free %p again, since it's not the head of the free list.\n", a); 27 free(a); 28 29 fprintf(stderr, "Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!\n", a, b, a, a); 30 fprintf(stderr, "1st malloc(8): %p\n", malloc(8)); 31 fprintf(stderr, "2nd malloc(8): %p\n", malloc(8)); 32 fprintf(stderr, "3rd malloc(8): %p\n", malloc(8)); 33 }
运行结果
checksec
先申请了3块8字节内存,由于64位内存16字节对齐,所以加上头部0x10字节,都为0x20字节
查看堆分布
之后释放a,a进入0x20的fastbin链表,在头部处
此时如果再释放a,由于a在链表头部,inux堆管理机制不允许这么做,会报错
所以释放b b->fd=a a->fd=null
此时b在链表头部,所以a又可以释放了
b->fd=a a->fd=b
此时0x20fastbin链表情况 a->b->a
此时再申请3次8字节的内存,会依次从0x20的fastbin链表中取出释放的堆块
遵循后进先出原则
3次申请的内存记为a1,b1,c1
a1分配到a的内存 b1分配到b的内存 c1分配到a的内存
造成了a1和c1都指向同一块内存,即a的内存
即造成了double free