Saturday, July 30, 2011

Integrating WinDbg and IDA for Improved Code Flow Analysis

IDA is hands down the best tool for static analysis. Its debugger on the other hand, when compared to the power of WinDbg is certainly lacking, IMHO. As such, I find myself wasting too much time switching between windows and manually highlighting and commenting instructions in IDA as I trace through them in WinDbg. Fortunately, the power of IDApython can be unleashed to reduce this tedium.

I was reading an older TippingPoint MindshaRE article from Cody Pierce entitled “Hit Tracing in WinDbg[1]” and was inspired by his ideas to implement my own IDApython script to better integrate WinDbg with IDA. While, I may be recreating many of his efforts, my primary intent was to get better at scripting in IDApython while improving upon my static/dynamic analysis workflow.

The purpose of my script is to parse WinDbg log files for module base addresses, instruction addresses, references to register values, and pointer dereferences. Then, for every instruction you hit in your debug session, the corresponding instructions will be colored and commented accordingly and in a module base address-agnostic fashion.

To get started, your WinDbg log file will need to display the following:

• Disassembly of current instruction
• Effective address for current instruction
• Register state
• Listing of loaded modules (optional, but highly recommended)

The first three items should be enabled by default but can be re-enabled with the ‘.prompt_allow’ command. Your output should look like the following:

eax=003762f8 ebx=006cc278 ecx=00000004 edx=00000000 esi=006cc420 edi=00000001
eip=00491469 esp=0020e348 ebp=0020e388 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
calc!CCalcEngine::DoOperation+0x6be:
00491469 e8074efeff      call    calc!divrat (00476275)

The reason it is ideal to include module base addresses in your log file is so that effective addresses can be calculated as offsets then added to the base address of the module in IDA. This helps because the module base address in WinDbg is often different than the base address in IDA. Also, this avoids having to modify the dumpfile to match IDA or rebase the addresses in IDA – both, a pain and unnecessary. My script parses the output of ‘lmp’ in WinDbg which outputs the base addresses of loaded modules minus symbol information.

To continue riding Cody’s coattails, I’ll be analyzing the DoOperation function (0x00495001-0x00495051) in calc.exe as he did. I determined the beginning and ending addresses of the function with the following commands:

0:000> X calc!*DoOperation*
00495001 calc!CCalcEngine::DoOperation =
0:000> BP 00495001
0:000> g

Entering in 1000 / 4 in calc

Breakpoint 0 hit
eax=00439220 ebx=0069c420 ecx=0069c278 edx=00000000 esi=0069c278 edi=00000000
eip=00495001 esp=0032e95c ebp=0032ea4c iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
calc!CCalcEngine::DoOperation:
00495001 6a1c push 1Ch

Step through function until return instruction

0:000> PT
eax=00000000 ebx=0069c420 ecx=00495051 edx=00445310 esi=0069c278 edi=00000000
eip=00495051 esp=0032e95c ebp=0032ea4c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
calc!CCalcEngine::DoOperation+0xfa:
00495051 c20c00 ret 0Ch
0:000> g
0:004> .logopen "calc.log"

The following dump is the result of the operation 1000/4 in the function without stepping into calls (using the PA command):


Obviously, manually annotating all of this information in IDA is the work of an unpaid intern. I, on the other hand, value my time and wrote the following script to parse out the log file and import it into IDA:


The script has the following features:

• Prompts user for WinDbg log file to load
• Prompts user for the instruction highlight color (real men use pink) ;P
• Parses the output of the ‘lmp’ command and calculates instruction offsets from the module base address
• Creates comments for the values of referenced registers
• Creates comments for the value of pointer dereferences

Here is what the graph of DoOperation looks like before 1000 / 4 is performed:


Here is what the graph of DoOperation looks like after 1000 / 4 is performed:


You can see the highlighted instructions and the values of any referenced registers and pointers.


Hopefully, by now you can see the power of IDApython in improving your analysis workflow. If you use this script, I welcome your feedback!

References:

1. Cody Pierce, “MindshaRE: Hit Tracing in WinDbg,” July 17, 2008, http://dvlabs.tippingpoint.com/blog/2008/07/17/mindshare-hit-tracing-in-windbg

Wednesday, July 20, 2011

Cool kids pop a programmer's calc in their demos

Over time, I've heard several well-respected security professionals mention that you're not really cool unless you can pop a scientific/programmer's calculator when demoing your exploits. I mean, what right does a standard, run of the mill calculator have showing its face to a crowd of enthralled conference attendees watching the latest version of Windows 7 get totally pwned? And how many self-respecting security folks use a standard calc more than the programmer's calc? So rather than waste the time of the people who thought this would be cool, I thought it would be better to waste my own time to complete this silly challenge. So without further ado, prepare to do some hexadecimal math. I'd like to mention that Jacob Appelbaum (@ioerror) and Aaron Portnoy (@aaronportnoy) inspired me to write this. ;D

To start, I used procmon to observe how calc was interacting with the OS when switching from standard to programmer's mode.


It turns out that it modifies the following registry key: HKCU\Software\Microsoft\Calc\layout and changes the REG_DWORD value to 0x00000002 when switching to a programmer's calc.

One of the nice features of procmon is that it lets you view the stack trace of each entry. Here's the stack trace for the call to RegSetValue:


So, to get my shellcode to work, I'll likely need to understand how calc.exe modifies the registry. After loading calc.exe into IDA, I quickly determined that it calls the folowing functions, which procmon graciously gave me the offsets to:

  • RegCreateKeyExW
  • RegSetValueExW
  • RegCloseKey

IDA in conjunction with my debugger conveniently gave me all the parameters I needed to pass to these functions. For more information on the function parameters, refer to MSDN documentation.

The only problem is that the shellcode needs to first determine the addresses to these functions, which turns out to be the bulk of my shellcode. I should be careful when saying 'my' shellcode considering I modified SkyLined's awesome w32-exec-calc-shellcode[1] which I believe was loosely based upon Matt Miller's paper - "Understanding Windows Shellcode[2]."

It's worth noting that if your shellcode is running in the stack, careful considerations must be made when writing your assembly. Specifically, the shellcode instructions and function parameters share the same space. Because you are executing code from the stack, you have to be careful not to clobber your instructions. So what I did was move esp (which would point to the first instruction) into ebp [MOV EBP, ESP] and essentially create my own stack frame above the code.

Here is the shellcode with relevant comments for your convenience. Note that this will only work on 32-bit Windows and it has only been tested on Windows 7 SP1 :

w32-programmer-calc hex
w32-programmer-calc assembly

Areas of improvement:
  • Remove all nulls. This would be relatively easy but I am lazy. Perhaps in a future version.
  • Only one byte of this needs to be modified to pop a scientific calc on Vista. This can be left as an exercise for the readers.
  • This could scan for the OS version and determine dynamically whether to pop a scientific (pre-Windows 7) vs programmer's calc. Do you really want to be popping calcs on anything besides Windows 7 though? ;D
  • My assembly is likely total crap. But it works. I'm sure someone out there could trim a couple dozen bytes off it but I'll leave that as a challenge for the assembly ninjas out there.

Please comment, try it out on your 32-bit Windows 7 machine for yourself, and let me know if it doesn't work and I might make an effort to fix it. Enjoy!

References:

1. Berend-Jan "SkyLined" Wever, w32-exec-calc-shellcode, http://code.google.com/p/w32-exec-calc-shellcode/

2. Matt Miller, "Understanding Windows Shellcode", December 6, 2003, http://www.hick.org/code/skape/papers/win32-shellcode.pdf