Windbg useful commands
Table of Contents
All windbg commands here #
Add symbol #
Go to File -> Symbol Search Path then add the path below
srv*c:\symbols*https://msdl.microsoft.com/download/symbols
Load the symbols #
Note.: Attach to a process then run the command to load the symbols
.reload /f
Run the program #
g
Clear windbg screen #
.cls
Unassemble MNEMONIC instructions #
The u command accepts memory address, range of memory address or symbol names. We can use “ub” command to disassemble by counting backwards.
u module!function
Read data from memory #
db esp
db 069fdcc
db kernel32!WriteFile
dw 069fdcc
dd 069fdcc
dq 069fdcc
dW KERNELBASE+0X40 // show ascii value on the right
dc KERNELBASE // show ascii character
Control length to be displayed #
The default is 0x80 bytes. The L
dd esp L4
db esp L10
Display contents of address #
sds (double word), dqs (Qword), dps (Pointer sized 4 byte or 8 byte depending on computer archtecture).
dds esp L10
dds esp-10 L10
Derefence memory using poi #
dd poi(esp)
Dumping Structures from Memory #
Display type the command is dt, the $teb is a pseudo register that provides address of the TEB
dt ntdll!_TEB
dt ntdll!_TEB @$teb ThreadLocalStoragePointer
Display nested Structures from Memory #
The -r will display nested structures, the $teb is the pseudo register that provides the address of the TEB
dt -r ntdll!_TEB @$teb
Display Exeption Registration Record #
The !teb get the ExceptionList value and use with the dt command as showing below. Another option is !exchain command
!teb
dt _EXCEPTION_REGISTRATION_RECORD 0014f4a4
Calculate size of structure #
?? sizeof(ntdll!_TEB)
Writing a value to Memory #
We can use the edit command followed by size (similar to the display command).
ed esp 41414141 // we are writing a dword to esp ( 4 bytes )
ed esp 41414141
ea esp "Hello" // we can modify ascii values using ea, we write Hello to esp
eu esp Address "String" // we can modify to unicode value using eu, we write to esp.
Searching the memory space #
The -d meanins dword memory address, 0 means beginning of address the L? Length to search, we enter 80000000 to search and followed by value 41414141. we can search for ascii string using the -a flag as well.
s -d 0 L?80000000 41414141
s -a 0 L?80000000 "This program cannot be run in DOS mode" // this earch for the ascii string via -a flag
Inspecting and Editing CPU Register in WinDbg #
We can use “r” command to display all register or individual register. We can use “r” to modify register values
r // list all register
r ecx // list only ecx
r ecx=41414141 // This edit ecx with value of 41414141
Software BreakPoints #
bp kernel32!WriteFile
bl // list the breakpoints
g // let execution run
Disable/Enable BreakPoints #
bd <number> // Disable Breakpoints, get the number with bl
be <number> // Enable Breakpoints, get the number with bl
Clear/Delete BreakPoints #
bc <number> // clear specific breakpoints
bc * to clear all breakpoints
Unresolved Function Breakpoints #
Function not loaded in process memory and it has not been resolved.
bu ole32!WriteStringStream
Breakpoint-Based Actions #
The command below break and print number of bytes from WriteFile function, %p display given value as a pointer.
bp kernel32!WriteFile ".printf \"The number of bytes written is: %p\", poi(esp + 0x0C); .echo;g"
Conditional Breakpoints Actions #
Command below breaks if number of bytes written is 4 otherwise continue execution.
bp kernel32!WriteFile ".if (poi(esp + 0x0C) != 4) {gc} .else { .printf \"The number of bytes written is 4\"; .echo;}"
Hardware Breakpoints #
Hardware breakpoints are performed on processor level in the register, x86/x64 have only 4 registers reserved for hardware breakpoints.
The access can be: e (execute), r (read), w (write)
Example: ba
ba e 1 kernel32!WriteFile
ba w 2 00c56330 // we are set hardware breakpoint write access of first 2 bytes on memory address 00c56330
Stepping through the code #
We can use p (step over the calls) and t (step into the calls) and pt (go end of the function) and ph ( execute code until branching instruction is reached),
This includes conditional or unconditional branches, functions calls and return instructions.
The pa <adddress> (step to Address) executes until reaches the specified memory address.
Listing Modules and Symbols #
We can use lm command do display loaded modules start/end addresses. The deferred for specific modules means no symbols are loaded and .reaload /f can be used to load the symbols.
lm
lm f
We can also filter modules with the command below
lm m kernel*
We can learn more about the symbols using the x command, example
x kernelbase!CreateProc*
Windbg as a calculator #
Mathematical evaluation is performed using the ? Command. The input is assumed to be in hex format.
? 77269bc0 - 77231430 // substraction of memory address
? 77269bc0 >> 18 // shifting a address by 18 bytes
Data Output Format #
by default windbg display result in hexdecimal format. We can conver hex to decimal with 0n prefix or binary to hex with 0xy prefix
? 0n41414141 // converts 41414141 from hex to decimal format
? 0y1110100110111 // convert binary value to hex and decimal
The .formats allow us to convert to all representation at once
.formats 41414141 // converts 41414141 to all formats
Pseudo Registers #
windbg has a series of pseudo registers, there are variables pre-defined.
Example of pseudo registers are $teb contains address of TEB, $t0…$t19 used for mathematical calculation
When using pseudo registers or registers its recommend to prefix them @ character, example @$teb this tells windbg to treat the content as a register or pseudo registers. It speeds the evaluation process because windbg won’t try to resolve it as symbols first.
r @$t0 = (41414141 - 414141) * 0n10 // store the result into pseudo register
r @$t0 // display the result
? @$t0 >> 8 // right shift the result to 8 bits
Check memory permission #
We can check memory permission under Protect field.
!vprot esp
!vprot eip
!vprot 00d13000
List stack frame #
Using the k command to list the stack frame
k
k2
k3
k4