0x00 事件描述
2017年9月28日,360核心安全事业部高级威胁应对团队捕获了一个利用Office 0day漏洞(CVE-2017-11826)的在野攻击。该漏洞几乎影响微软目前所支持的所有office版本,在野攻击只针对特定的office版本。攻击者以在rtf文档中嵌入了恶意docx内容的形式进行攻击。微软在2017年10月17日发布了针对该漏洞的补丁。
本文我们将对该样本进行漏洞分析,主要是通过调试来探究漏洞形成的原因。
0x01 事件影响面
操作系统:Windows 7 sp1 32位
Microsoft Word版本:Word 2010 sp2 32位
wwlib.dll 版本:
调试工具:Windbgx86_v6.12.2.633.1395371577、Process Explorer、oletools工具包
0x02 样本分析
样本文件SHA-256值为:
cb3429e608144909ef25df2605c24ec253b10b6e99cbb6657afa6b92e9f32fb5
下载样本后,用winhex打开可以发现是一个rtf文件,并嵌入了ole对象,我们可以用oletools工具包中的rtfobj.py进行查看:
可以看到该RTF样本中包含了3个嵌入对象。
2.1 第一个ole对象
用winhex打开RTF样本并搜索“object”字符串可以找到第一个对象:
Oleclsid后面跟的一串字符为该COM对象的CLASSID,在注册表对应的是C:Windowssystem32msvbvm60.dll,通过ProcessExplorer也可以看到word加载了msvbvm60.dll,用于绕过ASLR。
因为该dll没有随机化,加载后也不会被随机化。从Office 2013起,微软已经强制使用ASLR,即使DLL没有随机化,但是一旦加载,模块地址也会被随机化了,所以这次的野外攻击只对Office 2010和之前的版本起作用。(尽管这次攻击对新版本没有影响,我们还是建议用户尽快安装官方提供的补丁。)
2.2 第二个ole对象
继续将剩下的两个对象提取出来,解压第二个嵌入的ole对象,是一个word对象,通过查看解压目录下的[Content_Types].xml,可以看到该样本插入了40个ActiveX对象:
同时我们也可以在/word/activeX目录里找到40个activeX*.xml文件和一个 activeX1.bin,这些文件是用来堆喷的。其中ActiveX1.bin为堆喷的内容。
通过堆喷来控制内存布局,使[ecx+4]所指的地址上填充上shellcode,最后通过shellcode调用VirtualProtect 函数来改变内存页的属性,使之拥有执行权限以绕过DEP保护。
具体做法:将EIP设置为0x088883EC,最后一个“popeax; retn”将0x729410d0填入eax中,这是VirtualProtect函数的地址,调用 VirtualProtect(0x8888C90,0x201, 0x40, 0x72A4C045)。
我们通过IDA静态反汇编msvbvm60.dll,可以找到导出的VirtualProtect函数:
2.3 第三个ole对象
提取第三个ole对象,也是一个word对象,在word目录中的document.xml中可以找到崩溃字符串”LincerCharChar”:
用winhex打开该文件,字符串中间乱码的为”E8 A3 AC E0 A2 80”:
但是我们在dump出来的内存中找到却是“EC 88 88 08”
这是由于编码转换的问题,“E8 A3 AC E0 A2 88”为ASCII形式,而“EC 88 88 08”是Unicode形式。验证如下:
根据参考文章中的分析,我们可以知道该样本攻击的大体流程:
样本在RTF 中嵌入了 3 个OLE 对象, 第一个用来加载msvbvn60.dll 来绕过系统ASLR,第二个用来堆喷,做内存布局,第三个用来触发漏洞。
0x03 漏洞分析
3.1 漏洞文件分析
我们新建一个doc文件,修改后缀名为.zip,用压缩工具打开,修改word目录下的document.xml,修改如下:
其实就是将样本文件中提取出来覆盖即可。然后重新修改后缀名为.doc。这样我们直接用word打开就可以触发漏洞,方便调试:
通过栈回溯可以发现漏洞发生在wwlib.dll(文件位置:C:Program FilesMicrosoft OfficeOffice14WWLIB.DLL)中:
并且是发生在wwlib!DllGetLCID+0x2cfcdc,所以我们用IDA来分析一下wwlib.dll,并跳转到相对应的位置:(通过实际调试发现,wwlib.dll过一段时间地址是会改变的,所以以下相对偏移地址读者要根据实际的情况调整)
崩溃点是发生在call dword ptr[ecx+4],如果有之前有堆喷操作进行内存布局,在0x88888ec上放置shellcode,那就可以跳转去执行,进行样本下一步的攻击。
在call wwlib!DllGetClassObject+0x430c (69469960)(即callsub_316d9960)下的第二个mov中取出的值为0x88888ec,此时查看eax的内存如下:
说明0x88888ec是样本里写死的。
我们将崩溃点所在的函数重命名为漏洞函数重名为vul_319B0280,其上级函数重命名为upfunc_3170F32A,函数调用关系如下:
接下来我们就从漏洞函数开始分析:(两个vul函数地址不同是因为wwlib.dll的地址变了,调的是同一个wwlib.dll)
可以看到esi为漏洞函数的第一个参数,eax为漏洞函数的第二个参数。
通过调试跟踪,我们可以看到漏洞函数的第二个参数+18h的位置是一个指向Unicode字符串的指针,[eax+1Ch]的位置是一个指向字符串个数的指针,打印出来如下图:
“shapedefaults”即xml中的一个标签名,我们可以使用条件断点将经过漏洞函数处理的标签打印出来,条件断点:bp wwlib+2dc0c0 “dd poi(esp + 4) + 894 L1; du poi(poi(esp + 8)+ 18) Lpoi(poi(esp + 8) + 1c); g;”。打印结果如下:
可以看到列出的标签里有OLEObject、idmap但没有font,说明font标签并没有在漏洞函数里处理。所以我们在上级函数下断点,看是否能够断到font标签?
断点:bp wwlib+3f40e “dupoi((edi)+18) lpoi(edi+1c);g;”
发现可以断到:
在崩溃前处理的标签分别是OLEObject、font、idmap,和样本的攻击代码一致。所以我们先在漏洞函数处理idmap时断下,看看处理过程中发生了什么?
触发漏洞时:
eax 的值为6,edx的值为4,其中ecx保存的是第一个参数+17F0,即esi存储的值。
该值表示当前处理标签的层数,6对应着就是攻击代码中的o:idmap标签。之后对ecx的值进行计算,获取font标签里的地址:
接下来我们要看看标签嵌套层数这个值是怎么变化的?
重新启动调试器,我们可以先在漏洞函数开始处下断点:bp wwlib+2E0280,然后在漏洞函数的上级函数开始处下条件断点:bp wwlib+3f32a “dd poi(esp + 4) + 894 L1; du poi(poi(esp + 8) +18) Lpoi(poi(esp + 8) + 1c); g;”。当处理到font标签时,对存储标签嵌套层数的位置继续下访问断点:ba w4 poi(poi(esi+17f0)):
第一次触发访问断点时:
此时eax为5,并且上层函数显示正在处理font标签。继续执行,访问断点再次被触发。
第二次触发访问断点时:
此时已经显示正在处理idmap标签了,而此时的嵌套层数为6。
3.2 正常文件分析
新建一个正常doc文件,将document.xml中的font标签闭合。像上面那样继续下断点调试。font的嵌套层数变成5后,遇到font闭合标签还会再减去1变成4:
继续运行,处理下一个标签idmap:
可以看到font标签闭合后,idmap的嵌套层数为5。得到正常的内存布局,漏洞没有被触发:
3.3 分析总结
上面得到标签嵌套层数后,接下来就会根据嵌套层数来计算地址:
计算地址函数为:
这里eax为标签的嵌套层数,edx为eax-2的值,ecx为漏洞函数参数1 +17F0h存储的值。所以地址的计算和参数1以及嵌套层数相关。正常文件处理idmap时,嵌套层数为5,edx为3,处理的是OLEObject标签的内存空间。漏洞文件处理idmap标签时,嵌套层数为5,edx为4,此时处理的是font标签的内存空间。这也可以通过分析补丁得到验证。
总结:通过上面的调试可以发现漏洞原因在于font标签没有闭合,在处理idmap标签时,操作的还是font标签的内存布局。
0x04 补丁分析
在虚拟机我们首先保存原先版本的快照,方便以后复原,然后提出wwlib.dll。再找到相应的补丁打上,提出wwlib.dll,针对调试环境打的补丁版本为KB3213630。在IDA中搜索关键指令,找到漏洞函数,打过补丁的wwlib.dll如下:
没有打过补丁的wwlib.dll如下:
打过补丁之后,可以看到多了一个判断分支。调试补丁到这发现:
两个值相等,跳转到右边分支,漏洞就无法被触发了。
根据动态跟踪调试发现[eax+48h]保存着一个地址指针,这里猜测[eax+48h]为当前对象处理函数的指针,调试中发现offsetsub_31e94a4a返回的是一个处理函数地址,而上级函数处理font标签时调用了该处理函数,所以可以猜想此处补丁是将当前对象处理函数的指针和font对象处理函数指针进行比较,相同就表明处理idmap标签时实际上处理的是font标签,跳转到右边分支,就不会执行到漏洞触发点了
0x05 处理建议
1、建议用户通过以下的补丁地址,尽快更新微软补丁
2、下载360安全卫士,尽快更新针对该漏洞的补丁
补丁下载地址:https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-11826
0x06 时间线
2017-09-28 360安全团队捕获漏洞的在野攻击
2017-10-10 微软官方公布针对该漏洞的补丁
2017-11-02 360CERT完成了基本分析报告
0x07 参考
1、https://bbs.pediy.com/thread-221995.htm
发表评论
您还未登录,请先登录。
登录