CVE-2012-0158
一、漏洞信息
1. 漏洞简述
- 漏洞编号:CVE-2012-0158
- 漏洞类型:栈溢出
- 漏洞影响:信息泄露
- 该漏洞一直是office漏洞史上的经典案例。该漏洞首次发现于2015年6月,目标主要为东南亚国家和地区,此次攻击事件被命名为“Lotus Blossom”行动。该行动从2012~2015持续了三年之久。
- 黑客组织在此次间谍行动中,主要通过构造恶意Office文档诱使目标上钩,从而在对方的计算机上植入木马,窃取机密信息。
2. 组件概述
2012-0158是一个经典的栈溢出漏洞,成因在于office在解析activeX控件时调用系统的MSCOMCTL.OCX库中存在栈溢出漏洞,导致可被用于执行任意代码。
3. 漏洞影响
操作系统:XP SP3 ~ WIN7
office版本:2003 ~ 2010
二、调试环境
1. 环境搭建
使用环境 | 备注 | |
---|---|---|
操作系统 | xp SP3 | 简体中文版 |
虚拟机 | VMware | 16 pro |
调试器 | immunity debugger | 1.85 |
反汇编器 | IDA Pro | 6.8 |
漏洞软件 | word | 2007 中文版 |
office 格式分析工具 | OffVis | 1.1 |
三、漏洞分析
1. 基本信息
- 漏洞文件:MSCOMCTL.OCX
2. 详细分析
用immunity debugger附加word之后F9运行,将poc拖进word窗口打开之后,程序崩溃断下,如下图所示(如果栈中不显示模块地址的话,就alt + E
到模块中刷新一下再返回模块地址就显示出来了)
通过上图回溯栈上数据我们可以看到最近的返回地址在MSCOMCTL.275C8B91处,然后我们可以在左侧内存数据中跳转到275C8B91查看一下此处的汇编代码
继续往上追溯,可以看到0x275C8B91是位于函数sub_275C8B4E中的,将sub_275C8B4E标记为VulFun函数,然后在VulFun函数入口地址0x275C8B4E处下断。但是我们如果直接在这个地址下普通断点的话是断不下来的,因为这个地址时固定的所以我们直接alt + E
进入模块找到0x275C8B4E处下硬件断点即可,然后再每次重新打开poc的时候就会在这个地方断下来。
然后我们F8单步
可以断下来之后,我们用IDA加载MSCOMCTL.OCX模块来看一下刚才标记的VulFun函数,可以看到这里面有一个sub_275C88F4函数被调用了两次,这里原本是V5 == 1784835907
,将其标记为char类型之后为‘jboC’,这里按照小端存储的规则逆过来之后就是’Cobj’,后面的 &&dwBytes >= 8
,我们在immDbg中看到这个函数总共分配了0x14个字节大小的栈空间,在中间用掉了0xC个字节,剩余0x8字节,所以这里再判断 dwBytes >= 8,将dwBytes个数据再拷贝到栈上的时候,由于复制的大小超出0x8个字节,会导致溢出。
第一次调用sub_275C88F4复制了”Cobjd”字符串
在第二次调用sub_275C88F4的时候发生了溢出
动态执行到第二次sub_275C88F4拷贝结束的时候可以看到返回地址已经被0x41414141覆盖了,验证了我们前面的分析
现在我们已经大体上知道了溢出的点和原因在哪里,接下来我们分析一下poc.doc文件格式,看看程序是在解析doc文件中哪一字段时溢出的,下图是doc文件格式的开头内容
导致漏洞的是\object标签的内容,其中的\objocx代表在OLE容器中嵌入OCX控件,后面的\objdata包含对象数据,OLE对象采用OLESaveToStream结构,后面的D0CF11E0是OLE签名,代表DOCFILE,从这里开始就是OLE数据。如果我们直接用OffVis打开poc.doc解析,会得到未发现OLESS签名的错误。
这是因为poc.doc是RTF格式,里面的OLE数据是以文本形式存储,因此未被OffVis识别出来,可将从0xD0CF11E0开始至结尾的数据以16进制形式保存为test.doc,再用OffVis打开即可解析。
关于上面CLSID对应的控件,直接通过OLE Viewer或者注册表搜索即可查找到是ListViewA控件。然后找到覆盖返回地址的0x41414141,它位于EleName = Contents的Data字段
回头看下VulFun函数对此段数据的解析,回到IDA按F5查看C代码
动态调试数据
漏洞修复
下载补丁后,用binDiff对比打补丁前后的修复情况。
这里新添加了对dwVersion的判断:需要dwVersion等于0x64,dwBytes等于8才继续执行,否则直接返回
总结
对于栈溢出漏洞的分析,都是通过栈回溯的方法找到漏洞函数,可在原栈顶(上层函数返回地址)下内存写断点。程序断下时,经常是在mov和rep movs等用于实现字符串复制的相关指令处,再通过栈回溯或者函数交叉引用定位漏洞函数地址;而对于ActiveX控件的调试,一般通过OLEAUT32模块中的DispCallFunc函数对首个call ecx指令下断跟进,此时进入的就是POC中调用的控件函数,就得逐个跟进call ecx去判断对应的是哪个控件函数。上面的调试方法也不是唯一的,比如通过指令运行记录功能,将POC分别在漏洞版本和修复版本的程序上运行,再通过对比运行指令的差异性,从中找到漏洞成因及修复方法。
参考文章:
《漏洞战争》
- 标题: CVE-2012-0158
- 作者: xiaoeryu
- 创建于 : 2021-05-19 22:33:23
- 更新于 : 2023-11-17 19:37:35
- 链接: https://github.com/xiaoeryu/2021/05/19/CVE-2012-0158/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。