Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

$
0
0
【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

2017-03-20 10:33:06
来源:whereisk0shl.top 作者:k0shl

阅读:105次
点赞(0)
收藏





【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

前言

前段时间Google Project Zero(PJ0)曝光了一个关于IE11和Edge的一个类型混淆造成代码执行的漏洞,微软至今未推出关于这个漏洞的补丁,我对这个漏洞进行了分析,并且通过PoC构造了半个Exploit,为什么是半个呢,首先这个漏洞攻击面比较窄,只能控制Array里+0x4位置的值,通过类型混淆会认为这个值是一个指针,随后会调用指针某偏移处的虚函数,当我们能够控制这个指针的值的时候,虚函数也能够得到控制。这样就能劫持程序流,达到代码执行的效果。但这其中涉及到一个ASLR的问题,由于地址随机化,导致我们就算控制跳转之后,无法通过info leak来构造ROP,也就是DEP也无法绕过。

这里我也有考虑到袁哥的DVE,但由于我们并没有RW primitives,因此我们控制关键指针的条件太有限,导致想通过GodMod来执行脚本的方法似乎也不太可行(或者我没有发现?求大牛指教!)。

因此这里,我写了一个在关闭DEP时可以使用的exploit,并且和大家一起分享从PoC到Exp的整个过程,不得不说过程还是很麻烦的,因为想寻找这个Array+0x4位置的控制值如何能够DWORD SHOOT,我跟了Layout::TableBoxBuilder类下的很多函数。

PJ0 CVE-2017-0037 PoC地址:

https://bugs.chromium.org/p/project-zero/issues/detail?id=1011

目前来看,微软并没有更新这个exp的补丁,但是有人利用0patch修补了这个漏洞,其实我看起来感觉不太像从根本上解决了这个漏洞的问题:

https://0patch.blogspot.jp/2017/03/0patching-another-0-day-internet.html

尽管这个Type Confusion攻击面有限,但是Type Confusion这种漏洞是非常常见的,它的原理一般情况下是由于函数处理时,没有对对象类型进行严格检查,导致可以通过某些手段来造成类型混淆,通过对其他可控类型的控制可以达到代码执行的效果,甚至任意内存读写,比如Memory Corruption。

好啦,不多说了!下面我们来进入今天的分析,首先我们漏洞分析的环境:

windows7x64sp1build7601 IE11.0.9600.17843
【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

漏洞分析

首先漏洞的关键出现在boom()中,在PoC中定义了一个table表,其中在标签中定义了表id为th1,在boom()函数中引用到,随后通过setInterval设定事件。

运行PoC,可以捕获到漏洞崩溃,附加Windbg。

0:003:x86>r eax=00000038ebx=0947ffb0ecx=0947ffb0edx=00000002esi=00000064edi=6e65c680 eip=6e20fc87esp=086abdc0ebp=086abdeciopl=0nvupeiplnznaponc cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00010202 MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d36: 6e20fc87833800cmpdwordptr[eax],0ds:002b:00000038=????????

可以看到,这里eax作为指针,引用了一处无效地址,从而引发了崩溃,直接回溯崩溃位置的上下文,可以看到,在cmp汇编指令之前,调用了一处函数Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem> >::Readable。

而eax寄存器正是Readable函数的返回值。我们在这个函数call调用位置下断点,重新执行windbg。

0:007:x86>r eax=0a020590ebx=007e79f0ecx=007e79f0edx=007e79f0esi=00000064edi=69ad8080 eip=6968fc82esp=0900b878ebp=0900b8a4iopl=0nvupeiplnznaponc cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00000202 MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d31: 6968fc82e86df072ffcallMSHTML!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable(68dbecf4)

可以看到,ecx寄存器作为第一个参数,看一下这个参数存放的对象。

0:007:x86>dpsecx 007e79f068d82230MSHTML!Layout::FlowItem::`vftable' 007e79f400000000//这个值将会在Readable函数中引用 007e79f800000009 007e79fc007ec8d4 007e7a000a020660 007e7a0400000064 007e7a0800000064 007e7a0c007e79f0 007e7a10007e79f0 007e7a1468d82230MSHTML!Layout::FlowItem::`vftable' 007e7a1800000000 007e7a1c00000009 007e7a20007ec8d4 007e7a240a01fc60 007e7a2800000000 007e7a2c00000000 007e7a30007e7a14 007e7a34007e7a14

这个参数存放的对象是一个Layout::FlowItem::`vftable虚表,随后通过IDA来分析一下这个函数的功能。

int__thiscallLayout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable(intthis) { intv1;//eax@2 intresult;//eax@4 if(*(_BYTE*)(*(_DWORD*)(__readfsdword(44)+4*_tls_index)+36)) //gettlsarray { result=this+16; } else { v1=*(_DWORD*)(this+4); if(!v1)//这个位置会检查this+0x4位置的值,如果为0,则进入处理 v1=this;//获取vftablepointer result=v1+16; } returnresult; }

这里,读取虚表+0x4位置的值为0,因此会执行if(!v4)中的逻辑,会将this指针交给v1,随后v1+0x10后返回,因此,Layout::FlowItem::`vftable所属指针的这个情况是正常的情况,函数会正常返回进入后续处理逻辑。

0:007:x86>p MSHTML!Layout::Patchable<Layout::SharedBoxReferenceDataMembers>::Readable+0x1e: 68dbed1683c010addeax,10h 0:007:x86>p MSHTML!Layout::Patchable<Layout::SharedBoxReferenceDataMembers>::Readable+0x21: 68dbed19c3ret//函数正常返回 0:007:x86>reax eax=007e7a00 0:007:x86>dpseax 007e7a000a020660 007e7a0400000064 007e7a0800000064 007e7a0c007e79f0 007e7a10007e79f0 0:007:x86>p Breakpoint0hit//这个地方会引用正常的值 MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d36: 6968fc87833800cmpdwordptr[eax],0ds:002b:007e7a00=0a020660

直接继续执行,程序会第二次命中Readable函数,这次来看一下ecx中存放的对象。

0:007:x86>r eax=0a020000ebx=0a020120ecx=0a020120edx=00000000esi=00000064edi=69adc680 eip=6968fc82esp=0900b878ebp=0900b8a4iopl=0nvupeiplnznaponc cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00000202 MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d31: 6968fc82e86df072ffcallMSHTML!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable(68dbecf4) 0:007:x86>dpsecx 0a02012000000000 0a02012400000028 0a02012800000050 0a02012c00000078 0a020130000000a0 0a020134000000c8 0a020138a0a0a0a0 0a02013ca0a0a0a0

这次存放的对象并非是一个虚表对象,这个对象是一个int Array的维度对象,这样我们通过条件断点来跟踪两个对象的创建过程。我们重点关注两个对象创建的函数,一个是FlowItem::`vftable对应的虚表对象,另一个是引发崩溃的int Array对象。这两个函数的返回值,也就是eax寄存器中存放的就是指向这两个创建对象的指针。

MSHTML!Array<Math::SLayoutMeasure>::Create MSHTML!Array<SP<Tree::TableRowGroupBlock>>::Create

通过对这两个对象进行跟踪,我们可以看见到对象的创建,以及后续引用对象,导致Type Confusion。

//下条件断点,打印每一次intArrayobject创建的信息 0:007:x86>bp6912e1fb".printf\"Something:0x%08x,0x%08x\\n\",@eax,poi(eax);g;" //对象被不断创建 0:007:x86>g Something:0x088abc84,0x0098c788 Something:0x088abc84,0x09806790 Something:0x088abc84,0x097d9010 Something:0x088abc5c,0x097dafd8 Something:0x088abc84,0x097ce050 Something:0x088abc84,0x098026e0 Something:0x088abc84,0x098044c8 Something:0x088abc84,0x097ff540 Something:0x088abc5c,0x097d5058 Something:0x088abafc,0x097cab00 Something:0x088abafc,0x0980a690//key!! Breakpoint1hit MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d31: 6968fc82e86df072ffcallMSHTML!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable(68dbecf4) 0:007:x86>r//第一次命中时,是正常的FlowItem对象 eax=0980aa80ebx=0094d364ecx=0094d364edx=0094d364esi=00000064edi=69ad8080 eip=6968fc82esp=088abb28ebp=088abb54iopl=0nvupeiplnznaponc cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00000202 MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d31: 6968fc82e86df072ffcallMSHTML!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable(68dbecf4) 0:007:x86>g Breakpoint1hit MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d31: 6968fc82e86df072ffcallMSHTML!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable(68dbecf4) 0:007:x86>r//第二次命中时,注意ecx寄存器的值,0x0980a690 eax=0980a570ebx=0980a690ecx=0980a690edx=00000000esi=00000064edi=69adc680 eip=6968fc82esp=088abb28ebp=088abb54iopl=0nvupeiplnznaponc cs=0023ss=002bds=002bes=002bfs=0053gs=002befl=00000202 MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d31: 6968fc82e86df072ffcallMSHTML!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable(68dbecf4)

果然第二次命中的时候,是一个int Array Object。因此,这个漏洞就是由于Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem> >::Readable函数是处理虚表对象的函数,但是由于boom()函数中引用th1.align导致Readable函数第二次引用,由于没有对对象属性进行检查,导致第二次会将table对象传入。

这就是一个典型的Type Confusion。

而Readable会将这个对象当作虚表对象处理,而这个int Array维度对象我们可以控制,从而通过控制Readable返回值来达到代码执行。


Exploitation Surface

如果想利用这个漏洞,我们需要分析一下攻击面,首先是我们可控的位置是什么(也就是在之前我提到的int Array的维度),这个可控的位置是否有利用点,有哪些防护,是否有可能绕过等等。

首先我们来看一下利用位置的上下文。

cmpdwordptr[eax],0 jeMSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d83 movecx,ebx callMSHTML!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable movdwordptr[ebp-10h],esp movebx,dwordptr[eax] moveax,dwordptr[ebx] movedi,dwordptr[eax+1A4h] movecx,edi calldwordptr[MSHTML!__guard_check_icall_fptr] movecx,ebx calledi

可看到,在eax作为指针返回后,会在后续继续调用到一个Readable函数,而在这个函数后返回后,eax会连续传递,最后调用到call edi,引用这个虚函数。

也就是说,一旦我们可以控制这个指针,我们就有可能在call edi位置达到代码执行的效果。

而可以看到,在call edi之前,有一处call __guard_check_icall_fptr,这是Windows新的防护机制CFG,在执行虚函数调用前,会检查虚函数。


【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

由于我们调试环境是Win7,CFG只在高版本的Windows中启用,比如win8和win10,因此这处CFG check在Win7环境下并没有实际作用,是在Win8和Win10高版本开启后,为了向下兼容,而在Win7中加入的这处函数调用。

因此,我们简单分析一下我们的攻击面,首先我们可控的位置是int Array Object+0x4位置的值,这个值控制范围有限,因此我们似乎不能通过这种方法来获得任意地址的读写能力,因此对于我们来说ASLR对于这个漏洞来说不好绕过。ASLR和DEP不好绕过。

接下来,我们要分析的就是,如何控制这个值。这个对象经过我们刚才的分析,是由MSHTML!Array<Math::SLayoutMeasure>::Create函数创建的对象,但赋值并非在这个位置。在分析的过程中,我对Layout中的大量类函数进行了跟踪分析,这里我将通过正向来直接跟大家展示这个值是从什么位置来的。

跟踪TableBoxBuilder结构体

这里,我们稍微修改一下PoC,主要是对th1对象中的width值进行修改。

<thid="th1"colspan="5"width=10000></th>

下面调试过程中,由于多次重启,堆地址值有所变化,但不影响分析。

首先,我们要关注的是一个名为FlowBoxBuilder的对象,这个对象偏移+0x124的位置将会存放Width值生成的一个size。在Layout::FlowBoxBuilder::FlowBoxBuilder函数中,这个结构体对象被创建。

0:007:x86>p MSHTML!Layout::FlowBoxBuilder::FlowBoxBuilder+0xe: 67c70ae48bd9movebx,ecx//对象位置被初始化 0:007:x86>recx ecx=09a42ad8 0:007:x86>dd09a42ad8+124//对应位置的成员变量已经被初始化 09a42bfce0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0 0:007:x86>baw109a42ad8+124//对+0x124位置下写入断点 0:007:x86>g Breakpoint4hit MSHTML!Layout::FlowBoxBuilder::InitializeBoxSizing+0x11b: 67b18c75f3a5repmovsdwordptres:[edi],dwordptr[esi] 0:007:x86>dd09a42ad8+124//可以看到在InitializeBoxSizing函数中被赋值 09a42bfc00989680=1000000

可以看到,在MSHTML!Layout::FlowBoxBuilder::InitializeBoxSizing函数中,FlowBoxBuilder+0x124位置被赋值。赋值的内容是0x989680,就是1000000,这个值又是从哪里来的呢?在MSHTML中有一个函数MSHTML!Layout::ContainerBoxBuilder::ComputeBoxModelForChildWithUsedWidth,这个计算会将table的width*100。

如上面的代码片段,FlowBoxBuilder在InitializeBoxSizing中初始化之后,偏移+0x124位置会将ComputeBoxModelForChildWithUsedWidth函数的计算值保存。

随后这个值会加上200,之后这个值回存入结构体中,然后会存放在FlowBoxBuilder结构体+0x114的位置。

67b0201a8906movdwordptr[esi],eax 0:007:x86>g Breakpoint7hit MSHTML!TSmartPointer<Tree::TextBlock>::operator=+0x13: 67b0201c85c9testecx,ecx 0:007:x86>dd09b40948+114// 09b40a5c09b778d000000000e0e0e0e000000000//在FlowBoxBuilder+0x114位置存放了一个结构体 09b40a6c00989874//+200之后依然存放在FlowBoxBuilder+0x124的位置 0:007:x86>dd09b778d0 09b778d067e6c5740000000109b3656009b6f968//结构体+0xc位置存放着目标结构体,这个结构体其实就是一个intArray结构,这个结构会在后续调用中用到。 09b778e000989874 0:007:x86>dd09b6f968 09b6f96800000000001e84a8003d0950005b8df8 09b6f978007a12a000989748a0a0a0a0a0a0a0a0 09b6f98800000000000000004c762d5c000c2ca7 09b6f99809b5a4a809b71a68f0f0f0f0f0f0f0f0 09b6f9a8f0f0f0f0f0f0f0f0a0a0a0a0a0a0a0a0 09b6f9b8000000000000000059752d4a140c2caa 09b6f9c8abcdaaaa80411000000000440000006c 09b6f9d809b6fa5809b6f91004d67e6cdcbaaaaa 0:007:x86>kb//调用逻辑 ChildEBPRetAddrArgstoChild 08efb8f467e6c0fc09b778d008efbd5409b409d0MSHTML!TSmartPointer<Tree::TextBlock>::operator=+0x13 08efb94067e6c03e090b82f809b4090009b40a20MSHTML!Layout::SBoxModel::CalculateFullBoxModelForTable+0x9f 08efb9bc67b1a3dc090b82f809b4090009b40a20MSHTML!Layout::SBoxModel::CalculateFullBoxModel+0x270 08efbac467b1236508efbd540001f40008efbcecMSHTML!Layout::FlowBoxBuilder::BuildBoxItem+0x25a

到此,我们完成了对FlowBoxBuilder结构体关键成员变量的赋值,这个成员变量会在后续调用中,进入很关键的TableBoxBuilder结构体,我们关键的Array位置存放在FlowBoxBuilder+0x114的指针内偏移为+0xc的指针处,接下来我们进入TableBoxBuilder类函数跟踪。

+0xc的这个Array会在TableBoxBuilder::InitialBoxSizing函数中交给TableBoxBuilder结构体+0x294的位置。

0:007:x86>p MSHTML!Layout::TableBoxBuilder::InitializeBoxSizing+0x5c: 67e766ac8d460cleaeax,[esi+0Ch]//esi存放的就是FlowBoxBuilder+0x114的指针 //+0xc位置存放的就是Array结构体 0:007:x86>p MSHTML!Layout::TableBoxBuilder::InitializeBoxSizing+0x5f: 67e766af50pusheax 0:007:x86>p MSHTML!Layout::TableBoxBuilder::InitializeBoxSizing+0x60: 67e766b08d8b94020000leaecx,[ebx+294h]//ebx存放的是TableBoxBuilder+0x294的指针地址 0:007:x86>p//调用SArray::operator MSHTML!Layout::TableBoxBuilder::InitializeBoxSizing+0x66: 67e766b6e879e6c4ffcallMSHTML!SArray<Layout::TableGridBox::SRowGroupInfo>::operator=(67ac4d34)//esi+0c 0:007:x86>dd0963ba2c//esi+0xc的值 0963ba2c00a2beb000000000e0e0e0e000000000 0:007:x86>dda2beb0 00a2beb000000000001e84a8003d0950005b8df8 00a2bec0007a12a000989748a0a0a0a0a0a0a0a0 在MSHTML!SArray<Layout::TableGridBox::SRowGroupInfo>::operator函数中,会完成对TableBoxBuilder+0x294位置的赋值,就是将上面代码中esi+0xc的值,交给TableBoxBuilder+0x294。 0:007:x86>g Breakpoint4hit MSHTML!SArray<Math::SLayoutMeasure>::operator=+0x1a: 67ac4d4e85c9testecx,ecx 0:007:x86>dd09d7ff30+294//偏移294位置存放着TableBoxBuilder中的size部分,用于赋值给TypeConfusion的对象 09d801c409d7da3000000000e0e0e0e000000000 09d801d400000000a0a0a0a0a0a0a0a009d7f868 0:007:x86>dd09d7da30//已经完成了Size的赋值操作 09d7da3000000000001e84a8003d0950005b8df8 09d7da40007a12a000989748a0a0a0a0a0a0a0a0 0:007:x86>kb ChildEBPRetAddrArgstoChild 08e7b87867e766bb09da48bc08e7bbbc08e7b8a8MSHTML!SArray<Math::SLayoutMeasure>::operator=+0x1a 08e7b89067ccb346051d2fd8051d2f8809da48b0MSHTML!Layout::TableBoxBuilder::InitializeBoxSizing+0x6b

在最后漏洞触发位置的MSHTML!Layout::TableGridBox::InitializeColumnData函数中,会完成对我们漏洞触发位置的Type Confusion的结构体内容的赋值。

6912e2268b8394020000moveax,dwordptr[ebx+294h]ds:002b:0924592c=09245598//whatisebxandebx+294ebxisstructLayout::TableBoxBuilder 6912e22c8b0emovecx,dwordptr[esi]//获取我申请的堆指针 6912e22e8b0490moveax,dwordptr[eax+edx*4]//计算TableBoxBuilder对应294位置的值+索引*sizeof 6912e231890491movdwordptr[ecx+edx*4],eax//将这个值交给申请堆指针对应索引的位置 6912e23442incedx//edx=edx+1//自加1 6912e2353bd7cmpedx,edi//checklenth检测是否已经到达我申请的堆大小 6912e2377cedjlMSHTML!Layout::TableGridBox::InitializeColumnData+0x6c(6912e226)

可能大家这个时候有点乱了,下面我将用一个流程图来展示一下结构体的赋值过程。大致就是首先会通过计算获得Width的一个size,计算方法是:Width*100+200,随后,会将这个值保存在一个Array里,这个Array的大小后面会讲到。之后会将这个Array存入一个指针偏移+0xc的位置,交给FlowBoxBuilder结构体+0x114的位置。之后,会赋值给TableBoxBuilder结构体+0x294位置,最后会交给漏洞触发位置申请的堆指针。


【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

而经过我们上面的分析,产生漏洞的位置在这个Array+0x4位置,我们也需要通过table的条件控制这个位置的值,才能达到利用。


控制Array结构到漏洞利用

通过上面的跟踪,我们知道了id=th1的Table中的Width可以控制一个Array结构,但是我们也发现Array结构并非单独只包含一个Width计算得到的值。

0:007:x86>dd9bc7038 <thid="th1"colspan="5"width=1000></th>// 09bc70380000000000004e4800009c900000ead8 09bc70480001392000018768a0a0a0a0a0a0a0a0

可以看到,Array结构是有一个大小的,其实,这个Array中存放的值,取决于width,而大小取决于colspan,这个colspan为5的情况下,Array中存放了5个值,而我们需要控制的是Array+0x4这个位置的值,这样的话,我们将colspan的大小修改为1,并且修改Width的值。

<thid="th1"colspan="1"width=2021159></th> 0:005:x86>t MSHTML!Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable: 67afecf48b15fc5cb368movedx,dwordptr[MSHTML!_tls_index(68b35cfc)]ds:002b:68b35cfc=00000002 0:005:x86>p MSHTML!Layout::Patchable<Layout::SharedBoxReferenceDataMembers>::Readable+0x6: 67afecfa64a12c000000moveax,dwordptrfs:[0000002Ch]fs:0053:0000002c=00000000 0:005:x86>p MSHTML!Layout::Patchable<Layout::SharedBoxReferenceDataMembers>::Readable+0xc: 67afed008b0490moveax,dwordptr[eax+edx*4]ds:002b:008f5dd0=008f0fb8 0:005:x86>ddecx//ecx存放的是Array 098563c8000000000c0c0c04a0a0a0a0a0a0a0a0

可以看到,通过修改Width和colspan,我们成功控制了Array+0x4位置的值,这样,在接下来由于TypeConfusion,会将这个int Array当成是vftable pointer返回,并继续执行。

0:005:x86>p//Layout::Patchable<Layout::PatchableArrayData<Layout::SGridBoxItem>>::Readable函数 MSHTML!Layout::Patchable<Layout::SharedBoxReferenceDataMembers>::Readable+0x1e: 67afed1683c010addeax,10h 0:005:x86>p MSHTML!Layout::Patchable<Layout::SharedBoxReferenceDataMembers>::Readable+0x21: 67afed19c3ret 0:005:x86>p MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d36://返回之后,eax成功变成了0c0c0c14的值 683cfc87833800cmpdwordptr[eax],0ds:002b:0c0c0c14=00000000

可以看到,在返回后,我们可以成功控制这个返回指针了。接下来,我们利用heap spray来喷射堆,从而稳定控制0c0c0c0c位置的值。


【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

CFG???从PoC到半个exploit

到此,我们完成了对漏洞函数返回值的控制,在文章最开始的时候,我们看到这个指针的值中的成员变量,会作为虚函数在后续call调用中引用,在此之前,会有一处CFG check。
0:007:x86>p//eax已经被我们控制,跳转到喷射结束的堆中 MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d45: 683cfc968b18movebx,dwordptr[eax]ds:002b:0c0c0bb0=0c0c0c0c 0:007:x86>p MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d47: 683cfc988b03moveax,dwordptr[ebx]ds:002b:0c0c0c0c=0c0c0c0c 0:007:x86>p MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d49: 683cfc9a8bb8a4010000movedi,dwordptr[eax+1A4h]ds:002b:0c0c0db0=0c0c0c0c 0:007:x86>p MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d4f: 683cfca08bcfmovecx,edi 0:007:x86>p MSHTML!Layout::MultiColumnBoxBuilder::HandleColumnBreakOnColumnSpanningElement+0x2c3d51: 683cfca2ff1534afb568calldwordptr[MSHTML!__guard_check_icall_fptr(68b5af34)]ds:002b:68b5af34=67ac4b50//进入CFGcheck函数 0:007:x86>t MSHTML!CJSProtocol::`vftable'+0xc://这个CFG并无实际作用,直接返回了 67ac4b508bc0moveax,eax 0:007:x86>p MSHTML!CElement::OnGCFilteredForReplacedElem: 67ac4b52c3ret

这个CFG check在Win7中没有实际作用,如上代码跟踪的片段,进入CFG check之后,直接返回了,但是在高版本的Windows中,必须考虑CFG防护的绕过。


【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

但是由于所有地址模块都开启了ASLR,而利用面来看的话,并没有地方可以泄露内存信息,也没有其他好用的利用点,这样的话就不好绕过ASLR和DEP,我在关闭win7 DEP的情况下,完成了利用。


【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit

感谢大家阅读,如果有不当之处,请大家多多交流,谢谢!


【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit
【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit
本文由 安全客 原创发布,如需转载请注明来源及本文地址。
本文地址:http://bobao.360.cn/learning/detail/3626.html

Viewing all articles
Browse latest Browse all 12749

Trending Articles