以前没怎么弄过堆溢出问题,直到最近看见Google研究团队发布了关于dnsmasq的一系列问题 (需要翻墙)
其中有两个CVE涉及到了Heap Overflow。
其中的基础知识不再赘述,可以直接参考以下链接学习
1.Linux堆内存管理深入分析(上)
2.Linux堆内存管理深入分析(下)
3.Linux堆溢出漏洞利用之unlink
至此,基本的堆溢出原理就已经很明白了。
但是在最新的glibc中unlink的宏已经被修改,如下所示
#define unlink(AV, P, BK, FD)
{
if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0))
malloc_printerr ("corrupted size vs. prev_size");
FD = P->fd;
BK = P->bk;
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
malloc_printerr ("corrupted double-linked list");
else
{
FD->bk = BK;
BK->fd = FD;
if (!in_smallbin_range (chunksize_nomask (P)) && __builtin_expect (P->fd_nextsize != NULL, 0))
{
if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0))
malloc_printerr ("corrupted double-linked list (not small)");
if (FD->fd_nextsize == NULL)
{
if (P->fd_nextsize == P)
FD->fd_nextsize = FD->bk_nextsize = FD;
else
{
FD->fd_nextsize = P->fd_nextsize;
FD->bk_nextsize = P->bk_nextsize;
P->fd_nextsize->bk_nextsize = FD;
P->bk_nextsize->fd_nextsize = FD;
}
}
else
{
P->fd_nextsize->bk_nextsize = P->bk_nextsize;
P->bk_nextsize->fd_nextsize = P->fd_nextsize;
}
}
}
}
其中关键的部分为
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
这里就要求我们能找到一个ptr指向一个P,而P为堆上的分配的空间。
如何绕过此处,请参考如下链接
4.unlink绕过