pwnlib.windbg — Working with WinDbg
During exploit development, it is frequently useful to debug the target binary under WinDbg. This module provides a simple interface to do so under Windows.
By default, context.debugger is set to "auto", which will
attempt to automatically select an appropriate debugger based on the
available debuggers on the system.
The order of preference is:
- windbgx
- windbg
If automatic lookup fails, you can manually set context.debugger to
the debugger of your choice and provide the path to the debugger binary
using context.windbgx_binary or context.windbg_binary.
Useful Functions
Debugging Tips
The attach() and debug() functions will likely be your bread and
butter for debugging.
Both allow you to provide a script to pass to WinDbg when it is started, so that it can automatically set your breakpoints.
Attaching to Processes
To attach to an existing process, just use attach(). You can pass a PID,
a process name (including file extension), or a process.
Spawning New Processes
Attaching to processes with attach() is useful, but the state the process
is in may vary. If you need to attach to a process very early, and debug it from
the very first instruction (or even the start of main), you instead should use
debug().
When you use debug(), the return value is a tube object
that you interact with exactly like normal.
Tips and Troubleshooting
NOPTRACE magic argument
It’s quite cumbersom to comment and un-comment lines containing attach.
You can cause these lines to be a no-op by running your script with the
NOPTRACE argument appended, or with PWNLIB_NOPTRACE=1 in the environment.
(The name is borrowed from ptrace syscall on Linux.)
$ python exploit.py NOPTRACE
[+] Starting local process 'chall.exe': Done
[!] Skipping debug attach since context.noptrace==True
...
Member Documentation
- pwnlib.windbg.attach(target, dbgscript=None, dbg_args=[]) int[source]
Attach to a running process with WinDbg.
- Parameters:
- Returns:
int – PID of the debugger process.
Notes
The
targetargument is very robust, and can be any of the following:Examples
Attach to a process by PID
>>> pid = windbg.attach(1234)
Attach to the youngest process by name
>>> pid = windbg.attach('cmd.exe')
Attach a debugger to a
processtube and automate interaction>>> io = process('cmd') >>> pid = windbg.attach(io, dbgscript=''' ... bp kernelbase!WriteFile ... g ... ''')
- pwnlib.windbg.binary() str[source]
Returns the path to the debugger binary depending on the context.
context.debuggeris used to determine which debugger to use.- Returns:
str – Path to the appropriate
windbgbinary to use.
- pwnlib.windbg.debug(args, dbgscript=None, exe=None, env=None, creationflags=0) tube[source]
Launch a process in suspended state, attach debugger and resume process.
- Parameters:
- Returns:
process– A tube connected to the target process.
Notes
When the debugger opens via
debug(), it will initially be stopped on the very first instruction of the entry point.