我们伪造一个fake chunk,修改其fd为p-0x18(p储存堆块指针的地址,一般为bss段),修改bk为p-0x10,绕过保护,在形成双链表的过程中,修改了p->p-0x18导致我们可以修改p->任意地址,进行一次任意地址写,可以修改free为system。
伪造形式
伪造堆块的后一堆块的size低位要为0,这样会认为我们伪造的堆块是释放的,才能往前合并。
1 | 首先我们要绕过保护 |
这里我要提出一个问题了
为什么我们要伪造堆块而不用原堆块呢?
你要想一下我们绕过保护的要求是什么,最终我们回到的地方是chunk0,而最开始我们指向的是原堆块的数据区,我们是无法指到头部的,而我们构造的正好是可以指向头部的
//////
1 | //在使AB构成双链表 |
们在读入的时候就会往从p-0x18的位置开始读入,最后覆盖掉读入位置,在进行读入就从*p进行读入,相当于一次任意地址写
例如我们覆盖到读入位置为atoi函数的got表,
我们下次就会对这里进行修改
然后读入的内容从
这里读入
那么我们就可以覆盖got表了
例题
bamboobox
首先查看保护
64位开启了canary和nx保护
查看ida
菜单题
show函数内,我们查看一下打印的位置bss1在哪里,这里是我们随后创造第一个堆块的索引位置(重点关注)
查看add函数,创造指定大小堆块,将堆块索引位置放到itemlist的位置,这里我们就知道堆块地址在这个bss段放置了,而且前面的show也是打印itemlist+8的位置
且add里的read函数也是往itemlist+8的位置读入,也就是对堆块读入内容
在change函数中存存在自己规定大小的堆溢出,可以用于修改后面堆块的pre_size(前一个堆块的大小)size自己堆块的大小(主要改成地位为0,将前一个堆块标记为释放状态)
free释放函数
思路:
1.部署堆块(fk=itemlist-0x18,bk=itemlist-0x10),并设置后一个堆块标识位(size低位为0)
2.然后释放后itemlist+8的位置会指向fk的位置,这时候覆盖到itemlist+8,即可任意读写(覆盖为atoi_got)
3.然后show打印出atoi的got表地址,根据偏移可以找到system
4.这时候读入取覆盖安atoi的got表为stystem即可
部署的堆块
1 | target = 0x6020c8 |
然后释放,itemlist+8指向了itemlist-0x18的位置,此时我们读入就从itemlist-0x18读入,可以覆盖到itemlist+8,即可任意读写
我们读入地址覆盖itemlist+8为atoi
先打印获得libc地址,找到system地址
修改atoigot表为system
这时候就成功了
最终的exp
1 | from tools import * |
axb_2019_heap
首先查看保护
保护全开
查看ida
菜单题
banner函数,存在格式化字符串漏洞,进行泄露程序地址和libc地址
查看add函数
delete噶不是故意,释放堆块并清空内容不存在uaf漏洞
看exit函数
思路:
1.首先泄露程序地址和libc基地址
2.如何构造堆块,并覆盖后一个堆块的pre_size和size位(size低位为0)
3.释放使note指向note-0x18的位置,如何进行读入进行覆盖为free_hook为system
(因为这题开了RELRO不能覆盖got表)
最终的exp
1 | from tools import * |
- 本文作者: NEWYM
- 本文链接: http://example.com/2024/11/06/unlink/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!