类型混淆漏洞一般是将数据类型A当做数据类型B来解析引用,这就可能导致非法访问数据从而执行任意代码。
本文通过IE类型混淆漏洞实例和Word类型混淆漏洞实例进行分析,来学习理解类型混淆漏洞原理。
实例一:IE/Edge类型混淆漏洞(CVE-2017-0037)
漏洞原因:函数处理时,没有对对象类型进行严格检查,导致类型混淆。
分析环境: Win7、IE11
分析工具: Windbg、od、IDA Pro
在PoC中定义了一个table,标签中定义了表id为th1,在boom()中引用,然后是setInterval设定事件。
漏洞成因分析:
运行PoC,用OD或Windbg附加并加载运行,出现崩溃,如下图
从崩溃点可以看到eax作为指针,引用了一个无效地址,导致崩溃,而上一条指令是一个call,如下
这个无效的返回值来自这个call,此时我们进行逆推,在这个call处下断点,
ecx作为参数,存放的对象是一个Layout::FlowItem::`vftable虚表
这个值会在Readable函数中引用,如下图
这里读取虚表中+4的值,为0时this指针赋值v1,随后v1+16后返回,因此,Layout::FlowItem::`vftable所属指针的这个情况是正常的,函数会正常返回进入后续处理逻辑。
让程序继续运行,会再次调用该函数,此时ecx并不是一个虚表对象,而是一个int Array对象,这里我们可以通过条件断点来跟踪两个对象的创建过程,重点关注两个对象创建的函数,一个是FlowItem::`vftable对应的虚表对象,另一个是引发崩溃的int Array对象。这两个函数的返回值,也就是eax寄存器中存放的指向这两个创建对象的指针。
通过条件断点,输出每一次int Array object创建的对象信息
通过跟踪可以看到第一次调用Readable函数时ecx是一个正常的FlowItem对象,而第二次调用的时候ecx是一个int Array Object。Layout::Patchable >::Readable函数是处理虚表对象的函数,由于boom()函数中引用th1.align导致Readable函数得到第二次引用,由于没有进行对象属性检查,导致第二次调用时将table对象传入,最终发生类型混淆崩溃。
分析利用关键点
首先我们分析崩溃点上下文,通过流程走向看看是否有可利用的点,
在判断eax返回值不等于0后,会继续往下调用Readable函数,且eax会连续引用,后面看到一个call edi,这是一个虚函数,如果我们能控制edi就有可能在这里达到代码执行的效果。其中有一个控制流保护机制CFG(call __guard_check_icall_fptr),Win7系统未开启所以这里不用考虑pass。
edi是由ecx(Array Object)传递过来的,通过修改th1对象中的width值为2000000,允许我们将EAX的值移动到堆喷射中的受控内存位置。
PoC中设置eip为0x41414141
这里eax=0bebc2d8,我们的受控位置为0Xbebc200=(2000000*100),在可控范围。
EIP被设置为0x41414141,由于加载的所有模块均启用了ASLR,目前仍没有绕过的方法。
实例二:Word类型混淆漏洞(CVE-2015-1641)
漏洞原因:
Word在解析docx文档的displacedByCustomXML属性时未对customXML对象进行验证,导致可以传入其他标签对象进行处理,造成类型混淆。
分析环境: Win7、Word2007
分析工具: Windbg、od、oletools、notepad++、WinHex
样本: https://github.com/houjingyi233/office-exploit-case-study/blob/master/CVE-2015-1641/8bb066160763ba4a0b65ae86d3cfedff8102e2eacbf4e83812ea76ea5ab61a31.bin.gz
首先解压样本并改后缀名为doc,用oletools的rtfobj分析结果为4个文件,分离保存。
在样本中提取第三个OLE,构造成rtf文件(上图为文件前半部分截图),打开该文件后出错,如下图,可以看到故障模块为wwlib.dll,异常偏移为0x9d30。
运行word,用windbg附加word进程,再打开rtf文件,异常出现在wwlib模块中的0x5c4a9d30,代码为mov esi,dword ptr [ecx],崩溃原因是[ecx]引用到无效地址。
这里ecx=0x7c38bd50,指向何处? 接下来分析保存出来的ole文件,解压后在资源文件“document.xml”中发现ecx的值正是smarttTag标签的element的属性值。
smartTag是一个智能标签,可针对人名、日期、时间、地址、电话号码等进行智能识别并允许用户执行特定操作的标签,displacedByCumtomXml属性表示此处要替换为另一个customxml标签,样本作者在smartTag的element中构造了0x7c38bd50,Word在解析docx文档处理displacedByCustomXML属性时未对customXML对象进行验证,所以能传入smartTag标签对象。
由于是单独加载触发漏洞OLE引用到无效地址,因为这个地址位于” MSVCR71.DLL”模块中,而这个DLL正是通过第一个OLE对象“otkloadr.wRAssembly.1”引入的。将第一个OLE对象:{\object\objocx{\*\objdata180115000002000000160000006f746b6c6f6164722e5752417373656d626c792e3100000000000000000001000000400105000000000000}},添加到触发漏洞的OLE前面,构建成RTF运行,再通过Windbg下条件断点,这里先记录下crash发生的时候“0x7c38bd50 “所在的模块地址,通过它来下条件断点:
0x7C38BD50是smartTag标签的element值,4294960790(0xFFFFE696)是moveFromRangeStart的值,随后对这两个值进行计算得到一个地址0x7C38BD74。计算过程如下:
第二个smartTag,smartTag标签的element值此时为0x7C38BD68,moveFromRangeStart的值为0x7C376FC3(十进制为2084007875),计算出的地址为0x7C38A428,最后通过memcpy函数将0x7C376FC3覆盖到地址0x7C38A428中,在调试器可以看到,0x7C38A428为虚表指针:
接着往下执行,
会先经过一大片地址为“7C342404”的“ret”,然后进入ROP链,再往后就是shellcode。
将id为1的OLE解压后,
在解压目录的“activeX1.bin“中看到用来堆喷的数据块:nop指令上面的是ROP链,heapspary前会使用大量地址为0x7c342404 的ret-sled,
以上两实例分析文章在网上较多,这里只做一个浅析,不做深入分析。
原创文章转载请注明来源:四维创智***实验室
转载于:https://blog.51cto.com/13694685/2352767