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.

Useful Functions

  • attach() - Attach to an existing process

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, windbgscript=None, windbg_args=[]) int[source]

Attach to a running process with WinDbg.

Parameters
  • target (int, str, process) – Process to attach to.

  • windbgscript (str, list) – WinDbg script to run after attaching.

  • windbg_args (list) – Additional arguments to pass to WinDbg.

Returns

int – PID of the WinDbg process.

Notes

The target argument is very robust, and can be any of the following:

int

PID of a process

str

Process name. The youngest process is selected.

process

Process to connect to

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 process tube and automate interaction

>>> io = process('cmd') 
>>> pid = windbg.attach(io, windbgscript='''
... bp kernelbase!WriteFile
... g
... ''') 
pwnlib.windbg.binary() str[source]

Returns the path to the WinDbg binary.

Returns

str – Path to the appropriate windbg binary to use.

pwnlib.windbg.debug(args, windbgscript=None, exe=None, env=None, creationflags=0) tube[source]

Launch a process in suspended state, attach debugger and resume process.

Parameters
  • args (list) – Arguments to the process, similar to process.

  • windbgscript (str) – windbg script to run.

  • exe (str) – Path to the executable on disk.

  • env (dict) – Environment to start the binary in.

  • creationflags (int) – Flags to pass to process.process().

Returns

process – A tube connected to the target process.

Notes

When WinDbg opens via debug(), it will initially be stopped on the very first instruction of the entry point.