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> gAnd 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 01005C23This 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.logI 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


