CVE-2012-0158

xiaoeryu Lv5

一、漏洞信息

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 进行许可。
评论