今天打完比赛身心疲惫,来复习复习把,写一点简单的把
之所以记录一下fastbin,是因为现阶段我能接触到最多的就是它了。
程序中总是会分配一些比较小的堆块,对于这些堆块来说,如果我们直接将他们合并,那么下次申请的时候还需要重新切割出来,降低了运行的效率,所以ptmalloc设计了fastbins.
fastbins共有10个bin,分别是8-80字节,依次增加8.
使用了单链表结构对每个bin进行管理,所以只有fd有意义。
且最近被释放的chunk会被最先索引,并且最近被释放的chunk会指向前一个释放的chunk(同一个bin中的)。
当用户需要的 chunk 的大小小于 fastbin 的最大大小时, ptmalloc 会首先判断 fastbin 中相应的 bin 中是否有对应大小的空闲块,如果有的话,就会直接从这个 bin 中获取 chunk。
fastbin中的chun的inuse位始终被置为1,防止其被合并
how2heap上的一篇教程:
#include
#include
int main()
{
fprintf(stderr, "This file demonstrates a simple double-free attack with fastbins.\n");
fprintf(stderr, "Allocating 3 buffers.\n");
int *a = malloc(8);
int *b = malloc(8);
int *c = malloc(8);
fprintf(stderr, "1st malloc(8): %p\n", a);
fprintf(stderr, "2nd malloc(8): %p\n", b);
fprintf(stderr, "3rd malloc(8): %p\n", c);
fprintf(stderr, "Freeing the first one...\n");
free(a);
fprintf(stderr, "If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
// free(a);
fprintf(stderr, "So, instead, we'll free %p.\n", b);
free(b);
fprintf(stderr, "Now, we can free %p again, since it's not the head of the free list.\n", a);
free(a);
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);
fprintf(stderr, "1st malloc(8): %p\n", malloc(8));
fprintf(stderr, "2nd malloc(8): %p\n", malloc(8));
fprintf(stderr, "3rd malloc(8): %p\n", malloc(8));
}
This file demonstrates a simple double-free attack with fastbins.
Allocating 3 buffers.
1st malloc(8): 0x102b010
2nd malloc(8): 0x102b030
3rd malloc(8): 0x102b050
Freeing the first one...
If we free 0x102b010 again, things will crash because 0x102b010 is at the top of the free list.
So, instead, we'll free 0x102b030.
Now, we can free 0x102b010 again, since it's not the head of the free list.
Now the free list has [ 0x102b010, 0x102b030, 0x102b010 ]. If we malloc 3 times, we'll get 0x102b010 twice!
1st malloc(8): 0x102b010
2nd malloc(8): 0x102b030
3rd malloc(8): 0x102b010
先依次分配三个大小为8的堆块a,b,c,地址为0x102b010,0x102b030,0x102b050
然后free chunk a,此时的chunk a被放到了fastbin的第一个bin的链表的第一个,所以不可以再次free
然后free chunk b, 此时由于先进后出的策略,chunk b被放到了链表的首位,它的fd指向了chunk a
这是我们再次free chunk a,此时a不在链表的首位,所以可以被free。
所以被free后顺序为a -> b -> a (箭头为fd所指)
之后如果我们再次malloc三个大小为8的堆块d,e,f,那么d f 实际上是指向同一块区域的。
malloc后:
0x602000 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x21
}
0x602020 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x21
}
0x602040 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x20fa1
}
0x602060 PREV_INUSE {
prev_size = 0,
size = 135073,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
free a,a成功进入了fastbins里面:
0x602000 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x21
}
0x602020 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x21
}
0x602040 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x20fa1
}
0x602060 PREV_INUSE {
prev_size = 0,
size = 135073,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
pwndbg> fastbins
fastbins
0x20: 0x602000 ◂— 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
free b ,chunk b的fd指向了chunk a的地址,并且b出现在了fastbin的头部
0x602000 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x21
}
0x602020 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x602000,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x21
}
0x602040 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x20fa1
}
0x602060 PREV_INUSE {
prev_size = 0,
size = 135073,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
pwndbg> fastbins
fastbins
0x20: 0x602020 —▸ 0x602000 ◂— 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
再次free a, chunk a的fd指向了chunk b,fastbin顺序变成了a->b->a:
0x602000 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x602020,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x21
}
0x602020 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x602000,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x21
}
0x602040 FASTBIN {
prev_size = 0,
size = 33,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x20fa1
}
0x602060 PREV_INUSE {
prev_size = 0,
size = 135073,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
pwndbg> fastbins
fastbins
0x20: 0x602000 —▸ 0x602020 ◂— 0x602000
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0