1 分析环境
操作系统:Window 7
软件 :IE 8
2 基本信息
漏洞类型:堆溢出
影响范围: Microsoft Internet Explorer 6至9版本中存在漏洞
这个漏洞就是在Pwn2Own黑客大赛上用于攻破IE9的漏洞,我们一起来分析一下
POC MD5:97bff46c1f8ad00d05520b531aace884
我们打开页堆,打开IE8,用windbg附加上以后,将windbg设置成跟踪子进程(.childbg)后,我们可以看到发生异常,edi是页堆地址
我们首先看一下POC,我们确定了主要出问题的地方为col元素,通过js的over_trigger重置一些col的span和width元素的属性来触发漏洞
我们可以发现溢出点edi,来自上面的[esi+18h],而esi在函数内没有被操作,肯定来自上一层函数,上层函数从栈回溯中可以看出来是CalculateMinMax这个函数,我们断到这个函数
这个函数CalculateMinMax是处理col中的属性的,这个函数一共会被调用两次,第二次是在调用 js函数 over_trigger()时候,再次处理col中的属性
在第一次调用的时候,我们运行发现一个分配空间的函数,我们看看分配的空间
进去之后可以看到开辟了0x70字节的空间,我们老看看这0x70字节的空间是如何计算出来的
从上面可以看出来是从参数取出的0x1c乘以4然后分配的内存,我们在来看看为什么要分配这个内存
我们看到是在一个比较后才进行的分配的内存,我们分别看看这两个比较的值
我们向上追溯edx的值,可以看到程序的开始处将CTableLayout的对象取出,并取出CTableLayout对象偏移0x54的值,而这个值正式spannum 也就是POC中的span中的值
我们另一个比较数据是从CTableLayout 对象+0x90的位置这个是CImplPtrAry对象,而0x90 CImplPtrAry对象+8的位置是AllocCount(已经申请出来内存的可存放的指针数量),这里一个都没有申请所以去内存分配
我们来看一下申请的内存放到什么位置了,最后CTableLayout 对象+0x9c的位置上,也是CImplPtrAry对象+C的位置上指针数组
由于over_trigger函数更新col属性我们继续断到CalculateMinMax,来继续来看一下,可以看到这次并没有进行堆内存分配,而是在这里进行了跳过,因为ebx+94h,已经在上次分配内存的时候变成了4,而导致比较的时候没有跳过
我们在这里看下在上次分配完内存后,对CTableLayout 对象+0x94的地方进行了把span取出并乘以4,放入ebx+94h
而我们知道我们已经在over_trigger函数中将span的值设置为1000了,我们向下执行,看到了CTableCol::GetAAspan函数来获取span数值,可以看到span数值最大能为1000,
在将span数值拿到后,将进行一个堆空间利用循环1000次每次利用1ch个字节
而这个堆空间正是CTableLayout 对象+0x9c,而这个堆空间只分配了0x70字节的空间,导致溢出。
我们在来看看拷贝的字节拷贝的字节跟width属性有关,是通过CWidthUnitValue::GetPixelWidth这个函数取出的
知道了怎么溢出的,我们看看怎么才可以进行利用,我们先看看整个利用对堆的控制,可以看到先分配250次的100个字节的E和100个字节的A和100个字节的B,最后在后面分配一个Button对象,并将E释放掉,来让分配的占用到这个堆中
我们断到CTableLayout::CalculateMinMax,然后执行到分配内存的地方,我们知道分配的内存在ebx+9C的地方,可以看到整个堆空间的情况
我们看到分配的下面的A和B和B下面的BUTTON对象
之后便对构造的堆进行第一次溢出,这次溢出主要是覆盖到B字符串的大小,这样在覆盖之后,B字符串大小变大,实现内存泄漏,这样就可以读取Button对象的虚函数地址
由于对象的虚函数地址和基地址相差一段固定的距离,所有我们能取得mshtml的基地址,这样我们就可以绕过ASLR
我们在通过基地址构造ROP绕过 DEP
最后通过再一次溢出,覆盖Button的虚函数地址,并实现堆喷,实现控制EIP