TippingPoint Digital Vaccine Laboratories

MindshaRE: Hit Tracing in WinDbg


MindshaRE has focused exclusively on static analysis so far.  That is fine and all, but often we need a little dynamic help.  This can be due to virtual function calls, dynamic library calls, or just to speed things up.  So today we will add a little WinDbg to our diet and talk about hit tracing. I will also show a little script that lets us trace a process and import that trace into IDA.

MindshaRE is our weekly look at some simple reverse engineering tips and tricks.  The goal is to keep the topics short and discuss every day aspects of reversing.  You can view previous entries here by going through our blog history.

I will admit, I use debuggers when I can.  I am not ashamed to say that.  It boils down to speed.  With a little help from the debugger I can save hours of time while reversing.  One of the things I like to use the debugger for is code flow.  Code flow is obviously the path a process takes when arbitrary input is involved.  This can be UI input, network input, file IO, or file processing.  By using a debugger we can quickly set a breakpoint, trace it, and determine what modifications are made to data, or what kind of logic is involved in its branching.

So what we would like to do is marry the hit tracing from WinDbg to our idb in IDA.  This process will entail stepping through a function in WinDbg that I am interested in.  Once I am done I want to "import" that into IDA so I can visually see where I have gone.  I want to point out that hit tracing, also known as process stalking, is not a new concept and is very effective at helping understand the flow of something while reverse engineering.

First you have to find your starting point.  In this demonstration I will use the venerable calc.exe.  Since I have symbols, it is easy to find a place of interest.  Looking at the function DoOperation proves to be a great place to set a software breakpoint:
0:003> bp 01005a7a
0:003> g
And now multiplying 10 * 10 in the UI triggers that bp.
Breakpoint 0 hit
eax=00000010 ebx=00000000 ecx=00000000 edx=00000014 esi=000ecf10 edi=000aa2b0
eip=01005a7a esp=0007fa04 ebp=0007faf8 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!DoOperation:
01005a7a b816290101      mov     eax,offset calc!terminate+0x2e (01012916)
Our goal is to figure out what path 10 * 10 will take in this function.  We also want to record everything that happens.  Looking at the function in IDA we can see all branches lead to a single basic block responsible for the functions return.  This is where we want to stop.  Lets open our log file.
0:000> .logopen "c:\calc_dooperation.log"
Opened log file 'c:\calc_dooperation.log'

Then we need to trace to our return.

0:000> u 01005C23 L1
calc!DoOperation+0x1a9:
01005c23 c20c00          ret     0Ch
0:000> pa 01005C23
This will execute, skipping calls, until the address we specified.  So we can close our log file and go back to IDA.
0:000> .logclose
Closing open log file c:\calc_dooperation.log
I do hit tracing in IDA two ways.  Coloring, and commenting.  When I want to see where the process went, I will color each line that was executed.  When I want to see what values certain registers contained I will add that value to the comment of that line.  This allows me to easily see where I went via the colors, and to also see more information about execution (possibly what a cmp instruction might have been looking at).  The easiest way to get this information is from the WinDbg log file we created.

The log file is a snapshot of every instruction executed during our debugging session.  This includes register values, and the result of any branch that was taken.  With this we can parse out the needed info for IDA.  I have written an IDC to do exactly that.  The IDC script will ask the user for a log file.  It will then parse it and add any color information to an executed instruction.  If you chose to add comments it will give you the register value of any deferenced data, or local variable stores.  This can be fine tuned to your needs very easily.  Here you go:

    windbg_log_to_idb.idc

To use it, we go to File->IDC File... and select the script.  It will then prompt you for the log file you saved.  Once you select that it will then ask if you want to color each line, and if you want to add comments.  For this example I will simply color each line.  The script will run and you will see which instructions were hit.  Here is an example of DoOperation when multiplication occurs.
So we see that the process branches to the function mulrat and then returns.  Lets see what happens on a left shift operation.
Nice.

If we add comments we can see why it chose this route.
.text:01005A87                 mov     eax, [ebp+arg_0] ; 00000059
...
.text:01005A8E                 cmp     eax, 5Ah
...
.text:01005A9B                 jg      loc_1005D7C     ; br=0
.text:01005AA1                 jz      loc_1005F05     ; br=0
.text:01005AA7                 sub     eax, 7
.text:01005AAA                 jz      loc_1005C40     ; br=0
.text:01005AB0                 sub     eax, 4Fh
.text:01005AB3                 jz      loc_1005C33     ; br=0
.text:01005AB9                 dec     eax
.text:01005ABA                 jz      loc_1005C26     ; br=0
.text:01005AC0                 dec     eax
.text:01005AC1                 jz      loc_1005C0A     ; br=0
.text:01005AC7                 dec     eax
.text:01005AC8                 jnz     loc_1006049     ; br=0
...
As you can see the script labeled the contents of eax and we can see it trace through to the appropriate basic block.  If you remember in our log file we skipped calls (pa).  Changing this to step into a call (ta) will give us even more data.  Keep in mind that it may be a while before execution stops due to any functions containing loops, library calls, or windows handling.

Well that's our little hit tracer for WinDbg, and I didn't even go into a religious discussion on debuggers!  I hope you can see the benefit of combining live analysis with static analysis, because in my opinion using them together, when you can, is the perfect marriage.  I hope you enjoyed it.

-Cody
Tags:
Published On: 2008-07-17 14:32:39

Comments post a comment

  1. Nate McFeters commented on 2008-07-18 @ 01:41

    Cody,

    Thanks for this, this was hugely informative. As someone who's much more comfortable with a debugger and guess work than with RE, this provides a ton of help.

    -Nate

  2. Cody Pierce commented on 2008-07-18 @ 11:43

    @Nate:

    Im glad you liked it!


Trackback