首页
社区
课程
招聘
[原创]CVE-2017-7269:IIS6.0远程代码执行漏洞逆向分析记录
发表于: 2017-4-5 14:08 8580

[原创]CVE-2017-7269:IIS6.0远程代码执行漏洞逆向分析记录

2017-4-5 14:08
8580

  关于CVE-2017-7269,网上的大神们的分析的都很有高度,我做为一个小白,拿着这种给了exp的漏洞,我没有想太多,直接windbg和IDA动静结合,调试进行分析,不过,这样可能造成分析有些片面,毕竟是纯逆向进行分析。
好了,首先说说。
环境Windows Server 2003R2 上开启WebDAV服务的IIS6.0。
工具 Windbg,IDA
接着修改网上的EXP代码我们现在不需要完美执行这个EXP,我们需要它崩溃,所以去掉作者添加的shellcode,只保留EXP部分,如下图。

现在进行调试,Windbg直接附加进程,上网查了查IIS的进程名称为W3WP.EXE,好的附加,然后g跑起来。接着把修改后的EXP运行。好了,如下图所示,它崩溃了。

退出Windbg,再次附加W3WP.EXE的时候,发现已经找不到这个进程了,这是IIS应用池机制的问题,解决办法有两个
[1]备份虚拟机镜像
[2]在IIS信息服务管理器里面把网站下的任意网站右键浏览一下,W3WP.EXE就会重新启动

接着进行调试,这个漏洞作者是给了漏洞函数的ScStoragePathFromUrl。使用IDA静态分析吧,那么dll是那个呢,作者并没写明dll名称,但是在IIS信息服务管理器开启WebDAV服务的时候可以知道,如下图。Dll名称为httpext.dll

我们直接把这个dll,放入IDA,加载其符号表。然后CTRL+P 查找函数,输入函数名ScStoragePathFromUrl。双击进行进行分析。

其中很有趣地方里面有明显的内存拷贝,而且有if判断,那么是简单的栈溢出吗?

If判断地址

我们继续进行动态调试,知道了dll的名称,我们先用sxe ld:httpext下加载dll时的断点。
通过IDA知道了ScStoragePathFromUrl这个函数的retn地址为0x673F702C,那我们直接在这个地址下断点,看看每次执行完这个函数时候栈返回地址是否被覆盖,但是不幸的是我尝试几次,返回地址没有被明显的直接覆盖,最后都会以崩溃掉。

好像直接观察堆栈并不能看出什么来,换个思路,完全从逆向的角度分析,先不断下断点定位崩溃函数,看函数崩溃的原因是什么。进过几次的断点后,定位到了ScStoragePathFromUrl内部的一个函数ScStripAndCheckHttpPrefix,这个函数代码如下。

没有错,这个函数调用了虚函数,那么这个洞是简单的堆溢出吗?
再次进行调试,这次进行大量的逆向数据记录,希望从数据的变化中分析出这个洞的成因到底是什么。
首先我们要确定一下我们的要关注的数据什么?(地址通过IDA得到)
[1]内存拷贝 代码地址 0x673F6F99
[2] 判断是否进行数据拷贝的代码地址 代码地址 0x673F6F55
于是windbg下断点,执行情况如下

可以发现这个数据拷贝并不会每次进入ScStoragePathFromUrl函数都会进行拷贝,而且拷贝次数只有3次,分别是第二调用ScStoragePathFromUrl函数,第三调用ScStoragePathFromUrl函数,第五调用ScStoragePathFromUrl函数(其实没进行拷贝的调用也很重要),好吧,既然拷贝了三次数据,那么就下断点进行查看到底拷贝了什么数据,对堆栈进行了什么的影响吧。

  再进入windbg,只对内存拷贝进行下断点,并且每次跟完全部的拷贝,
第一次拷贝的结果如下(代码太多,不全部展示)

第一次拷贝的数据范围
edi 0130f804~0130f958

(第二次和第三次执行的时候edi的地址会大改,但是篇幅的原因,不能全部展示)
现在讲讲通过上面的代码再结合IDA,Windbg,我自己找到数据关系。
一共三次大内存拷贝,每次进行一次大内存拷贝时,有4次小拷贝,其中有两次不会拷贝,而另外进行拷贝的两次的地址edi是连续的,而esi是不连续的。
Edi的地址如果在某次大拷贝的时候变成一个对象的地址,然后进行拷贝,是不是就可以利用了呢?原作者也确实这么做了。
三次大内存拷贝的edi的地址变化范围如下:
第一次拷贝的数据edi:0x0130f804~0x0130f958
第二次拷贝的数据edi:0x680312c0~0x68031464
第三次拷贝的数据edi:0x0130fab4~0x0130fc08
通过数据好像看起来第一次和第三次好像是栈溢出。第二次是堆溢出
但是edi,esi的值是怎么被修改的,edi的值来自哪里?Esi的值来自哪里,这个问题需要弄明白。
通过IDA,和windbg,我找到了这些代码

通过看上面的第一次拷贝的范围可以知道,第二次开始的edi(堆地址)的来源地址0130f7a0,它并没有在第一次拷贝的范围内,但是这个地址就不能通过别的方法修改吗?
通过继续跟踪函数我找到了这条指令

当前的esp=0130f7a4,push也就是在给0130f7a0赋值

而ebp+0Ch =0x0130f7b8来自于

Edi来自于

跟到了这里原来数据来源是0130f90c,结合第一次拷贝的数据范围edi:0x0130f804~0x0130f958可以知道,这个地址就是拷贝进去的数据。(这里由于篇幅有限只分析,怎么通过第一次拷贝的数据,修改第二次将进行拷贝的edi的值,第二次的拷贝怎么修改第三次的edi值类推)

那么ESI是什么呢
通过几次再内存中的查看
[1]第一次拷贝前的esi指向的内存内容

[2]第二次拷贝前的esi指向的内存内容

[3]第三次拷贝前的esi指向的内存内容

可以知道esi的内容就只想我们发送数据的地址。
好了,我们现在能知道原作者通过第一次的溢出,使第二次的edi,变成自构造的对象堆地址,进行了第二次堆溢出,那么第三次溢出的作用是什么?
第三次拷贝的数据范围edi:0x0130fab4~0x0130fc08
下面这条指令是给ecx(this指针)赋值的,此时的ebp-14h=0130fbbc在第三次的溢出范围。而且结合第二次拷贝的数范围据edi:0x680312c0~0x68031464可以知道现在赋值的ecx就是第二次拷贝的起始地址。
//ecx值来源栈地址 0130f960内容 ->变成680312c0

接下来在执行虚函数时ecx已经是构造的exp的地址

进入之后发现虚函数的内容如下

把ecx赋值给esp,retn后,就从对象开始执行,并进行ROP,绕过DEP


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-2-4 13:05 被kanxue编辑 ,原因:
收藏
免费 1
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  CCkicker   +1.00 2017/06/19
最新回复 (12)
雪    币: 112
活跃值: (86)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
小白二进制楼主,写的比较基础,片面
2017-4-5 14:10
0
雪    币: 1746
活跃值: (227)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
3
既然把shellcode去了,为啥不再简化一点,崩溃的话只要aaaaa后面部分改为随机字符串不就行了么?
2017-4-5 18:42
0
雪    币: 292
活跃值: (800)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
2017-4-5 20:30
0
雪    币: 112
活跃值: (86)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
hackyzh 既然把shellcode去了,为啥不再简化一点,崩溃的话只要aaaaa后面部分改为随机字符串不就行了么?
aaaaa后面有原作者刻意构造的数据,用随机字符串,就不能完成这个艺术的三次溢出了
2017-4-6 23:28
0
雪    币: 112
活跃值: (86)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
Keoyo 赞[em_63]
膜拜大佬
2017-4-6 23:30
0
雪    币: 50
活跃值: (73)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
楼主写的不错的,赞
2017-5-17 14:52
0
雪    币: 236
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
!py  mona  jmp  -r  esp  -m  kernel32.dll  命令不能执行的问题解决了吗?
2017-6-11 13:08
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
kankan
2017-6-14 10:26
0
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
ads
2017-6-14 10:26
0
雪    币: 287
活跃值: (51)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
学习了
2017-6-14 17:13
0
雪    币: 112
活跃值: (86)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
fanslinux !py mona jmp -r esp -m kernel32.dll 命令不能执行的问题解决了吗?
貌似只支持32位的windbg
2017-7-14 16:35
0
雪    币: 2
活跃值: (56)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
现在支持64位了
2018-2-28 16:22
0
游客
登录 | 注册 方可回帖
返回
//