Skip to content

Latest commit

 

History

History
361 lines (289 loc) · 42.8 KB

windbg_cheatsheet.md

File metadata and controls

361 lines (289 loc) · 42.8 KB

WinDbg cheatsheet

Setup

Installation

Symbol Path

In a command prompt:

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 0xffff

Commands

Basic commands

Action Command Examples
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
.attach 0n<PID>
Display parameter value under different formats (hexadcimal, decimal, octal) .formats .formats 0x42
Change default base n n 8
n 10
Quit WinDbg (will kill the process if not detached) q
Restart debugging session .restart
Reboot system (KD) .reboot
Display register on Break .prompt_allow +reg

Back to top

.printf formatters

Description Formatter Examples
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 

Action Command Examples
Start or resume execution (go) g
Dump register(s) r r
r eax
r rax=42
Step over p pa 0xaddr (step over until 0xaddr is reached)
pt (step over until return)
pc (step over until next call)
Step into t Same as above, replace p with t
Execute until reaching current frame return address (go upper) gu
List module(s) lm lm (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 call k
kp

Back to top

Registers / Memory access

Action Command Examples
Read memory As bytes: db
word: dw
dword: dd
qword: dq
pointer: dp
unicode string: dS
db @sp 41 41 41 41
dw @rip
dd @rax l4
dyb @rip
dps @esp
dS @rsp
Write memory As bytes: 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 instruction r.
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 memory f
c
f @rsp l8 41
c @rsp l8 @rip
Dereference memory poi(<AddrOrSymbol>): dereference pointer size
wo(): dereference WORD
dwo(): dereference DWORD
qwo(): dereference QWORD
db poi( @$rax )

Back to top

Memory search

Action Command Examples
Search byte: 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 

Action Command Examples
Examine x x nt!*CreateProcess*
Display types dt dt ntdll!_PEB @$peb
dt ntdll!_TEB –r @$teb
Display Type Extended - with Debugger Object Model dtx dtx nt!_PEB 0x000008614a7a000
which is equivalent to
dx (nt!_PEB*)0x000008614a7a000
Set breakpoint bp 
bp 0xaddr (or mod!symbol)
List breakpoints bl
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 event sx sxe ld mydll.dll
Break on memory access ba ba r 4 @esp
Define breakpoint command bp … [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+1 bp /1 0xaddr (temporary breakpoint)
bp 0xaddr 7 (disable after 6 hits)
Set "undefined" breakpoint bu <address>

Back to top

Symbols 

Action Command Examples
Examine x x /t /v ntdll!*CreateProcess*
Display types dt dt ntdll!_PEB @$peb
List nearest symbols ln ln 0xaddr
Set/update symbol path .sympath
Load module symbols ld ld Module
ld *

Back to top

Convenience variables and functions 

Action Command Examples
Program entry point $exentry bp $exentry
Process Environment Block $peb dt _PEB @$peb
Thread Environment Block $teb dt _TEB @$teb
Return Address $ra g @ra
Instruction Pointer $ip
Size of Page $pagesize
Size of Pointer $ptrsize
Process ID $tpid
Thread ID $tid

Back to top

Useful extensions

Action Command Examples
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

Action Command Examples
Load the CLR extensions .loadby sos clr sxe 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 description Command Examples
Create a variable dx @$myVar = VALUE dx @$ps = @$cursession.Processes
Delete a variable dx @$vars.Remove("VarName") dx @$vars.Remove("ps")
List user defined variable dx @$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 description Command Examples
Create a "lambda" inline function dx @$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 structure dx 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*)0xAddress dx (nt!_EPROCESS*)&@$curprocess.KernelObject
Format* output data dx <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")
Search a symbol by address dx @$scriptContents.host.getModuleContainingSymbolInformation($addr)

* Format specifiers for .ToDisplayString()

Back to top

WinDbg JavaScript reference

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

Dealing with host.Int64

Action Command Examples
Create/Convert an Int64 object host.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 operation and: [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()

WinDbg gallery skeleton

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 TTD

Action Command Examples
DDM Objects @$curprocess.TTD
@$cursession.TTD
dx @$curprocess.TTD.Threads.First().Lifetime
dx @$cursession.TTD.Calls("ntdll!Nt*File").Count()
Run execution back g-
Reverse Step Over p-
Reverse Step Into t-
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