最近帮队友研究了一个pwn题,感觉好久不写exp差点把自己坑出shit…
xman - fastisfast
首先看到,这个程序前后问感觉是个经典的pwn,尤其是看到:
1 | Book *create() |
这个地方可以发现,ptr本身free之后,并没有被释放,换句话说,这个是一个典型的UAF。
这里想到,fast bin中对于堆的管理如下:
1 | +---------------+ |
如果说,这个chunk的fd存在指定值的时候,我们去修改fd,那么下一次malloc的返回值就会是fd的值。但是周末的时候,听到了大佬们讨论关于malloc的保护机制,去翻一下源代码看一下,大概看懂了防护机制。简单来说,检查了fd中的大小和malloc中的大小是否相等,这就不好搞了啊,如果我们随便的修改fd的话,很可能会被查出来。那么我们这里先做一次实验,看看会不会发生这样的事情。实验结果的确是,我们只有修改的fd指向了【堆块开头大小符合要求的时候才能够完成分配】。。。。。
那么我们首先要泄露数据,但是,但是,我发现free之后,也没有什么值得泄露的东西啊!
昨天晚上fuzz(?)了一下,发现有一个malloc的洞我居然没有发现:
1 | puts("Please input your information"); |
这个位置上,在v1指向的ptrfree之后,如果重新读入一个指针的话,那么malloc就【可能为其分配空间】。
利用算是找到了,但是泄露怎么办呢。。。
1 | .bss:0000000000602090 stdin@@GLIBC_2_2_5 dq ? ; DATA XREF: LOAD:0000000000400410↑o |
今天去找了大佬讨论,发现套路真的多。这个ptr是我们用来存放malloc对象的指针,然后,上面这个info,是一个计数器。我本来是想不到info用来做什么的,因为其功能就是【每次进入主循环,就自然增加1】,今天突然发现,原来可以用来【伪造malloc size】!具体是个什么思路呢,大致如下:
1 | +----------------------+ <---fd |
如上,我们让free之后的堆块中的fd指向info的位置,然后我们malloc两次之后,就会将这个fd分配出来。如果我们在malloc之前,info已经达到了0x30次,那么当我们把fd分配出来的时候,正好会变成0x31,此时就能够绕过malloc的保护机制,并且将ptr的位置分配出来(为什么不是fd的位置?这个是malloc决定的,要跨国prev_size和size,把data部分交出来啦)
那么接下来,当我们在修改name的时候,【实际上就是在修改ptr指针】。此时如果我们让指针指向got表的开头,从0x602010开始的位置,那么就能够在输入comment和age之后,将这些地址泄露。其中,为了防止在输入comment的时候,发生【不小心将重要数据覆盖的事情】,我们这里对于整数,可以使用scanf的漏洞【输入’-'的时候,符号不会被考虑】,然后完成曾输入,经过调整之后,我么能够泄露地址:
1 | _dl_runtime_resolve_avx : 0x7fca53b567c0 |
通过拿到了这个地址之后,我们就能够上网去查询当前我们使用的libc.so.6的版本号了
然而,今天试了很多次,发现其实libc-database好像没有那么好用啊。。。找不到指定的libc。。纠结了一会儿觉得就先这样吧。
之后的思路很简单,拿到libc之后,算出system的地址,然后修改got表,把free的地址改成system,然后重新create一个chunk,并且name里面的内容改成/bin/sh
,然后free掉这个内容即可。