类型混淆漏洞一般是将数据类型A当做数据类型B来解析引用,这就可能导致非法访问数据从而执行任意代码。

本文通过IE类型混淆漏洞实例和Word类型混淆漏洞实例进行分析,来学习理解类型混淆漏洞原理。

实例一:IE/Edge类型混淆漏洞(CVE-2017-0037)

漏洞原因:函数处理时,没有对对象类型进行严格检查,导致类型混淆。

分析环境:    Win7、IE11

分析工具:    Windbg、od、IDA Pro

             

506db2b45b05d5ec2ee2f13cca29bfda

在PoC中定义了一个table,标签中定义了表id为th1,在boom()中引用,然后是setInterval设定事件。

漏洞成因分析:

运行PoC,用OD或Windbg附加并加载运行,出现崩溃,如下图

0665831be72f200edd008e6650427830

2cdeaf5b9737bbd19a0a0f8c3d0e8fec

从崩溃点可以看到eax作为指针,引用了一个无效地址,导致崩溃,而上一条指令是一个call,如下

185be3e8bb6b4f225bdc07238a10a2c1

这个无效的返回值来自这个call,此时我们进行逆推,在这个call处下断点,

787b760cfda9611342a10af9df7c1902

ecx作为参数,存放的对象是一个Layout::FlowItem::`vftable虚表

8abbe161657ffd95360e14dbee7d5a57

这个值会在Readable函数中引用,如下图

3841b2d14e5d6c1ca0f25ff85e5bca80

bec2af611992baecd35551c52ebb45f6

这里读取虚表中+4的值,为0时this指针赋值v1,随后v1+16后返回,因此,Layout::FlowItem::`vftable所属指针的这个情况是正常的,函数会正常返回进入后续处理逻辑。


c76b2b5c938ff653b1336716efbd33c2

让程序继续运行,会再次调用该函数,此时ecx并不是一个虚表对象,而是一个int Array对象,这里我们可以通过条件断点来跟踪两个对象的创建过程,重点关注两个对象创建的函数,一个是FlowItem::`vftable对应的虚表对象,另一个是引发崩溃的int Array对象。这两个函数的返回值,也就是eax寄存器中存放的指向这两个创建对象的指针。


697071c9fe27679ad7dfba279dc21d8f

4345e7b3a8b11ed0aa94c8daed0dedfd

通过条件断点,输出每一次int Array object创建的对象信息

ae6fc1f44330f80bb1d88244801e042d

1%C3%97%C3%97%C3%977a6b1852ac4451e440dcc40b9ac

通过跟踪可以看到第一次调用Readable函数时ecx是一个正常的FlowItem对象,而第二次调用的时候ecx是一个int Array Object。Layout::Patchable >::Readable函数是处理虚表对象的函数,由于boom()函数中引用th1.align导致Readable函数得到第二次引用,由于没有进行对象属性检查,导致第二次调用时将table对象传入,最终发生类型混淆崩溃。


分析利用关键点

首先我们分析崩溃点上下文,通过流程走向看看是否有可利用的点,

185dbd91a1075182c002f5ba95bbbf20

在判断eax返回值不等于0后,会继续往下调用Readable函数,且eax会连续引用,后面看到一个call edi,这是一个虚函数,如果我们能控制edi就有可能在这里达到代码执行的效果。其中有一个控制流保护机制CFG(call __guard_check_icall_fptr),Win7系统未开启所以这里不用考虑pass。

d812d9ff9be985de1cf68086ad8c5d62

edi是由ecx(Array Object)传递过来的,通过修改th1对象中的width值为2000000,允许我们将EAX的值移动到堆喷射中的受控内存位置。

209524bdd9f3128812e7bed86021fe4d

de6dfbb2d49851c2a5f6010554f95b8e

PoC中设置eip为0x41414141

6d421ff4007da2b049e26de3f4f215b8

这里eax=0bebc2d8,我们的受控位置为0Xbebc200=(2000000*100),在可控范围。

7bd3a29879509a861bfe572c2ff402d5

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

4fa5b12bb0e75cd8a32db874d68a9a92

首先解压样本并改后缀名为doc,用oletools的rtfobj分析结果为4个文件,分离保存。

3bf9bb5bd5e0a5dbf443485bea664e8d

在样本中提取第三个OLE,构造成rtf文件(上图为文件前半部分截图),打开该文件后出错,如下图,可以看到故障模块为wwlib.dll,异常偏移为0x9d30。


f577c12443b7d9815c1d229d23d3dc93

运行word,用windbg附加word进程,再打开rtf文件,异常出现在wwlib模块中的0x5c4a9d30,代码为mov esi,dword ptr [ecx],崩溃原因是[ecx]引用到无效地址。

7edc5dca8049bebc19f89d84efcb0c0d

这里ecx=0x7c38bd50,指向何处? 接下来分析保存出来的ole文件,解压后在资源文件“document.xml”中发现ecx的值正是smarttTag标签的element的属性值。

28f47f49701536a53bc28a4b47ae634d

smartTag是一个智能标签,可针对人名、日期、时间、地址、电话号码等进行智能识别并允许用户执行特定操作的标签,displacedByCumtomXml属性表示此处要替换为另一个customxml标签,样本作者在smartTag的element中构造了0x7c38bd50,Word在解析docx文档处理displacedByCustomXML属性时未对customXML对象进行验证,所以能传入smartTag标签对象。

b883658cda120db06e06a583671cb0af

由于是单独加载触发漏洞OLE引用到无效地址,因为这个地址位于” MSVCR71.DLL”模块中,而这个DLL正是通过第一个OLE对象“otkloadr.wRAssembly.1”引入的。将第一个OLE对象:{\object\objocx{\*\objdata180115000002000000160000006f746b6c6f6164722e5752417373656d626c792e3100000000000000000001000000400105000000000000}},添加到触发漏洞的OLE前面,构建成RTF运行,再通过Windbg下条件断点,这里先记录下crash发生的时候“0x7c38bd50 “所在的模块地址,通过它来下条件断点:

f1ee53b2d149cbb1833de65bd183ff4a

0x7C38BD50是smartTag标签的element值,4294960790(0xFFFFE696)是moveFromRangeStart的值,随后对这两个值进行计算得到一个地址0x7C38BD74。计算过程如下:

396b8cede6531e4089e85318d0545bd4

3c626ddc174e47b3b1ef66c202f19b45

第二个smartTag,smartTag标签的element值此时为0x7C38BD68,moveFromRangeStart的值为0x7C376FC3(十进制为2084007875),计算出的地址为0x7C38A428,最后通过memcpy函数将0x7C376FC3覆盖到地址0x7C38A428中,在调试器可以看到,0x7C38A428为虚表指针:

e62210681b8289d74605281a69473540

接着往下执行,

会先经过一大片地址为“7C342404”的“ret”,然后进入ROP链,再往后就是shellcode。

bc4bf95bdb77dc1d44e45539a0f35934

将id为1的OLE解压后,

在解压目录的“activeX1.bin“中看到用来堆喷的数据块:nop指令上面的是ROP链,heapspary前会使用大量地址为0x7c342404 的ret-sled,

693b0486e3cbf9a8b98a7c64320f0306

以上两实例分析文章在网上较多,这里只做一个浅析,不做深入分析。

原创文章转载请注明来源:四维创智***实验室