unlink
1、简介:俗称脱链,就是将链表头处的free堆块unsorted bin中脱离出来,然后和物理地址相邻的新free的堆块合并成大堆块(向前合并或者向后合并),再放入到unsorted bin中。
2、危害原理:通过伪造free状态的fake_ chunk, 伪造fd指针和bk指针,通过绕过unlink的检测实现unlink,un'link就 会往p所在的位置写入p-0x18,从而实现任意地址写的漏洞。
3、漏洞产生原因:
unlink的源码如下:
其中的检查机制
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
malloc_printerr (check_action, "corrupted double-linked list", P, AV);
在unlink之前会检查一下当前结点的前一个结点的后一个节点和当前结点的后一个节点的前一个节点是不是同一个结点,要想成功unlink,必须绕过这个检测,一种思路是将chunk->fd设置为(&chunk_addr - 0x18),因为:
chunk->fd->bk == *(chunk->fd + 0x18) == *(&chunk_addr - 0x18 + 0x18) == chunk_addr
这样就满足了检测条件,同理需要将chunk->bk设置为(&chunk_addr-0x10)。检测之后进行unlink操作
unlink|绕过&利用
1、伪造如下: chunk = 0x0602280 (P是将要合并到的堆地址,P存在于chunk中,相当于*chunk=P ) P_ fd = chunk-0x18 = 0x602268 P_ bk = chunk-0x10 = 0x602270 2、绕过技巧: define unlink(P, BK, FD) { FD= P->fd; \FD = 0x602268 BK= P->bk; \BK = 0x602270 if(_ builtin_ expect (FD->bk != P|I BK->fd != P, 0)) \FD->bk = *(0x602268+0x18) | *(0x602280)= P \BK->fd = (0x602270+0x10) =(0x602280)= P,绕过! malloc_ printerr (check_ _action, "corrupted double-linked list", P, AV); . FD->bk= BK; \ *(0x602268+0x18) | *(0x602280) = 0x602270 BK->fd = FD; \ *(0x602270+0x10) | *(0x602280) = 0x602268
最终效果就是往chunk里面写入了chunk-0x18的值!