Windows Debugging - Basics
Basic Postmortem Of Windows Process
PART I. ( Understanding Tools To Be Used )
** **Every application / driver comprises of processes and threads. Every process has the following
- Virtual Address space
- Executable code
- One executable thread ( MUST )
- Open handles to objects
- PID (process ID )
- Working sets
- Security Context
How do we view this and what are the tools required to view this data will be covered below.
** **
**Utilities Used To Debug Applications And Drivers: **
My article is specific to debug Microsoft applications and drivers written for Windows operating systems. Following are some of the utilities that every developer should know and use.
- Visual Studio ( All versions )
- ADPlus
- Windbg
- DebugDiag
- BoundsChecker ( compuware )
- Purify ( IBM )
** **
**Points To Be Noted: **
a) Applications developed using .NET can take advantage of DebugDiag utility and then use Windbg side-by .
b) Driver developers can rely on Windbg. There was another classic tool “softice” which is no longer supported
c) Applications developed in MFC / ATL / C++ / C# can take advantage of Visual studio inbuilt debug functionality and can use windbg side-by.
** **
** **
PART II. ( Preparing Debugging Environment )
** **
Configuring Windbg Utility:
One of the best utility used by Microsoft / debuggers to debug applications / drivers is Windbg. You can download windbg from the following website http://www.microsoft.com/whdc/devtools/debugging/default.mspx . You can either download 32bit / 64bit installable. After downloading the utility, we have to configure it accordingly. Microsoft always assists newbie’s to use “help file” which exposes all the relevant documentation required to understand their product. Following are the immediate steps required once you have installed windbg utility.
**Configuring Symbol File Path: **
This is the next immediate step after you download and install the Windbg utility. Symbol files contains the following information
- Function names and addresses
- Global variables
- Local variables
- Frame pointers
All of the above are bundled into a file called .pdb .These .pdb files are generated when you execute the program ( specifically the linker creates these .pdb files ). The location of these .pdb files are located in application’s project directory
Eg: c:\DocumentsandSettings\Administrator\MyDocuments\VisualStudio2005\Projects\debugcrash\debug\debugcrash.pdb
The above example belongs to the applications you develop in-house, but in-order to download the symbol files belongs to Microsoft , you need to provide the symbol file path which is provided by Microsoft
Eg: SRV*your local symbol folder
*http://msdl.microsoft.com/download/symbols
Symbol file path should be configured under Windbg using following procedure
a) Open windbg
b) Navigate to File à Symbol File Path à provide the location accordingly
http://windowsarchitecture.files.wordpress.com/2010/12/windbg1.jpg?w=300&h=220
IMPORTANT NOTE: When debugging applications related to third party / applications for which you do not have the source code , you need to request the vendor for the .pdb files.
** **
**Configure Source File Path: **
Once you have configured the symbol file path, you should configure the path for your source ( provided you are debugging application / driver which you have developed ). You can do this by navigating to File à Source File Path and provide the location of your executable. (follow image below )
http://windowsarchitecture.files.wordpress.com/2010/12/windbg2.jpg?w=300&h=239
** **
** **
PART III ( Analyzing The Application )
Once you have configured the above settings, its time for us to analyze our application. The final step required is to hook the exe to Windbg which needs to be debugged. You have to open executable using Windbg through windbg à OpenExecutable à provide the path accordingly ( follow the image below )
http://windowsarchitecture.files.wordpress.com/2010/12/windbg3.jpg?w=300&h=186
*Please save the workspace when prompted.
Next step is to reload the symbol using .reload /f command, observe for any errors and resolve them accordingly. There is another way to reload the symbol files , by navigating File à Symbol File Path à reload . After you reload the symbol files, you have to confirm if the symbol files are loaded, this can be done using lm command , which gives you the .pdb files which are loaded by debugger ( follow the screen below )
http://windowsarchitecture.files.wordpress.com/2010/12/windbg5.jpg?w=300&h=67
When you hit lm command , you might see deferred status for modules . Debugger loads the symbols when required so you would see deferred status, in which you can force the symbol to load using .reload /f .
Till now , we have prepared the debugger , configured the symbol files, attached our exe to the debugger. If you are debugging Your application , you can always put the relevant breakpoints to the functions you require, this depends on scenario / behavior of the problem. For this article, I would like to restrict my lab to view process information. For my lab purpose , I have written an MFC application called “Threadtest” with single parent process and single **thread. **
To view the number of processes in your application, you should use pipe command |* which displays the below information.
http://windowsarchitecture.files.wordpress.com/2010/12/windbg6.jpg?w=300&h=20
My application is using one process and observe the ( dot ) beside ‘0’ which means this process is the current process.
Once we identify the number of processes for an application you are debugging / for driver , you should know more about how the process is built , which includes the different data structures involved , Memory information, Heap, Environment etc.. One of the limitation of Windbg is that it doesn’t provide a way to “step-in” between user mode and kernel mode. There are multiple ways to tackle this behavior
- Launch two debuggers , one in user mode and other in kernel mode and analyze the process or thread activity accordingly.
- Setup Target and Host and debug the process accordingly ( You can look into the help file in windbg how to setup Target and Host scenario )
Why do we need to perform step in to kernel mode ?, cant we analyze the data under user mode context ?
Answer to the above question is NO. In order to analyze the data structures responsible for constructing a process can only be analyzed in kernel mode.
So what are the options available for any user under User Mode ?
Specific to process ( excluding the stack ) , the options provided by windbg is lean. It provides you to analyze
- Number of processes of your application — | , | *
- Active process — | .
- Process which caused exception — | #
In order to analyze the Eprocess / PEB of the process / virtual memory of the process , you can perform the same in KD session. But I tried using !peb <PEB address of a process> under the user mode session and I was able to get the information which was similar running !peb <PEB address of a process> under LKD / KD.
Eg: under user mode running !peb 7ffdc000 will give you below information
** **!peb 7ffdc000
PEB at 7ffdc000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: Yes
ImageBaseAddress: 00400000
Ldr 002524b0
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 00252568 . 00253048
Ldr.InLoadOrderModuleList: 002524f0 . 002530f8
Ldr.InMemoryOrderModuleList: 002524f8 . 00253100
Base TimeStamp Module
Under kernel mode !peb 7ffdc000
!peb 7ffdc000
PEB at 7ffdc000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: Yes
ImageBaseAddress: 00400000
Ldr 002524b0
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 00252568 . 00253048
Ldr.InLoadOrderModuleList: 002524f0 . 002530f8
Ldr.InMemoryOrderModuleList: 002524f8 . 00253100
This article explains, how to setup the debugger appropriately and hook the application to debug.