![](https://csdnimg.cn/release/download_crawler_static/88639267/bg5.jpg)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在 malloc.c 中我们可以 找到, 这里的 __assert_fail 就是__malloc_assert ,即在 这里调 用
assert_fail 就相当于调用__malloc_assert。而__assert_fail 是在 assert 函数中被调用,因此只
需要找到在 malloc 函数中何处调用了 assert 函数即可。但 assert 函数调用的地方实在太多,
我们应该选择哪一个呢?注意在_int_malloc 函数中,所有针对堆的检查错误信息打印都是使
用 malloc_printerr 函数而非 assert。因此我们选择_int_malloc 函数调用的 sysmalloc 函数。
在 sysmalloc 函数中有检查是使用 assert 来实现的,而在_int_malloc 函数中只有当完全确认
释放的 chunk 无法满足申请需求且 top chunk 的大小也小于申请大小时才会调用 sysmalloc 函
数。我们首先分析一下进入 sysmalloc 函数之后应该如何做才能拿到 flag,至于如何调用
sysmalloc 函数,则是堆块排布方面的事情了,我们在后面也会提到。
在 sysmalloc 函数中,有这样一条 assert 语句:
// malloc.c line 2617
assert ((old_top == initial_top (av) && old_size == 0) ||
((unsigned long) (old_size) >= MINSIZE &&
prev_inuse (old_top) &&
((unsigned long) old_end & (pagesize - 1)) == 0));
1
2
3
4
5
这是用来检查 top chunk 的一些属性,其中注意最后一行,top chunk 必须页对齐。如果这里
的 top chunk 没有满足页对齐,那么就会调用__assert_fail 函数,也即__malloc_assert 函数。
而在__malloc_assert 函数中,经过调试发现,漏洞利用是发生在调用__fxprintf 中而非 fflush
函数。这是因为当我们执行到 assert 失败时,_IO_FILE 应该已经被我们修改,而__fxprintf 作
为一个需要将字符串输出到控制台的函数,必然会调出 stderr 文件描述符进行输出。但这个
时候只有我们自己伪造的_IO_FILE 指针,只要我们构造好假的 stderr,就有可能实现任意代