获取中...

-

Just a minute...

fastbin attack是一类漏洞的利用方法,是指所有基于 fastbin 机制的漏洞利用方法。主要利用了fast bin的单链表管理机制。

相关源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
If the size qualifies as a fastbin, first check corresponding bin.
This code is safe to execute even if av is not yet initialized, so we
can try it without checking, which saves some time on this fast path.
*/

if ((unsigned long) (nb) <= (unsigned long) (get_max_fast())) {
// 得到对应的fastbin的下标
idx = fastbin_index(nb);
// 得到对应的fastbin的头指针
mfastbinptr *fb = &fastbin(av, idx);
mchunkptr pp = *fb;
// 利用fd遍历对应的bin内是否有空闲的chunk块,
do {
victim = pp;
if (victim == NULL) break;
} while ((pp = catomic_compare_and_exchange_val_acq(fb, victim->fd, victim)) != victim);

这里首先根据所需chunk的大小获得该chunk所属fast bin的index,根据该index获得所需fast bin的空闲chunk链表指针,然后将头指针的下一个chunk(victim->fd)作为空闲chunk链表的头部(取出头部的chunk)。
这里是通过fd指针来获取下一个chunk的。所以如果可以控制某个fast bin中chunk的fd指针的值,那么在取出这个chunk后,fd指针指向的内存将会作为下一个将要被取出的内存,再次申请这个大小的内存,也就实现了在任意地方分配chunk的目的。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 存在可以利用的chunk
if (victim != 0) {
// 检查取到的 chunk 大小是否与相应的 fastbin 索引一致。
// 根据取得的 victim ,利用 chunksize 计算其大小。
// 利用fastbin_index 计算 chunk 的索引。
if (__builtin_expect(fastbin_index(chunksize(victim)) != idx, 0)) {
errstr = "malloc(): memory corruption (fast)";
errout:
malloc_printerr(check_action, errstr, chunk2mem(victim), av);
return NULL;
}
...
}

还需要绕过检测,malloc会检查取到的chunk的size是否是符合这个fast bin,所以想要在任意地方分配一个chunk,需要先想办法在此处构造合适的size来通过这个检查。

原理

fastbin使用单链表维护释放的堆块,由 fastbin 管理的 chunk 即使被释放,但next_chunk 的 prev_inuse 位也不会被清空。

fastbin单向链表储存结构

fastbins的存储采用后进先出(LIFO)的原则:后free的chunk会被添加到先free的chunk的后面。同理,通过malloc取出chunk时是先去取最新放进去的
因此,fastbins中的所有chunk的bk是没有用到的,因为是单链表。
并且fastbins比较特殊,一个fastbin链第一个chunk指向于一个特殊的“0”,然后后面接的是后free的chunk……以此类推,最后一个chunk再由arena的malloc_state的fastbinsY数组所管理

步骤一:被free的chunk会被放入到arena所管理的fastbins链中。如果此时我们malloc一个堆块p,并将其free到fastbin链中,但是我们的p指针没有置空,所以仍然指向于这个freechunk的fd成员处.

1
2
char *p=malloc(size);
free(p);

步骤二:释放之后,arena管理的fastbin中bin头的fd指针指向于我们申请的这个chunk,p指针就是chunk的fd,如上所示

步骤三:这个chunk的fd指针本来指向于数值0,此时我们通过p指针将fd指针指向于我们的target地址

1
*p=target

步骤四:malloc与我们释放的chunk相等大小的chunk,那么被上面被free掉的chunk就会从fastbin单链表中移除,根据fastbin链表的单链表结构,此时arena的fastbin的bin头的fd指针指向于我们的target地址了

1
char *q=malloc(size);

步骤五:由于此arena的fastbin的bin头的fd指针指向于我们的target地址了。此时我们再去malloc的时候,就是把target这块地址malloc出来给应用层使用了,此时我们就可以使用返回的target的指定地址,对target进行读写了

1
char *r=malloc(size);

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
#include<stdlib.h>
#include<unsitd.h>
int main()
{
void *chunk1,*chunk2,*chunk3;
chunk1=malloc(0x30);
chunk2=malloc(0x30);
chunk3=malloc(0x30);
sleep(1);
free(chunk1);
free(chunk2);
free(chunk3);
return 0;
}

释放之前

1
2
3
4
5
6
7
8
9
10
11
12
13
0x602000:	0x0000000000000000	0x0000000000000041 <===chunk1
0x602010: 0x0000000000000000 0x0000000000000000
0x602020: 0x0000000000000000 0x0000000000000000
0x602030: 0x0000000000000000 0x0000000000000000
0x602040: 0x0000000000000000 0x0000000000000041 <===chunk2
0x602050: 0x0000000000000000 0x0000000000000000
0x602060: 0x0000000000000000 0x0000000000000000
0x602070: 0x0000000000000000 0x0000000000000000
0x602080: 0x0000000000000000 0x0000000000000041 <===chunk3
0x602090: 0x0000000000000000 0x0000000000000000
0x6020a0: 0x0000000000000000 0x0000000000000000
0x6020b0: 0x0000000000000000 0x0000000000000000
0x6020c0: 0x0000000000000000 0x0000000000020f41 <===top chunk

还没有释放,bins链为空

)

释放chunk1

1
2
3
4
5
6
7
8
9
10
11
12
13
0x602000:	0x0000000000000000	0x0000000000000041 <===chunk1
0x602010: 0x0000000000000000 0x0000000000000000
0x602020: 0x0000000000000000 0x0000000000000000
0x602030: 0x0000000000000000 0x0000000000000000
0x602040: 0x0000000000000000 0x0000000000000041 <===chunk2
0x602050: 0x0000000000000000 0x0000000000000000
0x602060: 0x0000000000000000 0x0000000000000000
0x602070: 0x0000000000000000 0x0000000000000000
0x602080: 0x0000000000000000 0x0000000000000041 <===chunk3
0x602090: 0x0000000000000000 0x0000000000000000
0x6020a0: 0x0000000000000000 0x0000000000000000
0x6020b0: 0x0000000000000000 0x0000000000000000
0x6020c0: 0x0000000000000000 0x0000000000020f41 <===top chunk

一个fastbin链第一个chunk指向于一个特殊的“0”

)

释放chunk2后

1
2
3
4
5
6
7
8
9
10
11
12
13
0x602000:	0x0000000000000000	0x0000000000000041 <===chunk1
0x602010: 0x0000000000000000 0x0000000000000000
0x602020: 0x0000000000000000 0x0000000000000000
0x602030: 0x0000000000000000 0x0000000000000000
0x602040: 0x0000000000000000 0x0000000000000041 <===chunk2
0x602050: 0x0000000000000000 0x0000000000000000
0x602060: 0x0000000000000000 0x0000000000000000
0x602070: 0x0000000000000000 0x0000000000000000
0x602080: 0x0000000000000000 0x0000000000000041 <===chunk3
0x602090: 0x0000000000000000 0x0000000000000000
0x6020a0: 0x0000000000000000 0x0000000000000000
0x6020b0: 0x0000000000000000 0x0000000000000000
0x6020c0: 0x0000000000000000 0x0000000000020f41 <===top chunk

释放chunk1然后再释放chunk2,并且查看bins信息(可以看到两个chunkfree之后直接存储在fastbins的0x40bin链上),并且chunk2的fd指针指向前一个chunk的chunk头处,第一个chunk的fd指向的是特殊的“0”

)

释放chunk3后

1
2
3
4
5
6
7
8
9
10
11
12
13
0x602000:	0x0000000000000000	0x0000000000000041 <===chunk1
0x602010: 0x0000000000000000 0x0000000000000000
0x602020: 0x0000000000000000 0x0000000000000000
0x602030: 0x0000000000000000 0x0000000000000000
0x602040: 0x0000000000000000 0x0000000000000041 <===chunk2
0x602050: 0x0000000000000000 0x0000000000000000
0x602060: 0x0000000000000000 0x0000000000000000
0x602070: 0x0000000000000000 0x0000000000000000
0x602080: 0x0000000000000000 0x0000000000000041 <===chunk3
0x602090: 0x0000000000000000 0x0000000000000000
0x6020a0: 0x0000000000000000 0x0000000000000000
0x6020b0: 0x0000000000000000 0x0000000000000000
0x6020c0: 0x0000000000000000 0x0000000000020f41 <===top chunk

chunk3的fd指向chunk2,chunk2的fd指向chunk1,chunk1做为fastbin链的第一个指向特殊的“0”

)

相关文章
评论
分享
  • Alloc to Stack&Arbitary Alloc

    Alloc to Stack和Arbitary Alloc都利用了fastbin链表的特性。 Alloc To Stack利用了fastbin链表的特性。当前的chunk的fd指向下一个chunk。Alloc To Stack核心...

    Alloc to Stack&Arbitary Alloc
  • House of Spirit

    House of Spirit针对fastbin,也是fastbin attach的一种。核心在于在目标位置处伪造 fastbin chunk,并将其释放,从而达到分配指定地址的 chunk 的目的。 原理House of Spi...

    House of Spirit
  • Fastbin Double Free

    double free 是任意地址写的一种技巧,指堆上的某块内存被释放后,并没有将指向该堆块的指针清零,那么,我们就可以利用程序的其他部分对该内存进行再次的free, 利用条件Fastbin Double Free 能够成功利用主...

    Fastbin Double Free
Please check the parameter of comment in config.yml of hexo-theme-Annie!