[PowerShell Script] PowerDbg v6.0 – Using PowerShell to Control WinDbg
Last October the latest version of the PowerDbg tool was released, version 6.0. This release has major changes. For example, it is now easier to write scripts or otherwise just hack around the debugger, and includes the PowerDbgConsole, a bootstrapper designed to make setting up an interactive PowerDbg debugging session a one-liner. In addition, this new version is faster, easier to use, and has full 64 bit support.
For those new to PowerDbg, with this tool you can easily create PowerShell scripts to automate a WinDbg/CDB debugging session. You can use PowerDbg for Kernel Mode or User Mode, Post-Mortem Debugging or Live Debugging, either for native or managed code.
PowerShell has several advantages over the WinDbg Scripting Language, like:
- Increased ease in creating scripts
- Leverage in the .NET Framework
- Debugging and tracing features
- Code reuse through functions and cmdlets
- Easier maintenance
- Increased ease in building large scripts
- Ease in formatting and displaying important information
PowerDbg is hosted in the CodePlex website and there you can find all the information you need about the new PowerDbg, so I’m just reusing the information from CodePlex here.
Download
Prerequisites
In order to use PowerDbg you will need:
This comes ‘out of the box’ with Windows 7 and Windows 2008 R2 (though it may not be enabled by default). For other versions of Windows it can be obtained by installing the Windows Management Framework Core Package
A recent version of the Debugging Tools for Windows.
Most of the testing has been done against the version that comes with the Windows SDK 7.1 and the previous stand-alone version 6.1.1.404 (x86 / x64).
You’ll also need to configure PowerShell to allow scripting, which is disabled by default. Typically you’d relax the execution policy to allow unsigned scripts to run from the local machine (only) [1]:
Set-ExecutionPolicy RemoteSigned
If UAC is enabled you’ll need to do this from a PowerShell prompt ‘run as administrator’.
If you’re running 64 bit Windows and plan on doing any 32 bit debugging, you’ll also need to do this in the 32 bit PowerShell console (Windows PowerShell (x86) in your Start menu).
Installation
After downloading, extract the PowerDbg.zip to a temporary directory somewhere, and use the Install_PowerDbg.ps1 script to install it: just right click on it and select ‘Run With PowerShell’.
Alternatively, you can manually drop the PowerDbg.psm1 module file into your PowerShell module directory, ensuring it gets placed in a ‘PowerDbg’ subfolder.
Establishing a PowerDbg Session
New-DbgSession
To use PowerDbg you must first establish a ‘session’. This establishes PowerDbg’s internal connection between a local debugger and either a memory dump, live process, or remote debugger.
Sessions are established using the New-DbgSession cmdlet and can be instantiated in one of four ways:
- attaching to a running process by name (-process)
- launching a process under the debugger (-command)
- opening a memory dump in the debugger (-dump)
- connecting to an existing debugger configured as a server (-remote)
Additionally, PowerDbg can be instructed to auto-load SOS (if possible), using the -sos parameter. This can only be performed if the process in question has already loaded the CLR, and so is not applicable to the -command method.
Example
The PowerDbg 'unhandled exception' demo can be run under the debugger as follows (note the quotes which allow us to pass an argument to the process being launched):
PS > New-DbgSession -command '.\blah\ManagedScenarios.exe UnhandledExceptionScenario'
PS > Send-DbgGo
...
(1104.730): CLR exception - code e0434f4d (first chance)
(1104.730): CLR exception - code e0434f4d (!!! second chance !!!)
KERNELBASE!RaiseException+0x39:
000007fe`fdedaa7d 4881c4c8000000 add rsp,0C8h
PS >
Since the debugger immediately breaks into the launched process, we have to use Send-DbgGo to allow the process to continue on (and subsequently fail). When creating a session to a memory dump or a remote debugger already halted at the point of interest, this would be unnecessary.
Once a PowerDbg session exists, you can interact with it using any of the Get-Dbg* cmdlets, or by using Invoke-DbgCommand to send commands directly.
Notes
Each PowerShell window running PowerDbg can only support one such session at a time.
The session is automatically terminated when the PowerDbg module is unloaded (Remove-Module PowerDbg).
The debugger is attached invasively, and so the debuggee will terminate when the session is ended.
Some Commands
Session Management |
|
Establishes a PowerDbg session with the debugger |
|
Terminates the current PowerDbg session |
|
Loads a debugger extension into the active session |
|
Executes an arbitrary command against the debugger |
|
Exploration |
|
Expands the contents of a managed array |
|
Locates objects on the managed heap by type or MT |
|
Enumerates Dictionary<T,T> collections |
|
Enumerates List<T> collections |
|
Views the contents of a reference-type object |
|
Views the contents of a value-type object |
|
Process State |
|
Lists managed threads |
|
Views the COM apartment state associated with each thread |
|
Lists modules loaded into the process |
|
Views the kernel and user time associated with each thread |
|
Analysis |
|
Sorts all threads by CPU (User Mode) and writes in red all threads which are using third-party components, an easy way to isolate threads consuming high CPU. |
|
Misc |
|
Launches a debugger without creating a PowerDbg session |
|
Takes an immediate full minidump of a given process |
The new PowerDbg is the effort of a great team of people from different companies and different parts of the world. Particularly for me it’s always exciting to work with people from all over the world.
With that said, I want to thank everybody who worked in this project, especially:
I want to thank Lee Holmes (SDE from the PowerShell team) for all his support and valuable tips since the first versions of PowerDbg.
I also want to thank Augusto Pedroza (SDE from the Windows 8 FileSystem team) for using PowerShell in real Microsoft scenarios and for giving valuable feedback on how to improve the tool. (Obrigado Augusto! J)
Finally, I want to send a very special thanks to Piers Williams, who not only contributed with awesome ideas but added hundreds of lines of code to PowerDbg, worked on the documentation, and turned the PowerDbg project into one in which others can easily contribute.
We are looking for developers to join the PowerDbg project. If you’re interested, use the CodePlex site and join us!
Comments
Anonymous
March 26, 2011
Heya Roberto, I am starting to play around a bit more with WinDBG scripting. Are there any books on WinDBG scripting. I am messing with a script on which I want to read from EIP but it has to continue executing commands unless eip holds the value I am looking for It goes like this: r $t2 = by(eip) --> here it reads the byte value in eip than: .if $t2 = 50 { When 50 do this code } .else { When not 50 do this code. } This works only ones. Is there anyway to keep it executing unless it's 50?? Myabe you can point me to some books to read about. best regards, FlySkyAnonymous
March 28, 2011
Hi FlySky, Two mistakes with the code above: 1- Like C/C++ to compare you must use two "=" signs. 2- If you are comparing a decimal number you must specify that. Example: 0:000> r @$t2 = by(@eip) 0:000> r @$t2 $t2=000000c3 So our $t2 has 0xC3 stored in it. 0xC3 = 0n195 ;-) Comparing 0n50 against 0n195: 0:000> .if (0n50 == @$t2) { .echo Same value } .else { .echo Wrong value } Wrong value Comparing 0n195 against 0n195: 0:000> .if (0n195 == @$t2) { .echo Same value } .else { .echo Wrong value } Same value Comparing 0xC3 against 0n195: 0:000> .if (0xC3 == @$t2) { .echo Same value } .else { .echo Wrong value } Same value Comparing 195 (assumed to be Hexa by default and not Decimal) against 0n195: 0:000> .if (195 == @$t2) { .echo Same value } .else { .echo Wrong value } Wrong value Got it? :-) RobertoAnonymous
March 30, 2011
Thanks for the explanation, this indeed makes sense ;) Gonna experiment on it, also bought me the book about Powershell, gonna read and learn that aswell. You know of any books specificially explaining WinDBG scripting? Thanks for your help so far much appreciated, keep up this excellent blog.Anonymous
March 30, 2011
The comment has been removedAnonymous
April 08, 2011
Thanks for the good suggestions Roberto. If I use the following : r $t3 = (@eip)
ffd0 @$t3
It will find the instruction Call eax,. Is it possible to read the result into a psuedo register and do another search?, it's printing the resulting address into the command window , I would like to read it in a pseudo register. r $t4 = # ffd0 @$t3 keeps erroring with character errors: FlySky
Anonymous
September 25, 2012
Hi Roberto, I normally use windbg to debug dump. Your tool sounds interesting. Beside writing scripts and formatting display how it is different from normal windbg. Can you please provide your inputs. RudraAnonymous
September 26, 2012
Hi Rudra, WinDbg scripts and PowerDbg are just a way to automate the debugging session via scripts. With PowerDbg you use PowerShell. http://powerdbg.codeplex.com/ Source Code for PowerDbg: powerdbg.codeplex.com/.../79996 There other tools which do that too and have a nice interface are: Debug Analyzer - http://debuganalyzer.net/ Debug Diag - www.microsoft.com/.../details.aspx