Debugging the Windows kernel with WinDbg

Although debugging userspace applications in Windows is relatively easy as there are many tools (OllyDbg, Immunity Debugger…) for this purpose, kernel debugging is not such an easy task, in part due to the fact of that the methodology is not as straightforward as in ring3.

 This type of debugging is especially useful when examining Windows internal structures and/or stepping through instructions that are not otherwise available when looking from ring3. By debugging the Windows kernel, you will also get a clearer idea of how windows internals work.

 When speaking about kernel debugging we will generally be speaking about remote kernel debugging, as local debugging in ring0 is only reliable in a few situations when performing heavy analysis and modifications of the running processes is not needed. This document does will not cover local debugging on a single machine (you can get info about that here).

Remote kernel debugging is useful when:

  • Setting breakpoints – Set a breakpoint and the system freezes
  • Analyzing the stack and registers
  • Modifying registers at runtime
  • Analyzing crashes – How would you debug locally a crashed computer?
  • …and a long etcetera

Prerequisites

  • Basic debugging knowledge
  • WinDbg – Download it from Microsoft’s webpage
  • Two Windows instances – Physical or virtual machines

So…Remote debugging…how?

First of all, some glossary:

  • Debugee – Machine to be debugged.
  • Debugger – Machine that runs the the debugger (WinDbg)

As the word remote implies, two machines will be involved in the process, and they will have to be connected somehow. There are quite a few methods for connecting them, but the most common one is to use a serial port to connect the debugee and the debugger. In this article, we will be using this method.

The machines involved in the debugging session can be physical or virtual machines, this is not important as long as both can communicate with each other via a null-modem cable.

 OK. Enough small talk. Let’s get our hands dirty with WinDbg.

Practical windows debugging with WinDbg

Configure the debugee

First of all, we need to make the debugee ready to be debugged. This implies enabling debug mode for the debugee and specifying the port and the speed to be used in the connection. You can do that by modifying the boot.ini file. The following is a sample boot.ini file before enabling debug mode.

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows XP Professional" /fastdetect

And this is what the boot.ini file of the debugee should look like:

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]                                  multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows XP Professional" /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows XP Professional" /fastdetect /DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200

By modifying the file, we have enabled remote kernel debugging in port COM1 (you may want to use a different one) and specified a connection speed of 115200 bauds.

Connect the two machines

If you are debugging two physical machines, this is as easy as connecting the two instances with a null-modem cable, however, if you want to debug a VM, things get a little harder.

Under VirtualBox, you will have to connect the VMs by pointing the two machines to a temporary file that will be used as a pipe between them.

Debugger

Port Number: COM1
Port Mode : Host pipe
Create pipe : Checked
Port/File path: /tmp/something

Debugee

Port Number: COM1 – or whatever you set in the boot.ini file
Port Mode: Host pipe
Create pipe: UNchecked
Port/File path: /tmp/something – the same as for the debugger

A simple rule for remembering who creates the pipe: Whoever debugs, controls (creates) the pipe.

Start and configure WinDbg

Next, you have fire up WinDbg in the debugger machine, download the appropriate debugging symbols by selecting “Symbol File Path” from the File menu and entering “SRV*C:\websymbols*http://msdl.microsoft.com/download/symbols” (Note that this page is not browsable, but for debugger access).

After setting the configuring the debugging symbols, you are clear to open up a kernel debugging session by selecting “Kernel debug” from the file menu. You now have to enter the same baudrate you specified when configuring the debugee and click OK.

Boot the debugee

Having a debugging session ready to attach the target to, you can now proceed to boot the debugee, just make sure that when you get to the bootloader, you select the entry that says “Debugger enabled”. As soon as you select this entry, Windows will connect to the debugger.

After the machine has booted (or even before if you want), you can break into the target by pressing Ctrl+Break and you are all set.

Now, browse here and dive deep into your OS.

Happy Debugging!