unlink是利用glibc malloc 的内存回收机制造成攻击的。核心在于当两个free的堆块在物理上相邻时,会将它们合并,并将原来free的堆块在原来的链表中解链,加入新的链表中。其目的是将一个双向链表中的空闲块拿出来。前提是我们可以进行溢出修改下一个chunk的fd和bk指针。
当我们实现unlink的时候就可以进行任意地址写。然而现实是残酷的,现在的unlink加了很多保护。其中最重要的是检查p和其前后的chunk是否构成双向链表。这是一个关键的check。那么如何绕过检查呢?
64位满足以下式子32位依次类推:P->fd->bk == P <=> *(P->fd + 0x18) == P, p->bk->fd == P <=> *(p->bk + 0x10) == P。那么我们可以将fd设置为*p-0x18,bk设置为*p-0x10,那么我们就可以绕过检查。当我们free下一个chunk的时候就会进行合并,实现了unlink,那么当我们再次修改该chunk的时候指针就会指向*p-0x18的位置,进而实现任意地址写。
我们通过题目看一下具体用法。首先看保护
got表可修改,我们ida载入看一下
是一些菜单什么的,其中有一个隐藏选项,看一下
好家伙是后门函数,但是他有条件,magic处地址的值必须大于等于114514才可以执行
值得注意的是edit函数没有对我们输入的修改长度进行检查,那么我们可以使用unlink修改magic地址的值
思路:1.先申请4个较大的chunk(方便到时候我们进行伪造)。4个chunk是因为*p-0x18可以指向第一个chunk,最后一个用来free。2.编辑chunk进行伪造修改bk和fd指针,实现unlink。3.修改magic处地址的值为理想的值,选择隐藏选项得到flag。
这里采用下标为3的数组是因为当设置完bk和fd之后会指向第一个下标(*p-0x18),那么我们再次修改下标为0的chunk数据是理想数据下标为3的数组为magic地址那么相当于magic的地址为我们理想的值(3->0->magic)中间把下标为3的chunk分割成了两个chunk,伪造fd和bk以及下一个chunk的头部使当前chunk为free状态,那么再free下一个chunk就可以完成unlink。最后再进行修改就好啦。具体可以参考这个图和这个链接
标签:游戏攻略