ღ Miranda

CVE-2012-0003 利用一字节执行任意代码

前言

CVE-2012-0003是微软的多媒体库winmm.dll在处理MIDI文件时对数据处理不当导致的堆溢出。

环境

系统: windoes XP SP3
浏览器: IE6,IE7,IE8

poc

poc.html:

test_case.mid:

调试分析

设置IE的页堆开启,这样当堆溢出时浏览器就会产生异常,然后附加IE,打开poc.html,等一会后触发了异常:

触发点处于winmm.dllmidiOutPlayNextPolyEvent函数。

IDA中反汇编这个函数,找到触发漏洞的语句为:

往上回溯,关键语句为:

v26v24v20的影响,v20只和v1有关,v24v23有关,v23v13v21有关。

只要关注这几个变量:

需要追踪的几个变量为v1,v2,v9,v11,v13,21,由于有些变量的值需要经过if语句的判断,所以可以找一些无需判断的地方来追踪变量,对应汇编为:

给上面的指令下条件断点:

直接运行得到结果:

v2,v1是不变的,v11,v13相等,v21v11,v13的低位,v9是计数的,依次递增。0073B29F是文件中的一段数值。

76B2D0B5下条件断点,当[ebx+eax]==0073B29F时断下,然后单步直到漏洞点。

v20的赋值在v20 = *(v1 + 0x84)一句,跟到这句,此时要赋给esi的值为0A900C00:

对应的伪代码如下:

汇编代码与伪代码的对应,包含注释:

76B2D224处触发了崩溃,用windbg看看这里堆的情况:

那么漏洞的原因就清楚了,看到这里是从d27ec00开始的大小为0x400的一个堆,也就是到d27f000,而访问到了0d27f019,造成了越界。

由之前的分析可知:

这条语句将堆的起始地址加上一个数赋给了v25,然后下一句从这个地址里拿数据时就触发了漏洞,esi里的是堆的起始地址,往前可以追溯到76B2D1B9处的mov指令,那么堆的起始地址就是*(v1 + 0x84);,也就是*(wParam + 0x84);。而偏移v24来自于eax,计算过程如下:

追溯一下edx:

现在已经知道了是如何引发堆溢出了,然后寻找堆是在哪里分配的,*(wParam + 0x84)就是堆的起始地址,wParammidiOutPlayNextPolyEvent的一个参数,查找一下交叉引用,这个函数被midiOutTimerTick引用,查看伪代码:

可见wParam来自于gpEmuList,通过交叉引用找到mseOpen这个函数,发现在这里分配了空间:

可见gpEmuList来自于winmmAlloc分配的空间。

所以:

分配了0x400的空间,而后面计算得到0x419,造成了溢出。

漏洞利用

从漏洞点往下看:

发现会将[esi]中的一字节减去1再赋给[esi],这样能够控制一字节,vupen公司的安全人员给出了一种利用方法,能够实现稳定的利用。

方法就是改变的一字节可能会破坏浏览器中的对象,已经知道发生溢出的堆块大小是0x400,那么就可以事先分配很多大小为0x400的堆块,然后间隔的释放其中的堆块,这样mseOpen在申请时就申请到这些我们释放的内存,这样溢出的堆块就会落在我们之前分配的堆块中间:

这样溢出后的内存我们就可以控制了,实现这种方法的脚本如下:

这个脚本设置了selob对象的64个成员,其中一个是字符串,其他都是函数对象,每个对象大小都是0x10 bytes,所以一共就是0x40*0x10=0x400。这里使用IE8来调试,在溢出点76B2D224处下断点,断下第二次时:

v200x0d377d71-0x419=0x0d377958,那么下一个selob对象的地址可以通过加上这块的大小和下一块堆的头部大小得到:

浏览器中使用一个字节来判断属性的类型,0x8是字符串类型,0x9是函数类型,之前分配时w1为字符串,其余都是函数,所以只有0d377d70处的属性第二个字节为0x8,那么当溢出0x19字节时,[esi]就是0d377d71处的0x8:

此时0d377d71处的0x8被修改为0x9,成为了一个函数对象,在trigger函数中遍历所有克隆的对象,找到被修改的对象,执行clones[k].w1('come on!'),这样就会把字符串当做虚表指针来进行索引,再结合堆喷射就可以执行任意代码。

正常的alert对象的0024269c保存了虚函数表的地址,而字符串变量的03345f1c保存的就是字符串,这样相当于我们已经控制了虚表指针:

执行clones[k].w1('come on!')时会调用GetIntoVariant函数通过虚表调用函数:

只要结合精准堆喷射和rop就可以成功绕过DEP执行任意代码。

exp.html:

可以弹出计算器。

发表评论

电子邮件地址不会被公开。