WinDBG Tutorial - Part 1

Items covered

 

- Attaching to process

- Inspecting local variables (dv, ??)

- Inspecting last error (.lastevent)

- Evaluating parameters (x)

- Setting value (e)

Code used

 

For this introductory test, we will work with the following test program (Win32 C++ console project):

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])

{

      printf("Enter two numbers: ");

      int a, b;

      scanf("%d%d", &a,&b);

      int rez;

      rez = a / b;

      printf("The division is: %d", rez);

     

      return 0;

}

What the program does is obvious: it reads two integer variables from the command line and calculates the result of their division. The potential error is again obvious: if the latter variable is 0, we’ll get a division by zero exception.

Debugging

Let’s get to work:

Compile and run the program from console:

D:\home\…\Emptyapp\Debug>Emptyapp.exe

Set the symbol path in WinDBG to the Debug folder of the C++ program (where EmptyApp.exe and PDB files are located).

Open WinDBG and attach to the process named “EmptyApp”

For the moment, we will choose Go, as no exception as occurred yet:

0:001> g

(The message in WinDBG will be “Debugee is running”)

Let’s now input two values: a = 6, b = 0

When you press ENTER, winDBG will break because it receives a First-hand exception:

(1e38.1b00): Integer divide-by-zero - code c0000094 (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

This exception may be expected and handled (had we inserted a try/catch block in the C++ program), but it is not. Let’s go further and receive the second chance exception:

0:000> g

(1e38.1b00): Integer divide-by-zero - code c0000094 (!!! second chance !!!)

Assuming we didn’t know what happened, let’s find out the call stack:

0:000> k

ChildEBP RetAddr

0022f948 00fa1a28 Emptyapp!wmain+0x79 [d:\home\allinoner\emptyapp\emptyapp\emptyapp.cpp @ 14]

0022f998 00fa186f Emptyapp!__tmainCRTStartup+0x1a8 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 579]

0022f9a0 763d10dc Emptyapp!wmainCRTStartup+0xf [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 399]

0022f9ac 77301e9e kernel32!BaseThreadInitThunk+0xe

0022f9ec 77301e71 ntdll!__RtlUserThreadStart+0x70

0022fa04 00000000 ntdll!_RtlUserThreadStart+0x1b

The error, therefore, originates at line 14 in the source emptyapp.cpp

Since we do have the source for this file, let’s see what line 14 reads:

                rez = a / b;

Hmm, we get a division by zero and the line of code contains a division…

Let’s dump the local variables:

0:000> dv

           argc = 1

           argv = 0x00511310

              b = 0

            rez = -858993460

              a = 6

OK, question was answered, we want to divide a = 6 by b = 0.

Just out of curiosity: what is argv?

0:000> ?? argv

wchar_t ** 0x00511310

Since argc is 1, let’s see the value of the first argument:

0:000> ?? argv[0]

wchar_t * 0x00511318

 "Emptyapp.exe"

OK, let’s go further: let’s modify variable b so that no division by zero is thrown:

Firstly, get its address:

0:000> x b

0022f934 b = 0

Secondly, set value of b to 3, for instance:

0:000> e 22f934 3

Inspecting all local variables again:

0:000> dv

           argc = 1

           argv = 0x00511310

              b = 3

            rez = -858993460

              a = 6

This is it. Let’s let the program finish:

0:000> g

eax=5f24dff0 ebx=00000000 ecx=5f1812bc edx=5f1812bc esi=77377380 edi=77377340

eip=772e8244 esp=0022f8b0 ebp=0022f8cc 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!KiFastSystemCallRet:

772e8244 c3 ret

The command prompt reads:

Enter two numbers: 6 0

The division is: 2

And finally, to make sure program has exited:

0:000> .lastevent

Last event: 1e38.1b00: Exit process 0:1e38, code 0

  debugger time: Sun Jul 12 21:08:08.080 2009 (GMT+3)