UNLINK
思路
其实是艰辛的心路历程
这道题是昨天晚上这个时间就想到的思路 [虽然是道基础题但是是难得的一道没看别人exp就想到怎么写的题,当时觉得自己已经登顶了(bushi] 毕竟是一道套路题的确套路了我【微笑.jpg】
change_note这个函数里面没有检查输入长度,堆溢出。堆的几个漏洞里面,堆溢出我只会unlink,所以就顺着这个思路一直往下写了。
UNLINK
- 概念
-
合并
当一个chunk不属于fastbin的范围时,就会触发向前合并或向后合并。
前提是合并的chunk不在使用当中。
合并之后就会被放进unsortedbin中。
之后还需要判断这个合并之后的总chunk的大小是否大于FASTBIN_CONSOLIDATION_THRESHOLD, 大于就会触发fastbins的合并操作,合并之后仍旧放入unsortedbin,直至fastbins为空。
-
UNLINK触发情形
本质就是将一个bin中的某个结点拿出来,在分配内存和由free()带来的合并操作都会触发。
当free(a)时,a物理相邻的前一个chunk——b, 被判断 是空闲的,那么b就会从原有bin中断开,和a合并。
-
发生了什么
其实就是一个简单的双向链表删除某个结点,数据结构讲过很多遍的。
p是一个指向需要unlink的chunk的整个chunk的起始位置。FD = *(p->fd) BK = *(p->bk) *(FD->bk) = BK *(BK->fd) = FD //p->fd == p + SZ_WORD * 2 // 其他同理
SZ_WORD是程序的一个字长我忘却了各大源码里用的啥,瞎编的名字…
这个堆溢出在没有很久很久以前没有检查机制的时候是可以很简单地实现地址任意写的。只要
FD = target_addr - SZ_WORD * 3 BK = shellcode
unlink之后就会有
*target_addr = shellcode
但是那也是很早很早的事情了。如今开了防御措施,会检查FD->bk和BK->fd是否等于p。
但是也不是不能利用了,我们先要找到一个指针ptr==p。
fd = ptr - SZ_WORD * 3 bk = ptr - SZ_WORD * 2
unlink的时候就可以绕过检查机制
FD->bk == ptr - SZ_WORD * 3 + SZ_WORD * 3 == ptr BK->fd == ptr - SZ_WORD * 2 + SZ_WORD * 2 == ptr
会得到
FD->bk = ptr - SZ_WORD * 2 BK->fd = ptr - SZ_WORD * 3
也就是
*ptr = ptr - SZ_WORD * 3
ptr最终指向的是ptr前面一点的地方,往ptr里面写payload就能够覆盖ptr本身。然后再次往ptr里面写payload,就能实现地址任意写了。
在覆盖chunk_1的presize时,指的是构造的fake_chunk_0包括size和presize的大小。覆盖size的时候,原来这个地方是什么,就只要把最后一位从1变为0就好,不要改他的大小。不然会提示
但是我不知道为什么。按理来说,应该没得关系,难道是因为AMP里面的p位标识是0?可是double free不也可以吗,而且也不会报和size有关的错叭?
这个整个chunk的起始位置和presize、size就是今天的一个我的大坑之一。
nodelist的地址指向的是非空闲chunk数据开始的地方,而检查的时候,是检查这个地址是不是指向这个chunk的presize。
我一开始想的是用chunk_0溢出伪造chunk_1空闲的假象,然后free(chunk_0)。也就是向后合并。
我错在直接在chunk_1的原来的presize的地方开始构造,但是nodelist[1]不指向这里,也没有一个可以利用的指向这里的指针,所以通不过防御机制。
而且就算我从nodelist[1]这个地方开始构造,因为没有改到chunk_0的size域,导致ptmalloc找chunk_1的时候找到的还是chunk_1的presize的地方。
所以这个题是只能向前合并的[我jio得]。
size 和 presize就纯粹是脑子没转过弯来以及知识盲区。
哇塞真的好菜啊TAT
unlink可以看一个大佬写的关于unlink的分析 超详细超厉害der!
惊天巨坑!
昨天一晚上今天一上午,我都在想,为什么,我的exp让一个chunk在free之后,只是把相关数据清零,但是这个chunk并没有被放进任何一个bins。
然后我找了别人的exp跑了一下,卡死了。
我直接用gdb调试二进制文件,发现不是exp的原因,free()这个函数就很玄学,他不按说好的来啊根本就!!
我环境是glibc2.27, 师傅让我在2.23里面跑一下。
发现是没问题的。
那么2.27到底是个什么机制我也没有搜到。