Skip to content

Instantly share code, notes, and snippets.

@muzlightbeer
Last active February 3, 2024 15:52
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save muzlightbeer/a968ee9d35a2e15ef6147e24d455e585 to your computer and use it in GitHub Desktop.
Save muzlightbeer/a968ee9d35a2e15ef6147e24d455e585 to your computer and use it in GitHub Desktop.
WinDbg for Linux Users

The Windows Debugger (WinDbg) for Linux users

The following provides commands for getting started with WinDbg if you've come from a Linux only background and have only used GDB and LLDB.

VMware Fusion and VHD images

Some Windows operating system trials come as virtual hard disk (VHD) images, that state Hyper-V is required to use them. With macOS and VMware Fusion (at the time of writing, VMware Fusion 12.1.2), you can drag the executable files into VMware (the same as with ISO images) and install them normally. No subscriptions are required to obtain access to a DVD or ISO image if you do not have a system that uses Windows as the base operating system.

Microsoft symbols

WinDbg can be configured with Microsoft's public symbols. These are useful when using more advanced commands (such as getting a meaningful backtrace with !heap -p -a) later on. Create a local directory (such as C:\symbols), then navigate to File -> Symbol File Path ... in WinDbg and set the following:

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

Refer to Symbol path for Windows debuggers for further information.

What is the equivalent to b main?

b main does not work on Windows the way it does on Linux. The following is a reasonably close equivalent for most cases:

bp $exentry 

Beginner Reverse Engineering | Part 1: How To Find The Main Function by Marcus Hutchins has detailed information about how to find the main function in a Windows binary.

Setting breakpoints

Use the following to break on an address (in the program's text section):

bp 12345678

As per the Set Breakpoint documentation, such a breakpoint will not be saved in your workspace. If you restart the application with the .restart command, all of your breakpoints will be gone.

Use bu instead of bp if you want your breakpoints to persist across debugging sessions and the .restart command.

How do I list breakpoints?

bl

How do I delete a breakpoint?

Use the following command, where x is the number of the breakpoint returned from the bl command:

bc x

Several can be deleted in one command:

bc 0 1 2 3

How do I continue after hitting a breakpoint?

g

How do I view a stacktrace?

There are a lot of options for viewing a stacktrace in WinDbg. The following is the most basic:

k

If you are interested in parameters, and do not have full symbols, use the following to display a backtrace with the first three function parameters (for each entry in the backtrace):

kb

How do I view threads?

Use the tilda:

~

How do I view a stacktrace for a different thread?

Use the stacktrace command, k, prefixed with the tilda and the thread's number from the previous command's output, for example:

~2 k

I want to ignore C++ exceptions

C++ can throw exceptions. By default, WinDbg breaks when this occurs. Depending on what you are doing, you may cause a lot of exceptions but do not want to stop in the debugger each time.

List exceptions using the following:

sx

For example, by default you would see the following for C++ exceptions (note the break):

eh - C++ EH exception - break - not handled

If you want to ignore these so you do not have to manually continue, use the following command:

sxi eh

Running sx again will show the following:

eh - C++ EH exception - ignore - not handled

To enable these exceptions (break when they occur):

sxe eh

How do I x/32wx things?

WinDbg provides several options for viewing memory. Dumping as double words is a good place to start:

dd 12345

How can I see further ahead? If you start dumping at address 12345, run dd again, and then keep pressing enter, WinDbg will keep scrolling through the memory:

0:005> dd 12345
00012345  00000000 00000000 00000000 00000000
00012355  00000000 00000000 00000000 00000000
00012365  00000000 00000000 00000000 00000000
00012375  00000000 00000000 00000000 00000000
00012385  00000000 00000000 00000000 00000000
00012395  00000000 00000000 00000000 00000000
000123a5  00000000 00000000 00000000 00000000
000123b5  00000000 00000000 00000000 00000000
0:005> dd
000123c5  00000000 00000000 00000000 00000000
000123d5  00000000 00000000 00000000 00000000
000123e5  00000000 00000000 00000000 00000000
000123f5  00000000 00000000 00000000 00000000
00012405  00000000 00000000 00000000 00000000
00012415  00000000 00000000 00000000 00000000
00012425  00000000 00000000 00000000 00000000
00012435  00000000 00000000 00000000 00000000
0:005> 
00012445  00000000 00000000 00000000 00000000
00012455  00000000 00000000 00000000 00000000
00012465  00000000 00000000 00000000 00000000
00012475  00000000 00000000 00000000 00000000
00012485  00000000 00000000 00000000 00000000
00012495  00000000 00000000 00000000 00000000
000124a5  00000000 00000000 00000000 00000000
000124b5  00000000 00000000 00000000 00000000
0:005> 
000124c5  00000000 00000000 00000000 00000000
000124d5  00000000 00000000 00000000 00000000
000124e5  00000000 00000000 00000000 00000000
000124f5  00000000 00000000 00000000 00000000
00012505  00000000 00000000 00000000 00000000
00012515  00000000 00000000 00000000 00000000
00012525  00000000 00000000 00000000 00000000
00012535  00000000 00000000 00000000 00000000

How do I x/32s things?

If the following is not giving you the expected results:

ds

Use da instead (the 'a' is for ASCII). Refer to Display String for further information.

Where was this pointer allocated? Where was it freed?

Use GFlags to enabled page heap. For example:

"C:\Program Files (x86)\Debugging Tools for Windows (x86)\gflags.exe" -i "C:\path\to\your\binary" +hpa

(gflags.exe with only the -i option will display what debugging features are enabled for the specified binary.)

With page heap enabled, the following command can be used to show when a pointer was allocated, or in the case of freed memory, when it was freed. xxxx represents a memory address, or a register containing the address:

!heap -p -a xxxx

Page heap can be removed by using the previous command, but with -hpa instead of +hpa.

If you are using the 64-bit version of WinDbg to debug a 32-bit process, the !heap command will not work. Install the 32-bit version of WinDbg from the Microsoft Windows Driver Kit (D:\Debuggers\dbg_x86).

I want to know when something reads or writes a specific pointer

You can use break on access commands. For example, the following sets a read and write break on 12345678. If this were a pointer to some memory of interest, the breakpoint would trigger when the pointer is read or written:

ba r4 12345678

Refer to the Break on Access documentation for further information.

How do I view all registers?

To list all registers:

r

To view a specific register, such as rbx:

r rbx

I want to restart the application

.restart

Note that this will remove breakpoints that were not set with bu.

I want to detach from a running process

.detach

How do I view shared libraries and their base addresses?

!address -f:image

I want to see instructions. Is there an x/32i (GDB) or disass (LLDB) equivalent?

u

To start disassembling at a specific address:

u 12345678

How do I view memory permissions?

Is my heap executable? Run the following command to check. It accepts a register (if the register contains a memory address) or an address (such as 12345678), for example:

!vprot rcx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment