\x01 漏洞简介

  • 在 2017 年 11 月微软的例行系统补丁发布中,修复了一个 Office 远程代码执行漏洞(缓冲区溢出),编号为 CVE-2017-11882,又称为 “噩梦公式”。该漏洞从修复之日起已经隐藏了 17 年之久,而且通杀目前流行的所有 Office 版本,可见其危害程度。该漏洞位于 Office 的 EQNEDT32.EXE 组件中,该组件的作用是通过 OLE 对象的互操作性协助 Office 软件进行公式的处理,由于在拷贝 Office 传入 font name 字段时没有对该字符串的长度进行限制,所以造成了缓冲区的溢出。攻击者可以利用该漏洞以当前登录的用户身份执行任意命令。

  • CVE-2017-11882 漏洞影响的 Office 版本:

\x02 测试环境

注:以上软件有部分是第三方提供的下载支持,如没有进行杀毒处理或者未在虚拟机中安装导致电脑中毒的,后果自负

\x03 RTF 文件中的 OLE 对象互操作性

1)OLE 对象和 RTF 文件格式介绍

  • OLE 全称 Object Linking and Embedding,及对象的嵌入与链接技术,是 COM 技术的前身。该技术允许在程序之间链接和嵌入对象数据,从而建立复合文档。Office 当中的各种软件都会采用 OLE 技术储存文件规范,通过该规范,一个文件中不仅可以包含文本,而且还可以包括图形、电子表格、甚至是声音视频信息。如下图所示:

  • 富文本格式RTF)规范是为了方便在应用程序之间轻松储存格式化文本和图形的一种编码方法。由 Microsoft 公司制定,它适用于不同的设备、操作环境和操作系统。下图列出了部分 RTF 文档 16 进制内容信息:

2)RTF 中的公式编辑器对象的嵌入

  • 根据 RTF Specification Version 1.7 的文件格式规范,RTF 文件语法格式主要有三类:控制字(如 \rtf)、控制符(如 \~)和组( { } )。而 RTF 中的 OLE 对象主要是通过控制字 \object 进行识别,并且在外围包裹着一个完整的组。具体流程如下图所示:

  • 插入公式编辑器对象(OLE)。

  • 插入完成之后保存。

  • 使用 16 进制编辑器打开刚刚插入公式编辑器的 RTF 文档,搜索 object 关键字即可发现插入的对象。

  • 下图中的 Equation.3 表示的是公式编辑器对象。插入的对象由 \*\objclass 引用控制字进行识别。

注:如果想要更详细的了解 RTF 文件中的 OLE 对象的嵌入信息,请参照 RTF 文件规范 v1.7:https://pan.baidu.com/s/11w-xGVoguP-jtpJ6ocpwSA(提取码:9xar)

3)RTF 中的公式编辑器对象的处理

  • 既然 RTF 文档中可以嵌入公式编辑器对象,那么 Office 是怎么与之进行数据交互的呢?答案是通过 Ole32.dllIPersistStorage 接口实现的,当然了根据情况的不同也可以使用其他接口进行操作。当 Office 读入一个嵌入公式编辑器对象的 RTF 文档时,会调用 Ole32.dll 中的 OleLoad 函数对公式编辑器对象进行初始化。

  • 初始化完成之后,继续调用 ole32.dll 中的 CoCreateInstance 函数来初始化公式编辑器对象中的数据。注意这个函数的第一个参数 CLSID,作用是识别 OLE 对象,因为每个 OLE 对象都有自己的 CLSID。到此为止初始化对象就完成了,此时数据会以持久化的方式(序列化)储存。

  • 最后公式编辑器组件 EQNEDT32.EXE 调用 IPersistStorage ATL 接口中的 Load 方法就可以对数据进行处理, 也就完成了数据的交互操作。



\x04 调试分析

  • 使用 Python 脚本制作 POC 样本文件,功能是弹出计算器。



  • x32dbg 调试器设置为附加调试,注册表路径为 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\EQNEDT32.EXE

  • 打开含有漏洞的文档,断下 WinExec 函数(因为该漏洞文档触发漏洞的方式为使用 WinExec 函数来打开计算器),运行之后成功断在了此函数上。

  • 此时栈结构如下图所示,可以看到返回地址已经被覆盖了,因为漏洞模块没有开启任何的安全保护,所以不需要通过 ROP 等方式绕过安全保护。因此栈结构还没有被完全破坏,通过栈向上找出是哪一个函数调用的 WinExec

  • 如下图所示,eqnedt.4115A7 即为栈中找到的最靠近漏洞触发点的函数。

  • eqnedt.4115A7 函数下断,重新运行程序后单步调试,发现到达此位置时函数的返回值会被覆盖,由此确定这个就是漏洞的触发点。

  • 运行到函数的返回处。

  • 查看此时栈中的数据,发现函数的返回值已经被覆盖为 WinExec 函数的地址。

  • 查看 0x0018F354 地址的值,这个也就是让 WinExec 函数执行的命令。
  • 值得注意的是命令和溢出字符是以 0x26 隔开的,成功的避开了空格对拷贝字符的影响;而且 WinExec 函数是 EQNEDT32.EXE 模块本身就有的函数(因为没有 ASLR 保护),并不是从库中调用的。

  • 继续 F8 执行下去,运行到了 WinExec 函数的地址,最后会弹出计算器。



  • 由于 EQNEDT32.EXE 模块是通过 IPersistStorage 接口对 RTF 文档中传入 OLE 的数据进行处理的,所以找到 IPersistStorage::Load 函数分析其处理方式。
  • 因为 IPersistStorage 接口的函数是通过 EQNEDT32.EXE 模块本身调用的,所以并没有相应的符号文件,但是可以从 IPersistStorage 接口的初始化和调用方式推出 IPersistStorage::Load 函数的具体位置。IPersistStorage 接口的初始化如下图所示:



  • 通过比对后发现 sub_406881 就是我们要找的 IPersistStorage::Load 函数。



  • 之后通过对比 x32dbg 的调试结果和 IDA 的交叉引用,得出了函数调用链:

  • 需要注意的是 sub_406881sub_43B418 这个两个函数。在 sub_406881 中,先调用 GlobalAlloc 函数从堆中分配指定的字节数,然后调用 GlobalLock 函数锁定全局内存对象并返回指向对象内存块第一个字节的指针,指针储存在局部变量 var_3C 中。

  • 之后以 eax 为虚函数表的首地址,调用偏移地址为 0x0C 的函数 IUnknown_QueryInterface_Proxy 来获取 MTEF Byte Stream 数据。

  • 而获取到的 MTEF Byte Stream 数据就储存在局部变量 var_3C 中,也就是下图中的 [ebp-3C] 中。

  • 再来看看 sub_43B418 函数,该函数会通过 sub_4164FA 函数取出 MTEF Byte Stream 中的 font name 字段的数据并且拷贝到局部变量 [ebp-104] 当中。



  • 样本对照如下:

  • 在函数调用链的最后会将 font name 压入,压入参数之后调用漏洞函数 sub_41160F

  • 漏洞函数会将 font name 中的数据拷贝到局部变量 var_28 中。

  • 由于并没做任何的判断,并且只要数据的大小超过 0x28,就会造成栈溢出,这也是漏洞产生的根本原因。

  • 最后使用带有 mona.py 脚本插件的 Immunity Debugger 查询 EQNEDT32.EXE 模块的安全防护,发现确实没有开启任何防护措施。

\x05 补丁修复分析

  • 下载微软安全更新中心关于 CVE-2017-11882 的补丁并打好补丁。这里需要根据 Office 的版本和系统位数自行选择。



  • 对比之前的未打过补丁的版本,打过补丁的版本对 font name 字符串的长度做了判断,如果长度大于 0x21 的话就将拷贝的长度限制为 0x20,从而达到了防止缓冲区溢出的目的。



\x06 参考文献

关于 CVE-2017-11882 漏洞分析到此结束,如有错误,欢迎指正。

CVE-2017-11882:Microsoft office 公式编辑器 font name 字段栈溢出通杀漏洞调试分析的更多相关文章

  1. CVE-2018-0802:Microsoft office 公式编辑器 font name 字段二次溢出漏洞调试分析

    \x01 前言 CVE-2018-0802 是继 CVE-2017-11882 发现的又一个关于 font name 字段的溢出漏洞,又称之为 "第二代噩梦公式",巧合的是两个漏洞 ...

  2. CVE-2018-0798:Microsoft office 公式编辑器 Matrix record 字段栈溢出漏洞调试分析

    \x01 前言 2018 年 1 月 9 日,Office 公式编辑器再曝出新漏洞,编号为 CVE-2018-0798.提起公式编辑器大家都不陌生,之前的 CVE-2017-11882 和 CVE-2 ...

  3. CVE-2012-0003:Microsoft Windows Media Player winmm.dll MIDI 文件堆溢出漏洞调试分析

    0x01 蜘蛛漏洞攻击包 前言:2012 年 2月,地下黑产中流行着一款国产名为蜘蛛漏洞的攻击包 -- "Zhi-Zhu Exploit Pack",该工具包含 5 个漏洞,都是在 ...

  4. MathType与Office公式编辑器有什么不同

    说到在论文中编辑公式,有经验的人都会知道要用公式编辑器来编辑,没经验的人也会被安利使用公式编辑器.然而在使用公式编辑器时,又有了两种选择,一种是使用Office自带的公式编辑器,一种是MathType ...

  5. CVE-2011-0104:Microsoft Office Excel 中的栈溢出漏洞调试分析

    0x01 前言 CVE-2011-0104 是 Microsoft Office 中的 Excel(没有打补丁的情况下)表格程序在处理 TOOLBARDEF 中的 Record 字节时没有对 Len ...

  6. CVE-2012-0158:Microsoft Office MSCOMCTL.ocx 栈溢出漏洞调试分析

    0x01 Lotus Blossom 行动 在 2015 年 6 月,国外安全厂商 Palo Alto Networks 的威胁情报团队 Unit42 发现了一起针对东南亚政府的一次间谍行为,试图获取 ...

  7. CVE-2010-3333:Microsoft RTF 栈溢出漏洞调试分析

    0x01 前言 CVE-2010-3333 漏洞是一个栈溢出漏洞,该漏洞是由于 Microsoft文档在处理 RTF 数据的对数据解析处理错误,在进行内存操作时没有对操作的数据进行长度限制,导致存在内 ...

  8. CVE-2010-3974:Windows 传真封面编辑器 FxsCover.exe 双重释放漏洞调试分析

    0x01 堆空间申请后的双重释放 Windows FxsCover 程序存储封面编辑器的信息,封面编辑器是传真服务的一个组件,通过解析特定的传真封面文件(.cov)时,会调用类析构函数对同一内存中的栈 ...

  9. CVE-2010-2553:Microsoft Cinepak Codec CVDecompress 函数堆溢出漏洞调试分析

    0x01 前言 微软提供一个叫 Cinepak 的视频解码器,通过调用 iccvid.dll 这个动态链接库文件可以使用这个解码器:微软自带的 Windows Media Player(视频音频软件) ...

随机推荐

  1. 再探命令行传参之c与python

    继上一次java命令行传参 python sys模块包括了一组非常实用的服务,内含很多函数方法和变量,用来处理Python运行时配置以及资源,从而可以与前当程序之外的系统环境交互,如:python解释 ...

  2. 扫盲贴|如何评价一款App的稳定性和质量?

    作者:友盟+移动开发专家 张文 「崩溃」与「卡顿」.「异常退出」等一样,是影响App稳定性常见的三种情况.相关数据显示,当iOS的崩溃率超过0.8%,Android的崩溃率超过0.4%的时候,活跃用户 ...

  3. Java 树结构实际应用 二(哈夫曼树和哈夫曼编码)

     赫夫曼树 1 基本介绍 1) 给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为 最优二叉树,也称为哈夫曼树(Huffman Tree), ...

  4. C语言变量及其生命周期

    变量类型以及作用域和生命周期 变量的作用域 变量的作用域就该变量可以被访问的区间,变量的作用域可以分为以下四种: 进程作用域(全局):在当前进程的任何一个位置都可以访问 函数作用域:当流程转移到函数后 ...

  5. (数据科学学习手札114)Python+Dash快速web应用开发——上传下载篇

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  6. 力扣 - 剑指 Offer 09. 用两个栈实现队列

    目录 题目 思路 代码 复杂度分析 题目 剑指 Offer 09. 用两个栈实现队列 思路 刚开始想的是用stack1作为数据存储的地方,stack2用来作为辅助栈,如果添加元素直接push入stac ...

  7. 让你的程序炫起来!少有人知道但超酷的 Python 进度条开源库

    本文适合有 Python 基础的朋友 本文作者:HelloGitHub-Anthony HelloGitHub 推出的<讲解开源项目>系列,本期介绍让你快速拥有完美进度条的 Python ...

  8. 答应我,别在go项目中用init()了

    前言 go的 init函数给人的感觉怪怪的,我想不明白聪明的 google团队为何要设计出这么一个"鸡肋"的机制.实际编码中,我主张尽量不要使用init函数. 首先来看看 init ...

  9. 幻灯片放映模式切换windows terminal背景图片

    目录 幻灯片放映模式切换windows terminal背景图片 脚本功能 开发需求 使用技术 操作说明 使用示例 查看帮助 输入参数使用 脚本详情 引用参考 幻灯片放映模式切换windows ter ...

  10. python基础(四):切片和索引

    Python中的序列有元组.列表和字符串,因此我们都可以通过索引和切片的方式,来获取其中的元素. 索引 Python中的索引,对于正向索引,都是从0开始的.但是对于反向索引,确实从-1开始的.如图所示 ...