TippingPoint Digital Vaccine Laboratories
DID YOU KNOW... At the 2007 Black Hat Briefings in Las Vegas, TippingPoint DVLabs had five speakers presenting on a variety of topics.

MindshaRE: WinDbg Introduction

Everyone has their favorite debugger. Sometimes the debugger debate can become almost religious.  All that aside you must be familiar with a debugger. Honestly it's just a matter of preference. WinDbg, OllyDbg/Immunity Debugger, and GDB will all accomplish the basic tasks you'll need in 90% of cases. So today I'm going to just get you started using WinDbg since it's my preference.  A few commands to wet your whistle in the hopes you get motivated to practice until a debugger is second nature.

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

The debugger is used to control a process, that much is obvious. The key to being effective while debugging is to know what your ultimate goal is.  When you clearly understand what task you are trying to achieve you can issue the appropriate commands to get there. Most people lose focus because they are caught up in how to move around inside of their favorite debugger.  The confusion normally occurs when trying to figure out how to do certain tasks, or their debugger UI may not be optimal.

You must have a comfortable UI layout. This allows you to easily see all the information you may need like registers, disassembly, memory, etc. I seem to differ from everyone else.  In my WinDbg UI I only have the command window. Here, look how plain it is.
The norm seems to be several windows open with register views, memory views, disassembly, etc. I purposely do not do this so I can stay focused. I realized when I had multiple windows up that I was not paying attention to what I needed to do. With one window I can keep my mind on track. Through the command line window I can access information, view registers, search memory, and anything else I may need.  It makes me consciously ask "ok I need x information, lets get that".  This has proved successful for myself, but like I stated, its all preference.

Spending a few minutes, or even hours, finding your sweet spot can help you in the long run.  All of the debuggers can save settings, and window layouts for future debugging sessions. Once you get a comfortable layout you can move on.

This post is only focused on WinDbg, but each section has equivalent commands in other debuggers.  If you prefer one of those others try and find the equivalent commands and learn them. I am obviously not going to cover everything WinDbg can do. For that check out the .hlp that comes with the package, or check out the book "Advanced Windows Debugging" if you are looking for something more challenging.

We need to start somewhere, so lets look at a few of the commands to attach and load.
    F6              -   Attach to a process, dialog can be sorted

by pid or name
    Ctrl-E          -   Load an executable
Be mindful when opening an executable, the arguments are in the same window as the browse dialog. On many occasions I go to fast and forget to set my arguments.  When you first attach or start a process you will hit the initial breakpoint.  This BP allows you to set up any additional breakpoints, or other exception handling.

In WinDbg we can control several events we may be interested in.
    sxe             -   Enable an event breakpoint
    sxd             -   Disable an event breakpoint
    sxe ld          -   Enable break on module load
    sxe ct          -   Enable break on thread creation
Setting event breakpoints is very helpful when you have a library loading dynamically, or a specific thread that may be of interest. When doing malware analysis breaking on thread creation and library loading is extremely useful.

On of the most common things we will do is set up breakpoints.  WinDbg provides a myriad of options for breaking into a process, here are a few.
    Ctrl-Brk        -   Break into target process
    bp              -   Set a breakpoint at specified address
    bp <condition>  -   Set a breakpoint at specified address when

it satisfies a condition
    bl              -   List breakpoints
    bd              -   Disable a breakpoint
    bc              -   Clear a breakpoint, or all breakpoints
    be              -   Enable a breakpoint
    ba              -   Break on memory access (r/w/e)
    bu              -   Set a breakpoint on an unresolved address
    bm              -   Set a breakpoint by symbol name, also useful

for setting wild card bps

So we can break anywhere in the process.  Here are some ways to execute after you have hit a breakpoint.
    g               -   Go, or continue the current process
    gu              -   Go up, continue until return
    t               -   Trace, stepping into calls
    p               -   Step, stepping over calls
    ta              -   Trace to address, display all executed

instructions until address
    pa              -   Step to address, skipping all calls
    pc              -   Step to next call
    tc              -   Trace to next call
    ph              -   Step to next branch (call, j**, ret)
Using the execute until commands is always helpful when you want to skip code.  For instance when you step into a function and want to quickly move to the return. Having multiple commands to jump around a process helps us stay focused cutting away any cruft that may not be of interest.

Lastly lets look at inspecting and changing data. The most common of these is your register state.  If your WinDbg is set up like mine the registers will be printed at each step, or breakpoint. They are ordered like so.
(8a8.8f4): Break instruction exception - code 80000003 (first chance)
eax=7ffdd000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c90120e esp=0092ffcc ebp=0092fff4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
7c90120e cc              int     3
You can easily modify registers using the same command to list them.
    r               -   Display registers and EIP disassembly
    r eax=0x10      -   Write value into specified register
The ordered listing of registers in WinDbg may appear convoluted but you quickly get accustomed. As you can see we also see the current disassembly at EIP.  Here are a few commands to do this on any address.
    u               -   Unassemble current EIP or specified

address
    uf              -   Unassemble function, displays all

instructions in function
And finally we can dump and edit memory locations with ease.
    db              -   Dump data at address in bytes
    dd              -   Dump data at address in dwords
    dc              -   Dump data at address in dwords and ascii
    da              -   Dump data at address in ascii
    s               -   Search memory for specified data type
    eb              -   Edit address as byte
    ed              -   Edit address as dword
Well there you go, a few (there are hundreds) of WinDbg commands to get you going.  Hopefully you can learn these to aide in your next debugging adventure.  One of the best things about WinDbg is its extensive command support.  Take a look at the .hlp and various other resources on the net.

-Cody
Tags:
Published On: 2008-09-25 14:20:51

Comments post a comment

  1. Pedram Amini commented on 2008-09-25 @ 14:21

    OllyDbg rules...

  2. vulto commented on 2008-09-27 @ 12:21

    Nice post mate.


Trackback