<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2014-1773_Internet_Explorer%E5%85%A7%E5%AD%98%E6%90%8D%E5%A3%9E%E6%BC%8F%E6%B4%9E</id>
	<title>CVE-2014-1773 Internet Explorer內存損壞漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2014-1773_Internet_Explorer%E5%85%A7%E5%AD%98%E6%90%8D%E5%A3%9E%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2014-1773_Internet_Explorer%E5%85%A7%E5%AD%98%E6%90%8D%E5%A3%9E%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-16T10:38:06Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=CVE-2014-1773_Internet_Explorer%E5%85%A7%E5%AD%98%E6%90%8D%E5%A3%9E%E6%BC%8F%E6%B4%9E&amp;diff=1072&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==INFO== &lt;pre&gt; CClipStack::PushClipRect() Invalid Array Indexing  First, starting with the callstack from the crash with pageheap enabled:  ChildEBP RetAddr  0919aac8 6b58459f...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2014-1773_Internet_Explorer%E5%85%A7%E5%AD%98%E6%90%8D%E5%A3%9E%E6%BC%8F%E6%B4%9E&amp;diff=1072&amp;oldid=prev"/>
		<updated>2021-04-07T03:20:38Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==INFO== &amp;lt;pre&amp;gt; CClipStack::PushClipRect() Invalid Array Indexing  First, starting with the callstack from the crash with pageheap enabled:  ChildEBP RetAddr  0919aac8 6b58459f...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==INFO==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CClipStack::PushClipRect() Invalid Array Indexing&lt;br /&gt;
&lt;br /&gt;
First, starting with the callstack from the crash with pageheap enabled:&lt;br /&gt;
&lt;br /&gt;
ChildEBP RetAddr &lt;br /&gt;
0919aac8 6b58459f MSHTML!CWorldTransform::IsAxisAligned&lt;br /&gt;
0919ab40 6ba228e9 MSHTML!CDispSurface::CClipStack::PushClipRect+0x1a2&lt;br /&gt;
0919aba4 6be25b58 MSHTML!CDispSurface::PushClipRectInternal+0x2f&lt;br /&gt;
0919abc0 6bf1118f MSHTML!CDispSurface::PushClipRectUser+0x26&lt;br /&gt;
0919ac24 6bf1157e MSHTML!CCanvasCompositor::ClearRightAndBelowRenderedRegion+0xcd&lt;br /&gt;
0919acd8 6b28108c MSHTML!CCanvasCompositor::ExecuteCompositionEffects+0x34d&lt;br /&gt;
0919ace0 6b2802f4 MSHTML!CCanvasCompositor::Flush+0x3d&lt;br /&gt;
0919ace8 6bf0c867 MSHTML!CCanvasCompositor::~CCanvasCompositor+0x10&lt;br /&gt;
0919ae28 6bf0b668 MSHTML!CCanvasRenderingContext2D::StrokeRectInternal+0x1b3&lt;br /&gt;
0919ae70 6bf0e032 MSHTML!CCanvasRenderingContext2D::ExecuteStrokeRect+0x1c5&lt;br /&gt;
0919aebc 6bd74b6f MSHTML!CCanvasRenderingContext2D::Var_strokeRect+0xac&lt;br /&gt;
0919aee0 6ae7056e MSHTML!CFastDOM::CCanvasRenderingContext2D::Trampoline_strokeRect+0x3b&lt;br /&gt;
0919af50 6ae6cdda jscript9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x165&lt;br /&gt;
0919b328 6ae6dc86 jscript9!Js::InterpreterStackFrame::Process+0x1e74&lt;br /&gt;
0919b474 09560fd9 jscript9!Js::InterpreterStackFrame::InterpreterThunk&amp;lt;1&amp;gt;+0x1e7&lt;br /&gt;
&lt;br /&gt;
If we step back one function, this guy sets the object pointer that is used by the crash:&lt;br /&gt;
&lt;br /&gt;
.text:63CDE575 ; public: long __thiscall CDispSurface::CClipStack::PushClipRect(class CRectF const &amp;amp;, class CWorldTransform const *, bool, bool)&lt;br /&gt;
.text:63CDE575 mov edi, edi&lt;br /&gt;
.text:63CDE577 push ebp&lt;br /&gt;
.text:63CDE578 mov ebp, esp&lt;br /&gt;
.text:63CDE57A sub esp, 64h&lt;br /&gt;
.text:63CDE57D and [ebp+var_8], 0&lt;br /&gt;
.text:63CDE581 mov edx, ecx&lt;br /&gt;
.text:63CDE583 push ebx&lt;br /&gt;
.text:63CDE584 push esi&lt;br /&gt;
.text:63CDE585 mov esi, [ebp+arg_0]&lt;br /&gt;
.text:63CDE588 push edi&lt;br /&gt;
.text:63CDE589 lea edi, [ebp+var_28]&lt;br /&gt;
.text:63CDE58C mov [ebp+var_4], edx&lt;br /&gt;
.text:63CDE58F movsd&lt;br /&gt;
.text:63CDE590 movsd&lt;br /&gt;
.text:63CDE591 movsd&lt;br /&gt;
.text:63CDE592 movsd&lt;br /&gt;
.text:63CDE593 mov esi, [ebp+arg_4]&lt;br /&gt;
.text:63CDE596 test esi, esi&lt;br /&gt;
.text:63CDE598 jnz loc_63B1A8DF&lt;br /&gt;
.text:63CDE59E&lt;br /&gt;
.text:63CDE59E loc_63CDE59E:&lt;br /&gt;
.text:63CDE59E imul ecx, [edx+4], 18h&lt;br /&gt;
.text:63CDE5A2 xor bl, bl&lt;br /&gt;
.text:63CDE5A4 mov eax, [edx+8] &lt;br /&gt;
.text:63CDE5A7 add eax, 0FFFFFFE8h&lt;br /&gt;
.text:63CDE5AA add eax, ecx&lt;br /&gt;
.text:63CDE5AC mov [ebp+arg_0], eax&lt;br /&gt;
.text:63CDE5AF mov edi, [eax+14h]&lt;br /&gt;
&lt;br /&gt;
The outer object, CDispSurface, contains a CClipStack object inside of it. The CClipStack&lt;br /&gt;
object starts at offset 0x64 into the CDispSurface object. CClipStack is basically just&lt;br /&gt;
a subclass of CImplAry it seems, which is a generic array class that Internet Explorer&lt;br /&gt;
uses all over the place for arrays. In the above function, CDispSurface::CClipStack::PushClipRect,&lt;br /&gt;
the 'this' pointer is the subobject CClipStack inside of the outer CDispSurface.&lt;br /&gt;
&lt;br /&gt;
The CClipStack object looks something liek this:&lt;br /&gt;
&lt;br /&gt;
DWORD dwMaxElems;&lt;br /&gt;
DWORD dwCurElems;&lt;br /&gt;
VOID *pElems;&lt;br /&gt;
&lt;br /&gt;
So, looking at the above code, you can guess what is going on. What the above code is doing is&lt;br /&gt;
extracting the last element from the CClipStack array. Each element in the array is 0x18 bytes in size,&lt;br /&gt;
hence:&lt;br /&gt;
&lt;br /&gt;
imul ecx, [edx+4], 18h ; dwCurElems * 0x18&lt;br /&gt;
mov eax, [edx+8] ;pElems&lt;br /&gt;
&lt;br /&gt;
But then you can see the following:&lt;br /&gt;
&lt;br /&gt;
add eax, 0FFFFFFE8h ; subtract 0x18 from pElems&lt;br /&gt;
add eax, ecx ; pElems += (dwCurElems * 0x18)&lt;br /&gt;
&lt;br /&gt;
However, if the array is empty, dwCurElems * 0x18 '==' 0, and so pElems&lt;br /&gt;
will actually point BEHIND the start of the array, into the adjacent heap chunk&lt;br /&gt;
below it. The array itself contains objects of the type CWorldTransform, which you can&lt;br /&gt;
infer from the code that crashes shortly after extract the object from the array. ecx&lt;br /&gt;
is the object pointer taken from the 'mov edi, [eax+14h]' operation:&lt;br /&gt;
&lt;br /&gt;
.text:63B1A940 ; public: bool __thiscall CWorldTransform::IsAxisAligned(void)const&lt;br /&gt;
&lt;br /&gt;
.text:63B1A940 test dword ptr [ecx+8], 80000000h ;ecx == BAD&lt;br /&gt;
&lt;br /&gt;
So, where is the array allocated:&lt;br /&gt;
&lt;br /&gt;
MSHTML!CDispSurface::CClipStack::PushClipRect+0x32:&lt;br /&gt;
6b97e5a7 83c0e8 add eax,0FFFFFFE8h&lt;br /&gt;
0:013&amp;gt; !heap -p -a eax&lt;br /&gt;
address 0c4b0fa0 found in&lt;br /&gt;
_DPH_HEAP_ROOT @ 211000&lt;br /&gt;
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)&lt;br /&gt;
c45123c: c4b0fa0 60 - c4b0000 2000&lt;br /&gt;
739f8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229&lt;br /&gt;
77a95e7a ntdll!RtlDebugAllocateHeap+0x00000030&lt;br /&gt;
77a5a3ba ntdll!RtlpAllocateHeap+0x000000c4&lt;br /&gt;
77a25a70 ntdll!RtlAllocateHeap+0x0000023a&lt;br /&gt;
6b55c592 MSHTML!CImplAry::EnsureSizeWorker+0x00000061&lt;br /&gt;
6b584513 MSHTML!CDispSurface::BeginDraw+0x00000122&lt;br /&gt;
6b2847a0 MSHTML!CCanvasRenderingContext2D::BeginDraw+0x00000041&lt;br /&gt;
6b286155 MSHTML!CCanvasContextBase::OpenBitmapRenderTarget+0x00000014&lt;br /&gt;
6b283b77 MSHTML!CCanvasCompositor::Initialize+0x0000102f&lt;br /&gt;
6b285cf7 MSHTML!CCanvasRenderingContext2D::StrokeGeometry+0x00000131&lt;br /&gt;
6b285090 MSHTML!CCanvasRenderingContext2D::ExecuteStroke+0x000002c4&lt;br /&gt;
6b284dae MSHTML!CFastDOM::CCanvasRenderingContext2D::Trampoline_stroke+0x00000035&lt;br /&gt;
6ae7056e jscript9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x00000165&lt;br /&gt;
6ae6cdda jscript9!Js::InterpreterStackFrame::Process+0x00001e74&lt;br /&gt;
6ae6dc86 jscript9!Js::InterpreterStackFrame::InterpreterThunk&amp;lt;1&amp;gt;+0x000001e7&lt;br /&gt;
&lt;br /&gt;
It is in the 0x60 LFH bin. We can control the chunk behind the array by doing some heap crafting.&lt;br /&gt;
But the bad part of that code above is that the calculation for extracting the object used is&lt;br /&gt;
this:&lt;br /&gt;
&lt;br /&gt;
(BYTE *)pArrayStart - 0x18 + 0x14 =&amp;gt; (BYTE *)pArrayStart - 0x4&lt;br /&gt;
&lt;br /&gt;
That results in using the flags/index field of the LFH chunk header as an object pointer.&lt;br /&gt;
That's not really good as the bytes in that field are not super controllable (I think).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For seeing how to possibly control that second dword of the LFH header:&lt;br /&gt;
&lt;br /&gt;
http://illmatics.com/Understanding_the_LFH.pdf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Collaboration with Sean Larsson&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>