1 |
|
1 | user@ubuntu:~/workspace/pwn/fastbin_dup_consolidate$ vim fastbin_dup_consolidate.c |
0x01 两次malloc后
1 | pwndbg> heap |
0x02 第一次free p1
1 | pwndbg> heap |
0x03 malloc(0x400) 分配一个 large chunk
1 | pwndbg> heap |
==fastbins中的chunk已经不见,反而出现在了smallbins中,并且chunk p2中的prev_size字段和size字段都被修改!!!==
看main_arena的bins,有两个变成了0x602000补充:large chunk的分配过程:
1
2
3
4
5
6
7
8
9
10 /*If this is a large request, consolidate fastbins before continuing.
While it might look excessive to kill all fastbins before even seeing if there is space available, this avoids fragmentation problems normally associated with fastbins.
Also, in practice, programs tend to have runs of either small or large requests, but less often mixtures, so consolidation is not invoked all that often in most programs. And the programs that it is called frequently in otherwise tend to fragment.
*/
else
{
idx = largebin_index(nb);
if(have_fastchunks(av))
malloc_consolidate(av);
}==当分配 large chunk 时,首先根据 chunk 的大小获得对应的 largebin 的 index,接着判断当前分配区的 fastbins 中是否包含 chunk,如果有,调用 malloc_consolidate() 函数合并 fastbins 中的chunk,并将这些空闲 chunk 加入unsorted bin 中。因为这里分配的是一个 large chunk,所以 unsorted bin 中的chunk 按照大小被放回smallbins 或largebins 中。==
==由于此时 p1 已经不在 fastbins 的顶部,可以再次释放 p1==
0x04:第二次free p1
1 | pwndbg> heap |
p1再次被放到fastbisn中,于是p1同时存在于fastbins和smallbins中。
第一次malloc,chunk 从fastbins中取出;
第二次malloc,chunk 从smallbins中取出。
==????为什么这里看到的是只有fastbins,smallbins没看到嘞???!!==
——->很久以后对上面的回答,确实是同时存在fastbins和smallbins中的,只是pwndbg插件输bins命令的时候smallbins中没有,但是在main_arena的bins里面还是有602000的、
0x05:void *p4 = malloc(0x40);
1 | pwndbg> heap |
0x06:p5 = malloc(0x40);
1 | pwndbg> heap |
chunk p4 和 p5在同一位置。
疑问:
为什么我调试的时候,第二次free(p1)后,fastbins里出现了chunk p1,但是通过gdb的bins查看fastbins里的确有chunk p1,但是1
2
3
4
5
6
7
8
9
10
11
12
13
14
15pwndbg> bins
fastbins
0x20: 0x602000 ◂— 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
但是最后p4和p5又的确指向同一chunk
——>上面的这个问题 我当时是想表达什么???
0x07:总结
malloc()申请一块内存
- 首先去fastbins中找
- 然后去smallbins中找
然后到largebins中寻找,但是在找之前,先执行fastbins的合并操作,合并后的这个块丢到unsortedbin中,然后进入如下这个大循环:
按照 FIFO 的方式逐个将 unsorted bin 中的 chunk 取出来
如果是 small request,则考虑是不是恰好满足,是的话,直接返回。
如果不是的话,放到对应的 bin 中。- 尝试从 large bin 中分配用户所需的内存
通过申请一个large_chunk来触发fastbins的合并,合并后被丢到unsortedbin,又会在大循环中把这个unsortedbin中的chunk放回符合他大小对应的bins中去。
此时这个被丢回smallbins的chunk可以被再次释放了(因为不在fastbins中了),所以这时fastbins里有这个块,unsortedbin里也有这个块,那么再malloc两次,这两个指向同一个。