This page has been machine-translated from the original page.
My goal is to become proficient with WinDbg for Windows debugging and dump-based troubleshooting.
This time, I started by reproducing the steps in the official tutorial so I could try user-mode process debugging with WinDbg.
For a full list of articles on Windows debugging and dump analysis with WinDbg, see the page below.
Reference: Debugging and Troubleshooting Techniques with WinDbg
This article covers the following topics.
Table of Contents
- What Is WinDbg?
-
- Environment Used This Time
- Launching Notepad.exe
- Setting and Loading the Symbol Path
- Listing Symbols
- Setting a Breakpoint
- Running Notepad.exe
- Displaying the List of Code Modules Loaded in the Process
- Displaying a Stack Trace
- Resuming Notepad.exe
- Stopping the Process When a File Is Written
- Displaying the List of Threads in the Process
- Getting the Stack Trace of a Specific Thread
- Ending Debugging and Detaching from the Process
- Wrap-up
What Is WinDbg?
WinDbg is a tool used for debugging and troubleshooting in Windows environments.
Reference: Getting Started with Windows Debugging - Windows drivers | Microsoft Docs
WinDbg is mainly used for the following purposes.
- Analyzing Windows memory dumps and process dumps
- Live debugging in kernel mode
- Live debugging in user mode
It is Microsoft’s official debugger, and it is also used by the Windows development team.
One difference from the Visual Studio debugger is that WinDbg can also handle kernel-mode debugging and thread stack analysis.
WinDbg Tutorial
As a first step with WinDbg, I followed the official tutorial.
In this tutorial, we attach WinDbg to a user-mode process and debug it.
Environment Used This Time
The environment used this time is as follows.
- Windows 10 20H2
- WinDbg 10.0.22000.1 AMD64 (launched with administrator privileges)
Launching Notepad.exe
After starting WinDbg in Windows, press [Ctrl+E] to open [Open Executable File], then select C:\Windows\System32\notepad.exe.
When I opened the executable file, the Command window appeared.
Setting and Loading the Symbol Path
Enter the following command in the console at the bottom of the Command window.
.sympath srv*The .sympath command sets the symbol path.
The symbol path is the search location that the debugger uses when looking for symbol files.
Symbol files are required for the debugger to obtain information about code modules (such as function names and variable names).
Reference: .sympath (Set Symbol Path) - Windows drivers | Microsoft Docs
Now that the symbol path has been configured, run the following command.
.reloadThe .reload command clears symbol information and then reloads it.
Reference: .reload (Reload Module) - Windows drivers | Microsoft Docs
Note that even when you run .reload, there may be no visible response.
Proceed once you see output like the following.
0:000> .reload
Reloading current modules
................Listing Symbols
After confirming the output above, run the x notepad!* command to display the symbols in the Notepad.exe module.
If no output appears here, run .reload again.
Reference: x notepad!*
The output was close to 1,500 lines. That’s quite a lot.
Setting a Breakpoint
Next, using the symbol information confirmed above, set a breakpoint on the wWinMain function.
bu notepad!wWinMainThere is no particular output, but you can check the list of breakpoints with the bl command.
Reference: bl (Breakpoint List) - Windows drivers | Microsoft Docs
This confirms that a breakpoint has been set on notepad!wWinMain.
0:000> bu notepad!wWinMain
0:000> bl
0 e Disable Clear 00007ff6`8402c0f8 0001 (0001) 0:**** notepad!wWinMainRunning Notepad.exe
Now that the breakpoint has been set, run the application with the g command.
Reference: g (Go) - Windows drivers | Microsoft Docs
Execution stopped when the wWinMain function specified by the breakpoint was called.
0:000> g
ModLoad: 00007ff9`9cd70000 00007ff9`9cda0000 C:\WINDOWS\System32\IMM32.DLL
Breakpoint 0 hit
notepad!wWinMain:
00007ff6`8402c0f8 488bc4 mov rax,rspDisplaying the List of Code Modules Loaded in the Process
With the process stopped at the breakpoint, run the lm command to check the code modules currently loaded in the process.
Reference: lm (List Loaded Modules) - Windows drivers | Microsoft Docs
0:000> lm
start end module name
00007ff6`84020000 00007ff6`8405a000 notepad (pdb symbols) C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\notepad.pdb\6539CE998C7CAFD73A8E13A54542E1121\notepad.pdb
00007ff9`8ef30000 00007ff9`8f1ca000 COMCTL32 (deferred)
00007ff9`982c0000 00007ff9`98350000 apphelp (deferred)
00007ff9`9aa40000 00007ff9`9aadd000 msvcp_win (deferred)
00007ff9`9ab90000 00007ff9`9ae59000 KERNELBASE (deferred)
00007ff9`9aec0000 00007ff9`9afc0000 ucrtbase (deferred)
00007ff9`9b010000 00007ff9`9b11b000 gdi32full (deferred)
00007ff9`9b340000 00007ff9`9b362000 win32u (deferred)
00007ff9`9bbc0000 00007ff9`9bcea000 RPCRT4 (deferred)
00007ff9`9bf20000 00007ff9`9c275000 combase (deferred)
00007ff9`9c3c0000 00007ff9`9c46e000 shcore (deferred)
00007ff9`9cc50000 00007ff9`9cd0e000 KERNEL32 (deferred)
00007ff9`9cd70000 00007ff9`9cda0000 IMM32 (deferred)
00007ff9`9cfd0000 00007ff9`9cffb000 GDI32 (deferred)
00007ff9`9d000000 00007ff9`9d1a1000 USER32 (deferred)
00007ff9`9d1b0000 00007ff9`9d24e000 msvcrt (deferred)
00007ff9`9d290000 00007ff9`9d485000 ntdll (pdb symbols) C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\ntdll.pdb\E2BF5EA3ECAA1D5310F1E166306A0BCC1\ntdll.pdbDisplaying a Stack Trace
With the process stopped, run the k command to display a stack trace.
This time, I was able to capture the stack trace at the moment execution stopped in notepad!wWinMain.
0:000> k
# Child-SP RetAddr Call Site
00 00000055`5f11f7b8 00007ff6`840459b6 notepad!wWinMain
01 00000055`5f11f7c0 00007ff9`9cc67034 notepad!__scrt_common_main_seh+0x106
02 00000055`5f11f800 00007ff9`9d2e2651 KERNEL32!BaseThreadInitThunk+0x14
03 00000055`5f11f830 00000000`00000000 ntdll!RtlUserThreadStart+0x21Resuming Notepad.exe
If you run the g command once more, the paused process resumes and the Notepad application starts.
In this state, the debugger becomes Busy and stops accepting additional command input.
To stop the Notepad process again and continue using the debugger, click the Break button or press [Ctrl+Break].
This stops the Notepad process again, and debugger operations become available once more.
Stopping the Process When a File Is Written
Next, run bu ntdll!ZwWriteFile to set a breakpoint that interrupts the process when a file is written.
0:002> bu ntdll!ZwWriteFile
0:002> bl
0 e Disable Clear 00007ff6`8402c0f8 0001 (0001) 0:**** notepad!wWinMain
1 e Disable Clear 00007ff9`9d32ce60 0001 (0001) 0:**** ntdll!NtWriteFileAfter entering the g command again to resume the process, try writing and saving content in Notepad, and the process will stop.
If you display a stack trace at this point, you can capture the stack trace at the time of the write.
0:011> k
# Child-SP RetAddr Call Site
00 00000055`5f8fdb78 00007ff9`9bc1f6f4 ntdll!NtWriteFile
01 00000055`5f8fdb80 00007ff9`9bc0c641 RPCRT4!UTIL_WriteFile+0x5c
02 00000055`5f8fdbe0 00007ff9`9bbf5863 RPCRT4!NMP_SyncSend+0x81
03 00000055`5f8fdc60 00007ff9`9bbf2a56 RPCRT4!OSF_CCONNECTION::TransSendReceive+0xf7
04 00000055`5f8fdcd0 00007ff9`9bbf239b RPCRT4!OSF_CCONNECTION::SendBindPacket+0x2ee
05 00000055`5f8fdf20 00007ff9`9bbf3ed1 RPCRT4!OSF_CCONNECTION::ActuallyDoBinding+0xeb
06 00000055`5f8fdfd0 00007ff9`9bbf3c0e RPCRT4!OSF_CCONNECTION::OpenConnectionAndBind+0x225
07 00000055`5f8fe080 00007ff9`9bbf7736 RPCRT4!OSF_CCALL::BindToServer+0xce
08 00000055`5f8fe120 00007ff9`9bbf84d6 RPCRT4!OSF_BINDING_HANDLE::InitCCallWithAssociation+0x8a
09 00000055`5f8fe180 00007ff9`9bbf75e7 RPCRT4!OSF_BINDING_HANDLE::AllocateCCall+0x256
0a 00000055`5f8fe2e0 00007ff9`9bca00f5 RPCRT4!OSF_BINDING_HANDLE::NegotiateTransferSyntax+0x37
0b 00000055`5f8fe330 00007ff9`9bca3840 RPCRT4!NdrpClientCall3+0x715
0c 00000055`5f8fe6a0 00007ff9`99bc139e RPCRT4!NdrClientCall3+0xf0
0d 00000055`5f8fea30 00007ff9`775c1e00 wkscli!NetWkstaGetInfo+0x5e
0e 00000055`5f8feae0 00007ff9`83c62df6 ntlanman!NPOpenEnum+0x50
0f 00000055`5f8fec40 00007ff9`83c61b7f MPR!MprOpenEnumConnect+0x176Displaying the List of Threads in the Process
You can use the ~ command to get the list of threads in the process.
Reference: ~ (Thread Status) - Windows drivers | Microsoft Docs
It looks like the current Notepad process has the following 14 threads.
0:011> ~
0 Id: de4.7ac Suspend: 1 Teb: 00000055`5f35c000 Unfrozen
1 Id: de4.22f0 Suspend: 1 Teb: 00000055`5f36a000 Unfrozen
2 Id: de4.1500 Suspend: 1 Teb: 00000055`5f36e000 Unfrozen
3 Id: de4.198c Suspend: 1 Teb: 00000055`5f370000 Unfrozen
4 Id: de4.2094 Suspend: 1 Teb: 00000055`5f364000 Unfrozen
5 Id: de4.1d6c Suspend: 1 Teb: 00000055`5f372000 Unfrozen
6 Id: de4.1048 Suspend: 1 Teb: 00000055`5f368000 Unfrozen
7 Id: de4.1408 Suspend: 1 Teb: 00000055`5f374000 Unfrozen
8 Id: de4.30c Suspend: 1 Teb: 00000055`5f376000 Unfrozen
9 Id: de4.1b18 Suspend: 1 Teb: 00000055`5f378000 Unfrozen
10 Id: de4.af8 Suspend: 1 Teb: 00000055`5f37a000 Unfrozen
. 11 Id: de4.898 Suspend: 1 Teb: 00000055`5f37e000 Unfrozen
12 Id: de4.1720 Suspend: 1 Teb: 00000055`5f380000 Unfrozen
13 Id: de4.37c Suspend: 1 Teb: 00000055`5f382000 UnfrozenGetting the Stack Trace of a Specific Thread
To get the stack trace of a specific thread, use the following commands in sequence.
~0s
kThe ~0s command switches to thread number 0.
Reference: ~s (Set Current Thread) - Windows drivers | Microsoft Docs
The output looked as follows.
0:011> ~0s
win32u!NtGdiGetCharABCWidthsW+0x14:
00007ff9`9b3465e4 c3 ret
0:000> k
# Child-SP RetAddr Call Site
00 00000055`5f117108 00007ff9`9b01a2ae win32u!NtGdiGetCharABCWidthsW+0x14
01 00000055`5f117110 00007ff9`9b01a211 gdi32full!LoadGlyphMetricsWithGetCharABCWidthsI+0x5e
02 00000055`5f1174b0 00007ff9`9b019d60 gdi32full!LoadGlyphMetrics+0x99
03 00000055`5f1174f0 00007ff9`8aa29016 gdi32full!CUspShapingFont::GetGlyphDefaultAdvanceWidths+0x150
04 00000055`5f117550 00007ff9`9b020b65 TextShaping!ShapingGetGlyphPositions+0x516
05 00000055`5f117750 00007ff9`9b0266e3 gdi32full!ShlPlaceOT+0x255
06 00000055`5f117970 00007ff9`9b025d9b gdi32full!RenderItemNoFallback+0x573
07 00000055`5f117aa0 00007ff9`9b025c6b gdi32full!RenderItemWithFallback+0xeb
08 00000055`5f117af0 00007ff9`9b025a3f gdi32full!RenderItem+0x3b
09 00000055`5f117b40 00007ff9`9b027ac6 gdi32full!ScriptStringAnalyzeGlyphs+0x20f
0a 00000055`5f117bf0 00007ff9`9b024ca2 gdi32full!ScriptStringAnalyse+0x626
0b 00000055`5f117dc0 00007ff9`9b0246be gdi32full!LpkCharsetDraw+0x5c2
0c 00000055`5f117ff0 00007ff9`9d01f5f2 gdi32full!LpkDrawTextEx+0x5e
0d 00000055`5f118060 00007ff9`9d01e9bf USER32!DT_DrawStr+0xb6
0e 00000055`5f118110 00007ff9`9d01eede USER32!DT_GetLineBreak+0xf3
0f 00000055`5f1181b0 00007ff9`9d01eb50 USER32!DrawTextExWorker+0x36e
10 00000055`5f118300 00007ff9`6b8a6123 USER32!DrawTextW+0x40
11 00000055`5f118370 00007ff9`6b89ac60 DUI70!DirectUI::Element::GetContentSize+0x463
12 00000055`5f118450 00007ff9`6b8a7196 DUI70!DirectUI::Element::_UpdateDesiredSize+0x6a0
{{ Omitted below }}Ending Debugging and Detaching from the Process
Finally, use the qd command to end debugging and detach from the process.
When debugging ended, the Command window closed and the paused write operation in Notepad resumed.
Wrap-up
For now, I worked through the user-mode debugging steps from the official tutorial.
For other published information on Windows debugging and dump analysis with WinDbg, see the list on the following page.
Reference: Debugging and Troubleshooting Techniques with WinDbg