WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit d786c07

Browse files
committed
Add context.debugger to select which debugger to use
Allow to choose the debugger to start when using `windbg.attach`. By default it autodetects which debugger is available. You can specify the path to the debuggers using `context.windbg_binary` and `context.windbgx_binary`.
1 parent ea76973 commit d786c07

File tree

3 files changed

+126
-5
lines changed

3 files changed

+126
-5
lines changed

pwnlib/context/__init__.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,9 @@ class ContextType(object):
364364
'endian': 'little',
365365
'gdbinit': "",
366366
'gdb_binary': "",
367+
'windbg_binary': "",
368+
'windbgx_binary': "",
369+
'debugger': "auto",
367370
'kernel': None,
368371
'local_libcdb': "/var/lib/libc-database",
369372
'log_level': logging.INFO,
@@ -453,6 +456,9 @@ class ContextType(object):
453456

454457
valid_signed = sorted(signednesses)
455458

459+
#: Valid values for :attr:`debugger`
460+
debugger_choices = ['auto', 'gdb', 'windbgx', 'windbg']
461+
456462
def __init__(self, **kwargs):
457463
"""
458464
Initialize the ContextType structure.
@@ -1576,6 +1582,60 @@ def gdb_binary(self, value):
15761582
"""
15771583
return str(value)
15781584

1585+
@_validator
1586+
def windbg_binary(self, value):
1587+
"""Path to the binary that is used when running WinDbg locally.
1588+
1589+
This is useful when you have multiple versions of WinDbg installed or the WinDbg binary is
1590+
called something different.
1591+
1592+
Usually, it is installed to ``C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe``.
1593+
Adding the path to the Windows SDK to your PATH variable is recommended.
1594+
1595+
If set to an empty string, pwntools will try to search for a reasonable WinDbg binary from
1596+
the path.
1597+
1598+
Default value is ``""``.
1599+
"""
1600+
return str(value)
1601+
1602+
@_validator
1603+
def windbgx_binary(self, value):
1604+
"""Path to the binary that is used when running WinDbgX locally.
1605+
1606+
This is useful when you have multiple versions of WinDbgX installed or the WinDbgX binary is
1607+
called something different.
1608+
1609+
Usually, it is installed to ``%LocalAppData%\Microsoft\WindowsApps\WinDbgX.exe``.
1610+
1611+
If set to an empty string, pwntools will try to search for a reasonable WinDbgX binary from
1612+
the path.
1613+
1614+
Default value is ``""``.
1615+
"""
1616+
return str(value)
1617+
1618+
@_validator
1619+
def debugger(self, value):
1620+
"""Type of debugger to use when running locally.
1621+
1622+
Possible values are:
1623+
1624+
- ``gdb``: Use GDB as the debugger.
1625+
- ``windbg``: Use WinDbg as the debugger.
1626+
- ``windbgx``: Use WinDbgX as the debugger.
1627+
1628+
Defaults to ``windbgx`` on Windows and ``gdb`` on other platforms.
1629+
1630+
``auto``: Automatically select the available debugger based on the platform.
1631+
On Windows, it will prefer ``windbgx`` over ``windbg`` if both are available.
1632+
1633+
Default value is ``"auto"``.
1634+
"""
1635+
if value not in self.debugger_choices:
1636+
raise AttributeError("debugger must be one of %r" % sorted(self.debugger_choices))
1637+
return str(value)
1638+
15791639
@_validator
15801640
def cyclic_alphabet(self, alphabet):
15811641
"""Cyclic alphabet.

pwnlib/gdb.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,9 @@ def binary():
765765
>>> gdb.binary() # doctest: +SKIP
766766
'/usr/bin/gdb'
767767
"""
768+
if context.debugger not in ('auto', 'gdb'):
769+
log.error('Unsupported debugger: {}'.format(context.debugger))
770+
768771
if context.gdb_binary:
769772
gdb = misc.which(context.gdb_binary)
770773
if not gdb:

pwnlib/windbg.py

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,23 @@
33
target binary under WinDbg. This module provides a simple interface
44
to do so under Windows.
55
6+
By default, :attr:`.context.debugger` is set to ``"auto"``, which will
7+
attempt to automatically select an appropriate debugger based on the
8+
available debuggers on the system.
9+
10+
The order of preference is:
11+
- ``windbgx``
12+
- ``windbg``
13+
14+
If automatic lookup fails, you can manually set :attr:`.context.debugger` to
15+
the debugger of your choice and provide the path to the debugger binary
16+
using :attr:`.context.windbgx_binary` or :attr:`.context.windbg_binary`.
17+
618
Useful Functions
719
----------------
820
921
- :func:`attach` - Attach to an existing process
22+
- :func:`debug` - Start a new process under the debugger
1023
1124
Debugging Tips
1225
--------------
@@ -127,15 +140,60 @@ def debug(args, dbgscript=None, exe=None, env=None, creationflags=0, **kwargs):
127140
def binary():
128141
"""binary() -> str
129142
130-
Returns the path to the WinDbg binary.
143+
Returns the path to the debugger binary depending on the context.
144+
:attr:`.context.debugger` is used to determine which debugger to use.
131145
132146
Returns:
133147
str: Path to the appropriate ``windbg`` binary to use.
134148
"""
135-
windbg = misc.which('windbgx.exe') or misc.which('windbg.exe')
136-
if not windbg:
137-
log.error('windbg is not installed or in system PATH')
138-
return windbg
149+
if context.debugger == 'auto':
150+
for debugger in context.debugger_choices:
151+
with context.local(debugger=debugger, log_level='critical'):
152+
try:
153+
return binary()
154+
except Exception:
155+
pass
156+
else:
157+
log.error('No debugger found. Please set context.debugger to one of: %s\n'
158+
'You might have to specify the path to the debugger binary with context.windbg_binary or context.windbgx_binary.',
159+
', '.join(context.debugger_choices))
160+
161+
if context.debugger == 'windbg':
162+
if context.windbg_binary:
163+
windbg = misc.which(context.windbg_binary)
164+
if not windbg:
165+
log.warn_once('Path to WinDbg binary `{}` not found'.format(context.windbg_binary))
166+
return windbg
167+
168+
windbg = misc.which('windbg.exe')
169+
if not windbg and os.environ.get('ProgramFiles(x86)'):
170+
arch_str = {
171+
'i386': 'x86',
172+
'amd64': 'x64',
173+
'aarch64': 'arm64',
174+
}.get(context.arch)
175+
if not arch_str:
176+
log.error('Unsupported architecture for windbg: {}'.format(context.arch))
177+
windbg = os.path.join(os.environ.get('ProgramFiles(x86)'), 'Windows Kits', '10', 'Debuggers', arch_str, 'windbg.exe')
178+
if not windbg:
179+
log.error('windbg is not installed or in system PATH. You can set context.windbg_binary to specify the path manually.')
180+
return windbg
181+
182+
if context.debugger == 'windbgx':
183+
if context.windbgx_binary:
184+
windbg = misc.which(context.windbgx_binary)
185+
if not windbg:
186+
log.warn_once('Path to WinDbgx binary `{}` not found'.format(context.windbgx_binary))
187+
return windbg
188+
189+
windbg = misc.which('windbgx.exe')
190+
if not windbg and os.environ.get('LocalAppData'):
191+
windbg = os.path.join(os.environ.get('LocalAppData'), 'Microsoft', 'WindowsApps', 'WinDbgX.exe')
192+
if not windbg:
193+
log.error('windbgx is not installed or in system PATH. You can set context.windbgx_binary to specify the path manually.')
194+
return windbg
195+
196+
log.error('Invalid debugger selection: %s', context.debugger)
139197

140198
@LocalContext
141199
def attach(target, dbgscript=None, dbg_args=[]):

0 commit comments

Comments
 (0)