首页
社区
课程
招聘
[原创]从CVE-2015-1642到Office ActiveX控件堆喷探究
发表于: 2019-3-14 16:06 11065

[原创]从CVE-2015-1642到Office ActiveX控件堆喷探究

2019-3-14 16:06
11065

笔者最近重新研究了一下 officeActiveX 控件堆喷射的相关细节,在此过程中对遇到的一个cve-2015-1642 poc进行了复现,在本文的最后,笔者探索了 ActiveX 控件堆喷射的部分原理,提出了一种比较简单的 ActiveX 控件堆喷射检测思路,实践证明该方式可以准确检出这类堆喷射。

由于笔者能力有限,不足之处还请读者斧正。

cve-2015-1642 被公布时为在野利用状态(0day)

漏洞细节首先是由 @yongchuank2015.8.17 公布的,具体见:

1a6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6D9j5h3u0K6i4K6u0W2L8i4N6J5K9h3&6X3L8%4y4W2j5%4g2J5K9i4c8&6i4K6u0W2j5$3!0E0i4K6u0r3j5h3c8$3K9i4y4G2M7X3W2W2M7#2)9J5c8X3#2A6j5%4u0G2M7$3!0X3N6q4)9J5k6r3!0X3k6X3W2U0k6g2)9J5k6r3y4@1j5i4y4C8M7%4W2E0j5X3!0D9i4K6u0V1N6i4y4W2i4K6u0V1j5h3k6@1k6i4u0Q4x3X3c8X3M7X3g2W2i4K6u0V1N6Y4g2D9L8X3g2J5j5h3u0A6L8r3W2@1P5g2)9J5c8R3`.`.

随后,NCC Group 公司的 @d0mzw2015.10.30 公开了这个漏洞的进一步细节,并在文章内详细讨论了 office 内存破坏漏洞借助堆喷射进行利用的具体细节,作者还仔细讨论了office堆喷射的许多细节和通用利用编写方式。

c98K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2F1j5$3y4Y4M7X3!0#2M7q4)9J5k6i4c8J5N6i4y4@1i4K6u0r3N6h3E0Q4x3V1k6G2N6i4u0Q4x3X3c8J5k6i4y4W2j5i4u0U0K9q4)9J5c8Y4g2F1k6r3g2J5M7%4c8S2L8X3c8A6L8X3N6Q4x3X3c8E0K9h3y4J5L8%4y4G2k6Y4c8Q4x3X3c8%4L8%4u0V1i4K6u0V1L8$3I4W2i4K6u0V1k6i4S2H3L8r3!0A6N6q4)9J5k6s2m8J5K9h3#2A6N6r3W2$3k6i4y4Q4x3V1j5`.

接着,玄武实验室的 Danny__Wei2015.11.28 在自己的博客上公开了这个漏洞的poc,公开的poc是一段 C# 代码,poc构造思路基本遵循了 NCC Group 的文章。

bfaK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3y4F1j5X3I4G2k6%4y4Q4x3X3g2U0L8$3#2Q4x3V1k6p5j5h3&6F1P5g2)9J5k6q4N6W2K9g2)9J5c8Y4m8Q4x3V1j5#2x3o6l9K6x3K6l9J5i4K6u0W2K9s2c8E0L8l9`.`.

笔者最近对 officeActiveX 控件堆喷射的细节进行了进一步研究,研究过程中再次遇到上述材料,因此决定复现一下相关poc。

office UAF 漏洞的利用是比较少见的,因为重用内存时占位的时机不好控制。这个漏洞触发后恰好有一段时机可以用来占位,所以值得研究一下。这篇文章还解决了一个问题:可以借助字符串申请申请任意大小的内存块,这在UAF利用时是非常有用的,一般产生UAF时,相应的对象大小往往比较小,所以如何在 office 内进行任意大小内存的申请也就显得尤其重要。

office 下的堆喷射技巧,历史上有若干漏洞样本都曾采用过。例如 cve-2013-3906/cve-2015-1641/cve-2015-1642/cve-2016-7193/cve-2017-11826,有资料表明 cve-2015-2424 这个0day也用到了堆喷射,这一点需要进一步考证。

上述几个借助堆喷射的漏洞,其漏洞类型分别如下:

cve-2013-3906 整数溢出

cve-2015-1641 类型混淆

cve-2015-1642 UAF

cve-2016-7193 数组越界写

cve-2017-11826 类型混淆

这里我们来研究一下 cve-2015-1642,笔者遇到的第一个问题是如何编译 Danny__Wei 的poc代码,这看着是一段 C# 代码,在经过若干探索后,笔者用 VS2010 新建了一个 C# 的窗体应用程序,如下:

随后在窗口上添加一个按钮控件:

双击按钮,即来到了 button1_Click 函数中,此时将 Danny__Wei 的代码全部拷贝进来即可,拷贝完代码后,会有些对象类型不认识,此时我们需要添加对 MSCOMCTL.OCX 动态库和 Microsoft.Office.Interop.Word.dll 动态库的引用,具体的方法如下:

笔者的电脑装有若干版本的VS,所以这两个动态库可以通过 Listary 等工具搜到,将其拷贝到工程目录下,选中后点击确定即可,成功引入后,可以看到引用列表里面多了如下两个库:

最后添加所需的头文件即可:

此时我们就可以编译生成该poc了(确保你的机器上装有 office,笔者的机器上装的是 office 2010)。

编译完成后,双击 .exe 文件,出现一个窗口,点击上面的按钮就可以生成poc了(test.docx):

此时这个 test.docx 还不是一个漏洞样本,它只带有堆喷射和 0x60 大小的内存占位功能。关于如何在此基础上构造一个 cve-2015-1642 的漏洞样本,@d0mzw 在他的文章里面写的很清楚:

笔者在此思路上用 7z 打开了生成的 docx 文件,并将 activeX1.xmlclsid 换成了漏洞的 clsid:44F9A03B-A3EC-4F3B-9364-08E0007F21DF。此时我们就有了一个“理论上”可以劫持 eip0xC0DEC0DEcve-2015-1642 样本。

为什么说“理论上”呢?因为读者如果自己实验的话,就会发现这个poc很不稳定,构造的样本在没有打补丁的环境中 crash 是没有问题的,但是笔者试了几次后发现我们并未劫持到 eip

接下来我们通过调试并改造poc代码来初步实现对eip的劫持,本文不讨论利用编写,利用编写请参考笔者的另一篇文章:

https://bbs.pediy.com/thread-221792.htm

我们先删除堆喷射部分,构造一个只触发 cve-2015-1642 的样本,看一下崩溃现场是否和相关文章里面描述的相同(当然,如果读者比较懒,那么VT也有一个现成的 cve-2015-1642 crash poc,有条件的可以自己下载,md5: 8b7d1680d8aeb1d0d822ee33777671ab)

笔者调试时某次的 crash 现场如下,可以看到这是一个典型的UAF,且 crash 现场和 @d0mzw 的基本一致(请注意 @yongchuank 的crash现场并不是这里,笔者在 office 2013 下开启页堆后的崩溃现场依然是下面这个,读者请以实际调试的情况为准)

现在笔者有一个问题:我不知道被释放前 eax 对象的内存大小为多少。我们来下个断点看一下:

到这里,我们已经知道被释放的对象大小为 0x60.

现在,让我们来整理一下思绪,这个UAF如果要成功利用,所构造的文档在执行是需要满足哪些最简条件?

我们先来检视一下 @d0mzw 文章中提供的思路:

我们再来看一下 Danny__Wei 代码中对上述思路的实现,可以发现如果实际执行顺序为从下到上的话,和上述文章的思路完全一样:

顾名思义,DefragmenHeap 函数的作用是整理内存,实际内存申请时可能申请 0x60 大小的内存,占用的是稍微大一点的内存块,这个函数的作用就是把那些内存块先使用完,从而让系统分配精准的 0x60 大小的内存块,以便提高占位的有效性。

到这里,笔者脑海里的问题是:

我们借助调试器来探究一下上述问题。

要回答第1个问题,我们需要清楚以下几点:

笔者先回答a:显然,tabArrayB[j].Buttons.Add().ToolTipText = objAllocB/objAllocB/chunk; 这几处代码执行时存在一个统一的内存申请点。其次,每个 ActiveX[x].bin 文件在被映射到 office 进程空间时,还有一次统一的内存申请点,笔者将这部分的讨论放到本文最后。

关于 objAllocB/objAllocB/chunk 的申请,我们可以在堆喷射完的 winword 进程找一个对应堆块的指针,在只开启堆分配用户态栈回溯( +ust )的情况下可以观察到如下输出:

再回答b:借助上面得到的信息,笔者下了如下断点进行观察:

从上面的日志可以观察到:实际执行时 chunk 块(fffe0)的内存是最先申请的,随后是 DefragmenHeapReplaceHeap 中对 objAllocA/objAllocB 的申请,在不考虑字符串内容的情况下,这两个函数的执行顺序笔者并不关心。实际测试发现把 DefragmenHeap 函数中的 objAllocB 内存申请数量进一步增加,将 ReplaceHeap 函数删除,也可以实现正常占位。

接下来我们通过调试器来回答第2个问题:这个UAF在释放内存和重用内存之间的时间差够大吗?利用有足够的时间在这个时间区间内占用被释放的 0x60 大小的内存吗?

既然是UAF,调试时必须定位到 Free 在哪里?Reuse 在哪里?被释放的 0x60 字节内存是否成功被利用代码中申请的对象成功占位。

Danny__Wei 提供的poc在笔者的环境中并不能顺利完成占位,我们来借助调试器看一下究竟发生了什么:

根据上述观察,笔者推测利用代码中对 0x60 大小的字符串申请次数太少,于是笔者将 DefragmenHeap 函数的代码做了略微修改,如下:

同时在 button1_Click 函数进行了如下更改:

再次生成样本,笔者这次替换 activeX34.xml 中的 clsid 为漏洞 clsid,再次打开样本,在调试器中观察如下:

最后回答第3个问题,根据上面的代码已经知道,笔者在 DefragmenHeap 函数中一共用了80个大小为0x60字节的字符串去占位被释放的对象。这个视环境不同而异,读者可以按需自行调整。

通过上述调试,笔者成功借助公开资料和调试器劫持了 cve-2015-1642 样本的控制流,在此基础上就可以写出这个漏洞的 RCE 利用。这个漏洞比较好的一点就是我们可以在UAF之间对内存进行成功占位,对 office 来说这类可以成功利用的 UAF 还是比较少的。

在本文的最后,笔者单独讨论一下 office ActiveX控件堆喷射时的内存申请细节,这个问题实际上涉及一个更一般的问题:如何准确检出 office 堆喷射样本?也即,如何在动态执行过程中对 cve-2013-3906/cve-2015-1641/cve-2015-1642/cve-2016-7193/cve-2017-11826 这类漏洞样本的堆喷射行为进行准确标定。

每个 ActiveX[x].bin 文件在被映射到 office 进程空间时,有一处统一的内存申请点。

这里笔者以手头的某个自己构造的 cve-2015-1641 样本为例,为方便起见,我将负责堆喷射的 docx 文档单独抽取出来,抽取的 docx 文档内用1个 activeX1.bin 文件外加 40activeX[x].xml 文件进行堆喷射。

关于这部分的更多细节可以参考这篇文章:

c64K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2Y4M7X3g2&6K9r3q4@1K9r3q4U0K9$3g2J5i4K6u0W2L8X3g2@1i4K6u0r3i4K6y4r3M7q4)9K6c8o6V1I4x3b7`.`.

其中 activeX1.bin 的大小为 0x20500 字节:

以下调试环境仍为 windows7 sp1 x86 + office 2010 + windbg

笔者在调试器中( +ust )将文档打开,查找满足上述大小的堆块:

笔者在上述栈回溯信息中注意到了两个函数:ole32!CMemBytes::WriteAtole32!CMemBytes::SetSize。我们用 IDA 定位到 mso.dll(14.0.1063.1000) 中的相应调用点来看一下:

我们来看一下 ole32!CMemBytes::WriteAt 的伪代码,其中灰色调用处调用了 ole32!CMemBytes::SetSize 函数:

我们再来看一下 ole32!CMemBytes::SetSize 的伪代码,可以看到里面确实调用了 GlobalReAlloc 函数。

到这里,笔者有若干问题:

我们先来探索第1个问题。

我们对 mso.dll 的上述调用点下断点,看一下每次调用的具体函数是什么:

通过日志可以观察到这个地方每次调用的都是 ole32!CMemBytes::WriteAt 函数。

分析到此处,笔者突然记起自己之前写过的一篇文章,里面谈到了在 office 2010 下借助 msxml6.dll 的符号打印解析的xml标签的断点,相关文章见:

320K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2S2L8Y4q4#2j5h3&6C8k6g2)9J5k6h3y4G2L8g2)9J5c8Y4m8G2M7%4c8Q4x3V1k6A6k6q4)9J5c8U0p5H3x3K6l9^5x3l9`.`.

我们来看一下 ole32!CMemBytes::WriteAt 函数是在解析到哪个标签时被调用的:

可以看到正是解析到 ax:ocx 标签后,开始调用 ole32!CMemBytes::WriteAt 映射 ActiveX 控件的内存。

接下来看一下第2个和第3个问题,我们来看一下 ole32!CMemBytes::WriteAt 的声明:

再次下断点,在函数调用前输出参数看一下:

可以观察到每次调用 ole32!CMemBytes::WriteAt 函数时待写入数据的大小(cb)都为 0x1000,偏移(ulOffset)则按 0x1000 的顺序递增。由此笔者合理推断 ActiveX 控件在被映射到内存时,是按每次 0x1000 的大小被写入的,所以调用 ole32!CMemBytes::WriteAt 处应该位于一处循环内,我们看一下相关调用点的伪代码,果然如此:

现在让我们在第1次调用 ole32!CMemBytes::WriteAt 时断下,看一下写入的数据是什么?

可以看到写入的数据正是ole头部,并且在随后写入了 ActiveX[1].bin 控件的其余数据。

分析到这里,笔者想知道目的地址在哪里,既然有一个 ulOffset,那么肯定有一个 base,我们能通过上述数据得到 base 吗?答案是肯定的。

ole32!CMemBytes::WriteAt 函数中,调用完 ole32!CMemBytes::SetSize 后,有一处 memcpy 操作,这里就是在往新扩大的 0x1000 内存拷贝数据,其中第一个参数就是通过 base[offset] 来寻址的,笔者在寻找的就是这个 v5, 可以看到 v5 是通过如下调用得到的:

看来 v5 是间接通过 CMemBytes 对象指针得到的,我们来看一下 GlobalLock 函数的实现:

可以看到在 GlobalLock 函数中,返回的值其实就是对传入的参数做了一次解引用,原来如此。

现在我们还需要搞清楚 CMemBytes 对象及其相关对象的结构体,幸运的是 IDA 已经给出了相关的结构体定义:

我们的目的就是通过 CMemBytes 对象指针去解析到 v5 对应的地址,所以我们可以将断点修正如下:

上面的日志是一次完整的从 offset=0offset=0x20500 的过程(中间省略了大量重复日志),笔者注意到 base_addr 地址在中间发生过改变,笔者猜测一开始的地址在内存增长过程中可能大小不过,于是将之前已拷贝的数据拷贝到了一块更大的内存,并继续增长,这应该和 GlobalReAlloc 函数的实现有关,这里不再深究。

分析到这里,原则上笔者可以写出一个监控 office ActiveX 堆喷射总内存申请大小的实时 windbg 脚本,但是实际使用时发现带有伪寄存器的脚本执行的速度太慢,该脚本仅供参考。

由于笔者的日常工作涉及到沙箱检测技术的开发,所以我试着将上述调试结论融入沙箱的检测框架。通过累加堆喷射内存大小,并与预先准备的阈值(以下为75MB)进行比较,从而判断一个 office 样本是否有 ActiveX 控件异常堆喷射行为。笔者对 cve-2013-3906/cve-2015-1641/cve-2015-1642/cve-2016-7193/cve-2017-11826 常见攻击样本进行检测,获得了非常好的检出效果。

这里笔者给出若干漏洞的样本以及对应的检出日志,供读者参考:

由于 office 中一定还存在其他内存破坏漏洞,笔者预计未来仍然会有类似的利用手法出现,这些利用在针对旧版本 office(office 2007/office 2010) 的攻击中还是非常稳定的。

由于微软 EMETHeapSpray 检测方式只是简单的占坑,在新样本的检测中并没有非常好的效果。因此笔者在本文最后提供了一种较为简单的检测 office 堆喷射检测方式,供读者参考。

《Microsoft Security Bulletin MS15-081 - Critical》
64cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3k6h3&6Q4x3X3c8#2M7#2)9J5c8Y4y4W2j5%4g2J5K9i4c8&6i4K6u0V1N6i4m8V1j5i4c8W2M7#2)9J5c8Y4y4W2j5%4g2J5K9i4c8&6j5Y4g2D9L8r3g2@1K9h3&6K6i4K6u0r3x3U0l9I4y4g2)9J5c8X3#2K6x3e0g2Q4x3X3b7H3z5o6p5`.

《Microsoft Office CTaskSymbol Use-After-Free Vulnerability》
3d8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6D9j5h3u0K6i4K6u0W2L8i4N6J5K9h3&6X3L8%4y4W2j5%4g2J5K9i4c8&6i4K6u0W2j5$3!0E0i4K6u0r3j5h3c8$3K9i4y4G2M7X3W2W2M7#2)9J5c8X3#2A6j5%4u0G2M7$3!0X3N6q4)9J5k6r3!0X3k6X3W2U0k6g2)9J5k6r3y4@1j5i4y4C8M7%4W2E0j5X3!0D9i4K6u0V1N6i4y4W2i4K6u0V1j5h3k6@1k6i4u0Q4x3X3c8X3M7X3g2W2i4K6u0V1N6Y4g2D9L8X3g2J5j5h3u0A6L8r3W2@1P5g2)9J5c8R3`.`.

《Understanding Microsoft Word OLE Exploit Primitives: Exploiting CVE-2015-1642 Microsoft Office CTaskSymbol Use-After-Free Vulnerability》
58aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2F1j5$3y4Y4M7X3!0#2M7q4)9J5k6i4c8J5N6i4y4@1i4K6u0r3N6h3E0Q4x3V1k6G2N6i4u0Q4x3X3c8J5k6i4y4W2j5i4u0U0K9q4)9J5c8Y4g2F1k6r3g2J5M7%4c8S2L8X3c8A6L8X3N6Q4x3X3c8E0K9h3y4J5L8%4y4G2k6Y4c8Q4x3X3c8%4L8%4u0V1i4K6u0V1L8$3I4W2i4K6u0V1k6i4S2H3L8r3!0A6N6q4)9J5k6s2m8J5K9h3#2A6N6r3W2$3k6i4y4Q4x3V1j5`.

《CVE-2015-1642 POC》
c27K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3y4F1j5X3I4G2k6%4y4Q4x3X3g2U0L8$3#2Q4x3V1k6p5j5h3&6F1P5g2)9J5k6q4N6W2K9g2)9J5c8Y4m8Q4x3V1j5#2x3o6l9K6x3K6l9J5i4K6u0W2K9s2c8E0L8l9`.`.

《Spraying the heap in seconds using ActiveX controls in Microsoft Office》
858K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2Y4M7X3g2&6K9r3q4@1K9r3q4U0K9$3g2J5i4K6u0W2L8X3g2@1i4K6u0r3i4K6y4r3M7q4)9K6c8o6V1I4x3b7`.`.

《结合一个野外样本构造一个cve-2016-7193弹计算器的利用》
https://bbs.pediy.com/thread-221792.htm

《Open XML标签解析类漏洞分析思路》
656K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2S2L8Y4q4#2j5h3&6C8k6g2)9J5k6h3y4G2L8g2)9J5c8Y4m8G2M7%4c8Q4x3V1k6A6k6q4)9J5c8U0p5H3x3K6l9^5x3l9`.`.

 
 

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-3-26 13:07 被银雁冰编辑 ,原因:
上传的附件:
收藏
免费 6
支持
分享
打赏 + 2.00雪花
打赏次数 1 雪花 + 2.00
 
赞赏  Editor   +2.00 2019/03/15 精品文章~
最新回复 (2)
雪    币: 42947
活跃值: (65767)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
 厉害,感谢分享!
2019-3-15 09:37
0
雪    币: 1535
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
前排
2019-3-15 13:51
0
游客
登录 | 注册 方可回帖
返回