unlink_堆溢出
unlink_堆溢出
unlink是一种机制,简单来说,把一个双向链表中的空闲块拿出来,然后与其物理相邻的刚刚free掉的堆块进行合并,那其中如何将这个空闲的块拿出来便成了问题,我们来看看,系统是如何操作的:
其实可以清楚的看到,简单来说其实就两个步骤,第一:让FD->bk=BK,第二:让BK->fd=FD,当然,在unlink之前,是有一些检查的,防止我们的恶意操作,它的检查也分为两个点,第一:P->Fd->bk = P,第二:P->bk->Fd = P。简单来说呢,就是上图的第一张图片,从P指出去又要指回来。那这种检查呢,给我们了可以操作的空间,我们只需要找到一个地址,这个地址里面记录着一个数据就可以了,那么这个数据应该是啥?没错,这个数据就是P的chunk头的头地址,我来详细的解释一下(如下图,地址均为虚标):
所以能不能伪造成功,就是看有没有地址记录P的头地址,所以利用起来也是有一定的难度的。这时我们的检查就完毕了,那么unlink结束,我们的数据是否会发生变化呢,答案是会的,我们接下来来看unlink进行的操作,首先是FD->bk=BK,然后是BK->fd=FD,这两个操作我们上面说过了,所以呢,当FD->bk=BK执行完毕,0x40430处的数据就要发生改变了,由0x6020300变成0x40430-0x10,继续执行BK->fd=FD,0x40430处的数据就要由0x40430-0x10变成0x40430-0x18,所以unlink是会改写0x40430处(存放P头地址的地址)的数据的。这就是unlink的全部阶段。
可能图呢,也会有一些的看不懂,我来稍微解释一下,我们来看第一张图时,需要总结出来这么一点,就是P的Fd指向的就是大FD,P的bk指向的就是大的BK(把这一点应用到图二就可以了)
如果图二看不懂,需要这样想,P的Fd和bk指向的地方,对于计算机(程序)来讲,它指向的就是chunk的位置,如果我们自己补上chunk的结构在图二上,那么将会一目了然。