CVE-2017-11826浅析-word类型混淆漏洞

来源:互联网 发布:php 抓取url内容 编辑:程序博客网 时间:2024/06/05 16:29

本文转载自CVE-2017-11826样本分析
北京时间2017年10月11日,微软在10月的安全公告中公开致谢奇虎360,后者在9月底向其秘密报告了一个在野office 0day并积极协助修复。该漏洞的成因是</w:font>标签没有正确闭合,造成用OLEObject的数据结构解析了font提供的数据。攻击者通过在font的name属性中提供精心构造的数据,覆写了一个函数指针,从而实现控制流劫持。该漏洞是和CVE-2015-1641一样经典的类型混淆漏洞。若无特殊说明,文中的分析环境均为Win7 x86+Office 2007(wwlib.dll的版本号为12.0.4518.1014)。
SHA256:cb3429e608144909ef25df2605c24ec253b10b6e99cbb6657afa6b92e9f32fb5
windbg附加调试打开文档会崩溃在此处。
这里写图片描述
这里写图片描述
和大多数情形一样,漏洞的利用是借助嵌入OLE对象来实现的,我们可由oletools工具包中的rtfobj.py进行查看。
这里写图片描述
可以发现该样本内嵌三个对象,id为0的对象用来加载msvbvm60.dll绕过ASLR,后两个提取出来之后把后缀名改成zip解压。
这里写图片描述
这里写图片描述
id为1的对象用于堆喷射。
这里写图片描述
id为2的对象用来触发漏洞,查看word目录中的document.xml。
这里写图片描述
可以看到font标签之间的内容有点奇怪,怀疑是编码的问题,试着转换一下就得到了实际的值,正是崩溃点处eax的值。
这里写图片描述
这里写图片描述
eax的值依赖于上面那个call的返回值,重新开始,对该call下断,跟到call后第二条mov时可以看到从eax+44h取出的值是0x088888ec,这时看下eax的内存。
这里写图片描述
在发生奔溃的函数下断点运行,发现该函数会被断下多次,这里如果没有明显的条件用于判断在哪次中断时发生奔溃,可以统计该奔溃函数的调用次数,看看是在第几次发生的奔溃,然后再下相应的条件断点。
这里写图片描述
为了方便调试可以用oletools提取出来的文件,但是单独打开并不会崩溃,这里可以把document.xml中w:body里面的内容复制出来然后新建一个DOCX文件,随便写入一些内容之后用7z打开,把刚复制出来的内容替换word\document.xml中w:body的内容,再次打开DOCX可以看到奔溃在同一个地方。接下来跟踪一次不奔溃时执行该函数的流程,在IDA中用一个颜色把路径标出来,然后再跟一次奔溃时的流程,用另一个颜色把不同的路径标出来。主要的不同在下面这个地方。
这里写图片描述
当不奔溃时ecx为0而奔溃时ecx为1。这里ecx来自[esi+224h],通过IDA知道esi等于第一个参数,所以该值也可以做为条件断点的条件。通过跟踪函数流程可以知道奔溃函数的第二个参数+18h处是一个unicode字符串指针,+1ch处是字符个数。字符串的内容是文档的XML中的一些标签名,比如shapedefaults和idmap。下断点时通过输出该字符串可以知道现在处理的是哪个标签。
这里写图片描述
观察输出里面并没有出现POC中的w:font标签。这里我们可以回溯到奔溃函数的上级函数下断看看能不能断到font。奔溃函数的第一个参数等于poi(上级函数的第一个参数+0xb10),第二个参数等于上级函数的第二个参数,所以在这个函数下断依然可以输出第二个参数中的字符串。
这里写图片描述
这里写图片描述
测试后可以知道在上级函数是可以断到font的,只不过在处理font时没有进入奔溃函数,而是由别的函数处理。
这里写图片描述
前面我们分析过取出0x088888ec的地址是根据一个函数的返回值得到的。该函数的返回值等于调用该函数时的edx*[eax+8]+[eax+0ch]+eax,这里的edx为poi(poi(poi(参数1+b14)))。调试可以知道在奔溃时edx等于4,+8和+0ch处的值是4ch和10h(多次调试可以知道这两个值不管处理哪个标签时都是固定的),所以也就是eax+140h。eax等于poi(poi(参数1+0xb14))。在奔溃函数下断,处理OLEObject时停下,根据上面的表达式手工计算出奔溃时计算的地址,然后dd查看计算的地址+44h,发现此时这里全是0,所以这里对计算的地址+44h下ba w4断点。运行后首先断在上级函数,输出的字符串是font,说明开始处理font标签了。继续运行,接着内存写入断点触发。
这里写图片描述
这里写图片描述
这里db看下写入值的数据(减4是因为访问断点是在访问后才断下),正是奔溃时的数据。继续运行又断在了上级函数,输出idmap,再运行就会断在奔溃函数,输出同样是idmap。再运行就奔溃了。通过阅读ECMA-376文档可以知道这里font标签缺少关闭标签。
这里写图片描述
接下来分别调试有关闭标签的和没关闭标签的。首先在奔溃函数下断点,到处理OLEObject时对上级函数下断,对上面计算的地址+0x44h下写入断点。执行后可以发现在有关闭标签时当奔溃函数处理idmap时,在下面位置触发了写入断点。
这里写图片描述
这里重新写入了正常的值,上面的call同样是返回一个计算的地址,计算方法和奔溃点的call是一样的。只是这里edx等于poi(poi(poi(第一个参数+b14)))-1,而奔溃点是poi(poi(poi(第一个参数+b14)))-2。当上级函数处理OLEObject时查看poi(poi(poi(esp+4)+b14))处的值并对该位置下内存写入断点。经过多次调试可以发现当上级函数准备处理OLEObject时该值是3,处理过程中将该值修改为4,该值应该是标签的的嵌套层次(POC的document.xml中OLEObject就是嵌套的第4个标签,从document标签开始)。
这里写图片描述
当有关闭标签时,处理font标签时先增到5然后再减1,处理idmap时再修改为5,最后进入奔溃函数;当没有关闭标签时,处理font增到5而后并没有减1操作,到处理idmap时为6。
这里写图片描述
处理OLEObject时为4,有关闭标签的情况下,0x312C63DE处的call sub_3127F3FB把正常对象设置到4-1后计算的位置,到处理idmap时为5,在奔溃点处计算时是5-2,获取的正是OLEObject设置的值。没关闭标签的情况下,处理font时为5,处理font用了其它函数,不过也是修改5-1后计算的位置。到处理idmap时为6,在奔溃点用6-2计算,这里正是font设置的值。由于font和OLEObject设置的对象内存布局并不同,导致在奔溃点获取一个对象时,获取了font的name属性中的数据。漏洞的利用流程在前面还原POC时基本已经摸清了,就是通过堆喷布局内存然后在触发漏洞的文件中指定一个地址,最后根据该指定地址执行shellcode。

原创粉丝点击