[CVE-2012-1876] Internet Explorer堆溢出漏洞分析
0x0漏洞分析
1.开启页堆调试,!gflag +hpa,由于IE8会产生子进程,所以.childdbg 1开启子进程调试
1.1运行poc
Windbg导入mshtml模块的符号文件
1:020> .reload /f mshtml.dll
1:020> lm
1.2中断后,栈回溯下,产生问题的函数为mshtml!CTableLayout::CalculateMinMax
2.分析下mshtml!CTableLayout::CalculateMinMax这个函数
2.1 sxe ld:mshtml 加载mshtml模块时断下,再下断点
其中[ebp-90h]为poc中span元素的值
mshtml!CTableLayout::CalculateMinMax分析大概
3.进入mshtml!CImplAry::EnsureSizeWorker函数分析
大概就是根据 传进来的span元素*0x1c 后得到结果 进行内存分配,分配成功保存的地址为edi+0ch,edi是从html!CTableLayout::CalculateMinMax函数传进来的:edi = [ebx+90h], ebx是CTableLayout:对象
分配成功的地址:2cb408
mshtml!CTableCol::GetAAspan分析大概
第一次执行完后mshtml!CTableColCalc::AdjustForCol后,分配的heap变化(esi = pHeapAddr)
5.对GetAAspan下断
g执行后,会中断2次,都是对span属性进行修改操作
6.第三次g后,将第2次断到mshtml!CTableLayout::CalculateMinMax,继续单步分析下
查看下此时CTableLayout对象
单步执行到GetAAspan函数跟进,可以看出获取到的span已经更改为1000,通过eax传出
由于等于3e8,后面的跳转不会实现,接着 [ebp+nDenominator]被赋值3e8
得到width的值后乘以100
一直单步到CTableColCalc::AdjustForCol函数,基本可以知道溢出的原因了
[ebp+nNum]为增加的次数,esi为pHeapAddr,每循环一次pHeapAddr增加0x1c,[ebp+nDenominator]为循环结束的判断条件
而CTableColCalc::AdjustForCol函数里,也对pHeapAddr增加0x18,对增加后的值进行 赋值,分配的堆空间大小为0x70,经过不断的循环赋值操作后,最后会超过堆分配的内存,去改写堆内存以外的数据
每次填入的的数据为width*100和width*100+4
0x01 exploit分析
1.javascript释放内存的函数为jscript!JsCollectGarbage,先对该函数下断点,中断后清除该断点,查看下mshtml!CImplAry::EnsureSizeWorker函数
对其里面分配的内存函数下2条指令处下断点
bp 65ee34e4 ".if(poi(ebp-8) == 0xfc){.echo ok;db poi(esi) l 300;}.else{gc;}"
主要是断到分配0xfc大小的内存,打印堆块里面的数据
2.可能分配的位置不一定是,后面溢出操作的堆块,为了能断到操作的堆块
根据exp中的改变span处代码(第一处)
改变span时,需要先获取span吧(CTableCol::GetAAspan(void)),那么可以在获取span,对返回值进行判断是否为19(0x13),是的话就断下.先禁止之前的断点
29F31F (偏移) => cmp eax, 3E8h
bp 65FAF31F ".if(eax == 0x13){.echo run ok;}.else{.echo error;gc;}"
断下后,对后面对产生漏洞的堆块操作,也下断点,禁止前面的断点
29F480 => add [ebp+var_24], 1Ch
bp 65FAF480 "!heap -p -a esi;.echo;db esi l 200"
主要是获取堆块的信息,还有里面的数据
占用了“E”释放的内存
看下其他占用的“E”释放的内存
跑几下,对比下填充的数据
第一次溢出,最后会填充到“B”(BSTR字符串)的长度值,通过读取字符串后,就会读取CButtonLayout虚表指针,泄露虚表地址,再通过虚表地址减(mshtml模块到虚表的偏移),就能得到mshtml模块的加载基址,从而绕过aslr,构造rop链
3.第二次溢出
根据exp中的改变span处代码(第二处)
bp 65FAF31F ".if(eax == 0x2c){.echo run ok;}.else{.echo error;gc;}"
然后禁止掉65FAF480 处的断点
启用刚刚禁止掉的断点,看下堆块地址也是刚刚的
直接查看溢出完后的堆块
第二次溢出主要覆盖CButtonLayout虚表指针为07070024,再通过HeapSpray,把shellcode喷射到调用虚函数的地址处,达到漏洞利用(具体参考《漏洞战争》)
总结:该漏洞的漏洞利用是非常巧妙的,绕过了ASLR和DEP,分析该漏洞的漏洞利用,可以收获不少东西
评论
发表评论