0x00:
1 |
|
接上1
2
3
4
5
6
7
8
9
10
11 fprintf(stderr, "Allocating 3 buffers.\n");
char *d = malloc(9);
char *e = malloc(9);
char *f = malloc(9);
strcpy(d,"DDDDDDDD");
fprintf(stderr, "4st malloc(9) %p points to %s the first time\n",d,d);
strcpy(e,"EEEEEEEE");
fprintf(stderr, "5nd malloc(9) %p points to %s\n",e,e);
strcpy(f,"FFFFFFFF");
fprintf(stderr, "6rd malloc(9) %p points to %s the second time\n",f,f);
}
源代码中可以看出, 在前面把a free了两遍。
1 | user@ubuntu:~/workspace/pwn/fastbin_dup$ vim fastbin_dup.c |
==这个程序展示了利用fastbins的double-free攻击,可以泄漏出一块已经被分配的内存指针。fastbins可以看成一个LIFO的栈,使用单链表实现,通过 fastbin->fd来遍历fastbins。由于 free的过程会对free list做检查,我们不能连续两次free同一个chunk,所以这里在两次free之间,增加了一次对其他chunk的free 过程,从而绕过检查顺利执行。然后再malloc三次,就在同一个地址malloc了两次,也就有了两个指向同一块内存区域的指针。==
1 | /* Check that the top of the bin is not the record we are going to add |
0x01:三次malloc后
1 | pwndbg> heap |
0x02:free(a)
1 | pwndbg> heap |
被free后,fd 原本被填充的AAAAAAAA被清零,这个chunk也被加入到fastbins中。
但是这个chunk a被free后,并==没有使chunk b的pre_size和size的pre_inuse改变==,不像上一篇的first_fit那个free后chunk b的字段被改变,也没放到unsorted bins中,而是被放到了fastbins中
0x03:free(b)
1 | pwndbg> heap |
==chunk b被放入fastbins中,成为新的表头,chunk b的fd字段里存着上一个chunk的地址,即chunk a 的地址:0x602000==
0x04:free(a)
1 | pwndbg> heap |
又再次free了 a,此时fastbins的表头变成了chunk a的地址,即0x602000,它的fd里的值是上一个表头里的值,即chunk b的地址,即0x602020。chunk b里的fd值依旧是 chunk a 的值。形成了一个闭环 a -> b -> a
0x05:malloc
1 | char *d = malloc(9); |
1 | pwndbg> heap |
0x06:
1 | strcpy(d,"DDDDDDDD"); |
1 | pwndbg> heap |
1 | strcpy(e,"EEEEEEEE"); |
1 | pwndbg> heap |
1 | strcpy(f,"FFFFFFFF"); |
1 | pwndbg> heap |
这里把chunk a原来的”DDDDDDDD”覆盖为”FFFFFFFF”,即是说d指针与f指针指向同一个chunk mem处。
所以通过double-free可以泄露出一个chunk的指针。
总结:
double-free的触发是:==连续==free==同==一个chunk。
可以通过double-free泄漏出一个堆块的指针。指向同一个内存区域的指针。