-
-
[原创]2019 Q2 第二题 沉睡的敦煌(pwn) 分析
-
发表于: 2019-6-23 13:12 3550
-
基地址固定
程序开始调用了alram,为了便于调试,需要nop掉。同时malloc一块小内存,并保存了其地址作为地址边界。
实现了malloc,free,edit,show 4个常见功能
只能edit一次,show默认是不能使用的
edit:
show:
保存内存边界,指针数组,编辑次数和admin的全局变量的内存布局:(后面漏洞利用时能发现这布局是作者精心布置的)
很明显的一处漏洞,malloc函数中,有一个字节的溢出。
由于的malloc默认大小为0x28,所以溢出的一个字节刚好能覆盖下一个chunk的size域的最低字节。
看到基址固定,而且全局变量有堆指针,很容易就能想到unlink。unlink在论坛以前的比赛中出过好几次了。
简要的说就是,伪造一个已经free掉的chunk,然后free这个chunk高地址相邻的另一个伪造的chunk,这两个chunk的合并过程中会把低地址的chunk从双向链表中摘除。为了绕过unlink的check,假设存在一个指向低地址chunk的指针P,把低地址chunk的fd和bk分别设为&P-0x18和&P-0x10就能绕过检测。unlink后,P被改写为&P-0x18。同时,两个伪造的chunk合并起来进入unsorted bin。
unlink的详细分析可以参考下面两位dalao的文章:
[原创]看雪.Wifi万能钥匙 CTF 2017 第4题Writeup---double free解法
堆溢出漏洞简介
然鹅,这题半路偷偷改过一次,改之前的edit的限制次数是两次,所以只要unlink后edit两次就能改到admin和editcnt的值,之后就能随意任意地址的读写了。
改之后,edit限制为一次,利用起来就麻烦多了。
需要用到另一种堆漏洞利用技术:tcache的double free来malloc出任意地址。类似于fastbin的double free,但比fastbin的限制要少(不检查size域)。
要触发double free,要先得到两个同样的指针。操作步骤如下:
然鹅这样还是不能分配出任意地址,原因是malloc中的边界检测:
boundary是程序最开始malloc返回的堆地址
完整的利用链比较繁杂,简要叙述如下:
1.填满0x90的tcache
2.tcache double free后,malloc出boundary的地址
3.在boundary处伪造给unlink预备的chunkA,
4.伪造unlink需要的chunkB
5.tcache double free后,准备malloc出存放堆指针数组的地址(但是先不malloc,因为此时不在boundary范围内,会失败)
6.free(chunkB),触发unlink,改写boundary为&boundary-0x18
7.把堆指针数组的地址malloc出来(此时绕过了boundary的check),修改editcnt和admin的值
8.然后就能随意show和edit了
9.got表泄露libc,修改__free_hook为system,然后free一个内容为"/bin/sh\x00"的堆块,得到shell。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!