WinDbg cheatsheet

origin link: https://github.com/hugsy/defcon_27_windbg_workshop/blob/master/windbg_cheatsheet.md

Content

Setup

Symbol Path

In a command prompt:

C:\> setx _NT_SYMBOL_PATH srv*C:\Symbols*https://msdl.microsoft.com/download/symbols

In WinDbg, Ctrl+S then

srv*C:\Symbols*https://msdl.microsoft.com/download/symbols

Back to top

Providers

In WinDbg

0:000> .scriptproviders

Should display something like

Available Script Providers:
    NatVis (extension '.NatVis')
    JavaScript (extension '.js')

VS Code linting

Download JsProvider.d.ts to the root of your script and add the following at its top:

/// <reference path="JSProvider.d.ts" />
"use strict";

Kernel Debugging

kd> ed nt!Kd_Default_Mask 0xf
  • permanently from registry hive (in Admin prompt on Debuggee)
C:\> reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter" /v DEFAULT /t REG_DWORD /d 0xf

Commands

Basic commands

ActionCommandExamples
Help / Manual.hh <command>.hh
.hh !process
Clear screen.cls
Dynamic evaluation?? 40004141 – nt
? 2 + 2
? nt!ObTypeArrayIndex
Comment$$$$ this is a useful comment
Print a string.echo.echo "Hello world"
Print a formatted string
(see printf formatters)
.printf.printf "Hello %ma\n" , @$esp
Command separator;command1 ; command2
Attach (Detach) to (from) process.attach.detach
Display parameter value under different formats (hexadcimal, decimal, octal).formats.formats 0x42
Change default basenn 8
Quit WinDbg (will kill the process if not detached)q
Restart debugging session.restart
Reboot system (KD).reboot

Back to top

.printf formatters

DescriptionFormatterExamples
ASCII C string (i.e. NULL terminated)%ma
Wide C string (i.e. NULL terminated)%mu
UNICODE_STRING** string%msu
Print the symbol pointed by address%y.printf “%y\n”,ffff8009bc2010 // returns nt!PsLoadedModuleList
Print a Pointer%p.printf “%p\n”,nt!PsLoadedModuleList // returns 0xffff8009bc2010

Back to top

Execution flow

ActionCommandExamples
Start or resume execution (go)g
Dump register(s)rr
r eax
r rax=42
Step overppa 0xaddr (step over until 0xaddr is reached)
pt (step over until return)
pc (step over until next call)
Step intotSame as above, replace p with t
Execute until reaching current frame return address (go upper)gu
List module(s)lmlm (UM: display all modules)
lm (KM: display all drivers and sections)
lm m *MOD* (show module with pattern 'MOD' )
Get information about current debugging status.lastevent
!analyze
Show stack callk
kp

Back to top

Registers / Memory access

ActionCommandExamples
Read memory Asbytes: db
word: dw
dword: dd
qword: dq
pointer: dp
unicode string: dW
db @sp 41 41 41 41
dw @rip
dd @rax l4
dyb @rip
dps @esp
dW @rsp
Write memory Asbytes: eb
word: ew
dword: ed
qword: eq
ascii string:ea
Unicode string: eu



ea @pc "AAAA"
Read register(s)r
r [[REG0],REG1,...]
r rax,rbp
Write register(s)r [REG]=[VALUE]r rip=4141414141414141
Show register(s) modified by the current instructionr.
Dump memory to file.writemem.writemem C:\mem.raw @eip l1000
Load memory from file.readmem.readmem C:\mem.raw @rip l1000
Dump MZ/PE header info!dh!dh kernel32
!dh @rax
Read / write physical memory
(syntax similar to dX/eX commands)
!db / !eb
!dw / !ew
!dd / !ed
!dq / !eq
Fill / Compare memoryf
c
f @rsp l8 41
c @rsp l8 @rip
Dereference memorypoi(<AddrOrSymbol>): dereference pointer size
dwo(): dereference DWORD
qwo(): dereference QWORD
db poi( @$rax )

Back to top

ActionCommandExamples
Searchbyte: s [RANGE] [VALUE]
dword: s -d [RANGE] [DWORD_VALUE]
s @eip @eip+100 90 90 90 cc
s -d @eax l100 41424344
Search ASCII (Unicode)s –a <AddrStart> L<NbByte> "Pattern"
s –a <AddrStart> <AddrEnd> "Pattern"
(for Unicode – change –a with –u)
Search for pattern in command.shell.shell -ci "<windbg command>" batch command
.shell -ci "!address" findstr PAGE_EXECUTE_READWRITE

Back to top

Breakpoints

ActionCommandExamples
Examinexx nt!*CreateProcess*
Display typesdtdt ntdll!_PEB @$peb
dt ntdll!_TEB –r @$teb
Display Type Extended - with Debugger Object Modeldtxdtx nt!_PEB 0x000008614a7a000
which is equivalent to
dx (nt!_PEB*)0x000008614a7a000
Set breakpointbp
bp 0xaddr (or mod!symbol)
List breakpointsbl
Disable breakpoint(s)bd [IDX] (IDX is returned by bl)bd 1
bd *
Delete breakpoint(s)bc [IDX] (IDX is returned by bl)bc 0
bc *
(Un)Set exception on eventsxsxe ld mydll.dll
Break on memory accessbaba r 4 @esp
Define breakpoint commandbp … [Command]
Where [Command] can be
- an action: "r ; g"
- a condition: ".if (@$rax == 1) {.printf \"rcx=%p\\\n\", @rcx }"
bp kernel32!CreateFileA "da @rcx; g" "
Enable breakpoint after N hit(s)bp <address> N+1bp /1 0xaddr (temporary breakpoint)
bp 0xaddr 7 (disable after 6 hits)
Set "undefined" breakpointbu <address>

Back to top

Symbols

ActionCommandExamples
Examinexx /t /v ntdll!*CreateProcess*
Display typesdtdt ntdll!_PEB @$peb
List nearest symbolslnln 0xaddr
Set/update symbol path.sympath
Load module symbolsldld Module
ld *

Back to top

Convenience variables and functions

ActionCommandExamples
Program entry point$exentrybp $exentry
Process Environment Block$pebdt _PEB @$peb
Thread Environment Block$tebdt _TEB @$teb
Return Address$rag @ra
Instruction Pointer$ip
Size of Page$pagesize
Size of Pointer$ptrsize
Process ID$tpid
Thread ID$tid

Back to top

Useful extensions

ActionCommandExamples
Detailed information about loaded DLLs!dlls
!dlls -I (show load order)
!dlls -c 0xaddr (show DLL containing0xaddr)
Get mapping information!address!address -f:MEM_COMMIT
Change verbosity of symbol loader!sym!sym noisy
!sym quiet
Dump PEB/TEB information!peb
!teb
Analyze the reason of a crash!analyze!analyze -v
Convert an NTSTATUS code to text!error!error c0000048
Perform heuristic checks to
the exploitability of a bug
!exploitable
Encode/decode pointer encoded
by KernelBase API EncodePointer()
!encodeptr32 (or 64)
!decodeptr32 (or 64)
Display the current exception handler!exchain
Dump UM heap information!heap

Back to top

.NET Debugging

ActionCommandExamples
Load the CLR extensions.loadby sos clrsxe ld clr; g to make sure clr.dll is loaded, then .loadby sos clr
Get help!help
Set managed code breakpoint!bpmd <module> Path.To.Function!bpmd mscorlib.dll System.Reflection.Assembly.Load
!bpmd System.dll System.Diagnostics.Process.Start
!bpmd System.dll System.Net.WebClient.DownloadFile
List all managed code breakpoints!bpmd -list
Clear specific managed code breakpoint!bpmd -clear $BreakpointNumber
Clear all managed code breakpoints!bpmd -clearall
Dump objects!DumpObj!DumpObj /d 0x<address>
Dump the .NET stack!CLRStack!CLRStack -p

Back to top

LINQ & Debugger Data Model

Variables

Variable descriptionCommandExamples
Create a variabledx @$myVar = VALUEdx @$ps = @$cursession.Processes
Delete a variabledx @$vars.Remove("VarName")dx @$vars.Remove("ps")
List user defined variabledx @$vars
dx Debugger.State.UserVariables
Bind address Address to
a N-entry array of type T
dx (T* [N])0xAddress dx (void** [5]) Debugger.State.PseudoRegisters.General.csp

Functions

Function descriptionCommandExamples
Create a "lambda" inline functiondx @$my_function = ([arg0, arg1] => Code) dx @$add = (x, y => x + y)
Filtering objects[Object].Where( [FILTER PATTERN] )dx @$cursession.Processes.Where( x => x.Name == "notepad.exe")
Sorting objects- asc: [Object].OrderBy([Sort Expression])
- desc: [Object].OrderByDescending([Sort Expression])
dx @$cursession.Processes.OrderByDescending(x => x.KernelObject.UniqueProcessId)
Projecting.Select( [PROJECTION KEYS] ).Select( p => new { Item1 = p.Name, Item2 = p.Id } )
Access n-th element of iterable$Object[n]@$cursession.Processes[4]
Get the number of objects in iterable$Object.Count()@$cursession.Processes.Count()
Create a iterator from a LIST_ENTRY structuredx Debugger.Utility.Collections.FromListEntry(Address, TypeAsString, "TypeMemberNameAsString")dx @$ProcessList = Debugger.Utility.Collections.FromListEntry( *(nt!_LIST_ENTRY*)&(nt!PsActiveProcessHead), "nt!_EPROCESS", "ActiveProcessLinks")
dx @$HandleList = Debugger.Utility.Collections.FromListEntry( *(nt!_LIST_ENTRY*)&(nt!PspCidTable), "nt!_HANDLE_TABLE", "HandleTableList")
Apply a structure S to memory (dt-like)dx (S*)0xAddressdx (nt!_EPROCESS*)&@$curprocess.KernelObject
Format output datadx <LinqObject>.ToDisplayString($format)
where $format can be
  • d → decimal
  • x → hexadecimal
  • o → octal
  • b → binary
  • s(b) → char string
  • su(b) → wide-char string
dx @$peb->ProcessParameters->ImagePathName.Buffer.ToDisplayString("su"

Back to top

WinDbg JavaScript reference

ActionCommandExamples
Print messagehost.diagnostics.debugLog(Message)
Read data from memoryhost.memory.readMemoryValues(0xAddr, Length)
Read string from memoryhost.memory.readString(0xAddr)
host.memory.readWideString(0xAddr)
Evaluate expressionhost.evaluateExpression([EXPR])var res=host.evaluateExpression("sizeof(_LIST_ENTRY)")
dx @$scriptContents.host.evaluateExpression("sizeof(_LIST_ENTRY)")
Resolve symbolhost.getModuleSymbolAddress(mod, sym)var pRtlAllocateHeap = host.getModuleSymbolAddress('ntdll', 'RtlAllocateHeap');
Dereference a pointer as an objecthost.createPointerObject(...).dereference()var pPsLoadedModuleHead = host.createPointerObject(host.getModuleSymbolAddress("nt", "PsLoadedModuleList"), "nt", "_LIST_ENTRY *");
Create typed variable from addresshost.createTypedObject(addr, module, symbol)var loader_data_entry = host.createTypedObject(0xAddress,"nt","_LDR_DATA_TABLE_ENTRY")
Dereference memoryhost.evaluateExpression('(int*)0xADDRESS').dereference()
Get access to the Pseudo-Registershost.namespace.Debugger.State.PseudoRegistersvar entrypoint = host.namespace.Debugger.State.PseudoRegisters.General.exentry.address;
Execute WinDbg commandhost.namespace.Debugger.Utility.Control.ExecuteCommandvar modules=host.namespace.Debugger.Utility.Control.ExecuteCommand("lm");
Set Breakpointhost.namespace.Debugger.Utility.Control.SetBreakpointAtSourceLocation
host.namespace.Debugger.Utility.Control.SetBreakpointAtOffset
host.namespace.Debugger.Utility.Control.SetBreakpointForReadWrite
Iterate through LIST_ENTRYshost.namespace.Debugger.Utility.Collections.FromListEntry()var process_iterator = host.namespace.Debugger.Utility.Collections.FromListEntry( pAddrOfPsActiveProcessHead, "nt!_EPROCESS", "ActiveProcessLinks")

Dealing with host.Int64

ActionCommandExamples
Create/Convert an Int64 objecthost.parseInt64('value')
host.parseInt64('value', 16 )
host.parseInt64('42');
host.parseInt64('0x1337', 16);
Add / Subtract[Int64Obj].add($int)
[Int64Obj].subtract($int)
var NextPage = BasePage.add(0x1000);
var NextPage = BasePage.subtract(0x1000);
Multiply / Divide[Int64Obj].multiply($int)
[Int64Obj].divide($int)
Compare[Int64Obj1].compareTo([Int64Obj2])BasicBlock.StartAddress.compareTo(Address1) <= 0
Bitwise operationand: [Int64Obj].bitwiseAnd($int)
or: [Int64Obj].bitwiseOr($int)
xor: [Int64Obj].bitwiseXor($int)
lsh: [Int64Obj].bitwiseShiftLeft($shift)
rsh: [Int64Obj].bitwiseShiftRight($shift)
var PageBase = Address.bitwiseAnd(0xfffff000);
Address.bitwiseShiftLeft(12).bitwiseShiftRight(12);
Convert Int64 to native number- with exception if precision loss: [Int64Obj].asNumber()
- no exception if precision loss: [Int64Obj].convertToNumber()

Only 3 files are needed (see [5] for more details):

  • config.xml
<?xml version="1.0" encoding="UTF-8"?>
<Settings Version="1">
  <Namespace Name="Extensions">
    <Setting Name="ExtensionRepository" Type="VT_BSTR" Value="Implicit"></Setting>
    <Namespace Name="ExtensionRepositories">
      <Namespace Name="My Awesome Gallery">
        <Setting Name="Id" Type="VT_BSTR" Value="any-guid-will-do"></Setting>
        <Setting Name="LocalCacheRootFolder" Type="VT_BSTR" Value="\absolute\path\to\the\xmlmanifest\directory"></Setting>
        <Setting Name="IsEnabled" Type="VT_BOOL" Value="true"></Setting>
      </Namespace>
    </Namespace>
  </Namespace>
</Settings>
  • ManifestVersion.txt
1
1.0.0.0
1
  • Manifest.X.xml (where X is the version number, let's just use 1 so it is Manifest.1.xml)
<?xml version="1.0" encoding="utf-8"?>
<ExtensionPackages Version="1.0.0.0" Compression="none">
  <ExtensionPackage>
    <Name>Script1</Name>
    <Version>1.0.0.0</Version>
    <Description>Description of Script1.</Description>
    <Components>
      <ScriptComponent Name="Script1" Type="Engine" File=".\relative\path\to\Script1.js" FilePathKind="RepositoryRelative">
        <FunctionAliases>
          <FunctionAlias Name="AliasCreatedByScript`">
            <AliasItem>
              <Syntax><![CDATA[!AliasCreatedByScript]]></Syntax>
              <Description><![CDATA[Quick description of AliasCreatedByScript.]]></Description>
            </AliasItem>
          </FunctionAlias>
        </FunctionAliases>
      </ScriptComponent>
    </Components>
  </ExtensionPackage>
</ExtensionPackages>

Then in WinDbg load & save:

0:000> .settings load \path\to\config.xml
0:000> .settings save

Back to top

Time-Travel Debugging

ActionCommandExamples
DDM Objects@$curprocess.TTD
@$cursession.TTD
dx @$curprocess.TTD.Threads.First().Lifetime
dx @$cursession.TTD.Calls("ntdll!Nt*File").Count()
Run execution backg-
Reverse Step Overp-
Reverse Step Intot-
Regenerate the index!ttdext.index
Jump to position XX:YY (WinDbg)!tt XX:YY!tt 1B:0
Jump to position XX:YY (DDM)<TtdPosition>.SeekTo()dx @$curprocess.TTD.Lifetime.MinPosition.SeekTo()

Back to top

Additional resources

  1. WinDbg .printf formatters
  2. JavaScript Debugger Scripting
  3. WinDbg Pseudo-Register Syntax
  4. WinDbg Playlist on YouTube
  5. WinDbg Extension Gallery
  6. SOS commands for .NET debugging

Back to top