这个漏洞已经发布有一段时间了,现在假期有空,分析一下当作练手。
运行环境:
Windows XP SP3
IE 6.0.2900.5512
以下将从逆向的角度,通过对汇编代码的分析,找出漏洞产生原因。
首先从网上下载CVE-2010-3962利用程序。在此附上一份下载地址:
http://www.exploit-db.com/exploits/15421/
获得漏洞利用网页之后,做了简单的测试,发现该程序无法正确执行,但可以正常出发漏洞,如果shellcode能正确执行的话,只需在shellcode开始处加入0xcc,略作调整,就能让程序断下来了。
下面开始分析用WinDbg加载IE,打开利用程序网页,当程序因出错停下来后查看寄存器和调用堆栈。
可以看到,是在函数mshtml!CLayout::EnsureDispNodeBackground中出现了问题。
查看mshtml!CLayout::EnsureDispNodeBackground函数的反汇编
可以看出是因为虚函数表被修改而造成的错误,重新运行,在mshtml!CLayout::EnsureDispNodeBackground处下断点,确定一下,发现,进入EnsureDispNodeBackground函数时,虚函数表中内容都是非法的。
下面就要想办法找到在什么地方修改了对象的虚函数表,继续根据调用堆栈向前查找,通过对mshtml!CTableLayoutBlock::EnsureTableDispNode的分析可以发现,mshtml!CLayout::EnsureDispNodeBackground中第二个参数是在EnsureTableDispNode中生成的,这样就节省了很多力气,只要跟踪EnsureTableDispNode中出错对象的改变即可。
经过测试,可以发现在第二次调用mshtml!CDispNode::SetUserClip之后,esi指向类的前四个字节,即虚函数表地址由0x7e2233f0变为0x7e2233f1,那么问题就出在mshtml!CDispNode::SetUserClip里面了。
mshtml!CDispNode::SetUserClip的调用过程如下:
我们看看mshtml!CDispNode::SetUserClip都做了些什么:
通过以上的分析,可以发现,造成错误的关键在于mshtml!CDispNode::_extraSizeTable值为0,这个值是在对象实例化的时候进行赋值的,我们在看看对象创建时的情况。
由以上代码可以看到,在构造函数中,默认地使用了0x00作为_extraSizeTable的大小,并将其值放入[edi+4]处,及类首地址便宜为0x04处,此时再看
[eax+4]处为__extraSizeTable的大小,而[eax+6]处为0x8080,可以猜测_extraSizeTable的数据大小应该为2字节,但事实是否如此,在最后还有一个说法。
通过以上的分析,可以看到,在创建CdispContainer的时候,因为使用默认的0作为_extraSizeTable的大小,从而未分配内存,在其后的mshtml!CDispNode::SetUserClip函数中,需要对_extraSizeTable进行修改,而没有进行严格的检验,从而造成了漏洞的产生。
以上就是从逆向的角度分析的该漏洞的成因,至于原理方面,在看雪已经有大牛发过该漏洞的分析贴,在此附上链接,不再赘述:
http://bbs.pediy.com/showthread.php?t=125122
可能因为环境测试环境不同,造成分析结果会有一些差异,根据个人的调试过程,在此对llydd大大的分析提出一点质疑:
由前面的分析可以发现[edi+4]本身不为0,其值为0x8c800000,esi为0x0000000f,经过
运算之后,eax值才为0,事实上,由esi的值应该可以确定,_extraSizeTable的数据大小只有四位。