Software Vulnerability Exploitation Blog

Saturday, July 01, 2006

Heap Spraying: Internet Exploiter

SkyLined's Internet Exploiter is the first public exploit that use heap spraying technique, may be :). It was written to exploit the vulnerability in Microsoft Internet Explorer - MS04-040. I interest this exploit because it is the original one in heap spraying.

I start learn his exploit by copy his HTML tag that trigger the overflow. This is the code:

iframe src="file://BBBBBBBBBB....." name="CCCCCCCCCC....."

IE crashs when I browse this page. Umm, it seems ok and SkyLined's document said that this should set eax to 0x0d0d0d0d. I attach IE to WinDbg and browse the malicious HTML page again.


IE crashs, but in the different manner. Eax is written by value 0x000d000d, not 0x0d0d0d0d, and eip stops at address 0x769f682f - the instruction:

mov eax, [eax + 0x34]

Reading at address 0x000d000d + 0x34 = 0x000d0041 causes the access violation, I try to figure out why eax is set to 0x000d000d. I append the end of buffer by 2 bytes of 0x0d but the result is still the same.

I'm stuck 2 hours about this issue. My HTML code and SkyLined's code are the same. Umm... may be there is something in his file format. I open Internet Exploiter with hex editor xvi32


Hey... this is not simple ASCII file. It starts with 2 bytes FFFE and every character use 16 bits - 2 bytes. In this case every character is followed by 0x00 byte. This file format looks like UTF-16 little endian. I try to confirm my assumption by create a Unicode file by Wordpad and open it with xvi32. The result shows me that they are same !! Ahhhh why I don't think that this file is not ASCII format - -". I had opened this file by Vi (Windows version) and it show me that file is unreadable.

I start create HTML file in UTF-16 format and exploit IE again. Ahhh, why the result's still the old one - eax is set to 0x000d000d ? I open Internet Exploiter by xvi32 again and locate the position the 0x0d bytes are in. I found that SkyLine's code 0x0d bytes are positioned like this:

..... 0x0d 0x0d 0x0d 0x0d .....

while my 0x0d bytes are arranged like this:

..... 0x0d 0x00 0x0d 0x00 0x0d 0x00 0x0d 0x00.....

Oh he embedded 4 0x0d bytes in 2 Unicode characters !! This is the important trick to control eax in his exploit. After solve the simple but tricky problem, I get this result from WinDbg:


Now eax is set to 0x0d0d0d0d and reading at address 0x0d0d0d0d + 0x34 = 0x0d0d0d41 causes access violation. I think you've already known the method to made the address 0x0d0d0d41 to be valid memory address. Yez, Heap Spraying :)

When I inject 400 heaps in to the memory, I found this:


Ah.. our payload is executed !!! How could it happen ? SkyLined said in his document that if we can control eax, then we can control ecx. Because the instruction

CALL NEAR DWORD PTR [ECX]

is called after we have set ecx to 0x0d0d0d0d, so the flow of execution will transfer to the address near 0x0d0d0d0d - our payload.

I start to follow the document by set breakpoint at 0x769f682f - the address that eax is set to 0x0d0d0d0d. When WinDbg break at 0x769f682f at the first time, eax is not set to 0x0d0d0d0d, so I press 'g'' until WinDbg break at 0x769f682f and eax is set to 0x0d0d0d0d (I think may be WinDbg has the feature to let we set the breakpoint condition, but I don't know the command - -"). When eax is set to 0x0d0d0d0d, ecx is set to 0x769c62ec. I continue run WinDbg step by step instruction until I found this:


Something is strange. After eax is set to 0x0d0d0d0d, it is set to other value in the instruction "pop eax" at address 0x769f6850. Ecx has never been set to 0x0d0d0d until our payload is executed. I think may be this instruction is the key:

call dword ptr [ecx + 0x14] {SHDOCVW!CIEFrameAuto::GetParentFrame (769f6d69)}

This instruction, at address 0x769f6d2b, is called and the flow of program transfers to our payload. May be WinDbg doesn't show details about this instruction, so I set another breakpoint at [ecx + 0x14] = 0x769f6d69 and view the result. Again, the flow of execution transfers to our payload without setting eax and ecx to 0x0d0d0d0d - -". I found that before the flow of execution transfers to our payload, there is a call instruction:

call SHDOCVW!CIEFrameAuto::_GetParentFramePrivate (769f6d95)

I repeat the same step and I found the following instructions:

call SHDOCVW!CIEFrameAuto::_GetOleObject (769f6e23)
call dword ptr [eax + 0x18] {SHDOCVW!CwebBrowserSB::GetOleObject (769f6d46)

In SHDOCVW!CwebBrowserSB::GetOleObject, I let the debugger run instruction by instruction, this is the result:

.....
eax=001c612c ecx=
001c612c

769f6d4a mov eax, [eax + 0x1400]
eax=0d0d0d0d ecx=
001c612c

769f6d50 test eax, eax
eax=
0d0d0d0d ecx=001c612c

769f6d52 je SHDOCVW!CwebBrowserSB::GetOleObject + 0xe (76a07b8b)
eax=
0d0d0d0d ecx=001c612c

769f6d58 push dword ptr[esp + 0x8]
eax=
0d0d0d0d ecx=001c612c

769f6d5c mov ecx, [eax]
eax=
0d0d0d0d ecx=0d0d0d0d

769f6d5e push 0x769c6598
eax=
0d0d0d0d ecx=0d0d0d0d

769f6d63 push eax
eax=
0d0d0d0d ecx=0d0d0d0d

769f6d64 call dword ptr [ecx]
.....

Eax is set to 0x0d0d0d0d at the instruction address 0x769f6d4a (mov eax, [eax + 0x1400]). Ecx is set to 0x0d0d0d0d at the instruction address 0x769f6d5c (mov ecx, [eax]). Because ecx is set to 0x0d0d0d0d, the instruction address 0x769f6d64:

call dword ptr [ecx]

is equivalent to

call dword ptr [0x0d0d0d0d]

And because address 0x0d0d0d0d contains value 0x0d0d0d0d, then

call dword ptr [0x0d0d0d0d]

is same as

call 0x0d0d0d0d


At address 0x0d0d0d0d, our shellcode is there. When the instruction "call dword ptr [ecx]" is launched, we win the game :)

P.S. - Tested onWindows XP Professional Service Pack 0 and Internet Explorer 6.0

2 Comments:

Post a Comment

<< Home