Skip to content

Commit

Permalink
Update gdb.py
Browse files Browse the repository at this point in the history
before this commit, it was not was possible to specify `argv[0]` using `gdb.debug`, nor run the program with `argc = 0` (see for example Gallopsled#1273)

this commit adds support for specifying both `argv` and `exe`, thus allowing further customization of the provided arguments.
  • Loading branch information
giladreti authored Jan 26, 2022
1 parent 04f401c commit 29b7ecf
Showing 1 changed file with 46 additions and 14 deletions.
60 changes: 46 additions & 14 deletions pwnlib/gdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,31 +249,52 @@ def debug_shellcode(data, gdbscript=None, vma=None, api=False):

return debug(tmp_elf, gdbscript=gdbscript, arch=context.arch, api=api)

def _find_python(which):
for py in ["python2.7", "python2", "python", "python3"]:
# python3 os.execve does not support os.exec* with no argv, so it is last resort
found = which(py)

if found is not None:
return found

return None

def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
"""_gdbserver_args(pid=None, path=None, args=None, which=None, env=None) -> list
Sets up a listening gdbserver, to either connect to the specified
PID, or launch the specified binary by its full path.
Arguments:
pid(int): Process ID to attach to
path(str): Process to launch
args(list): List of arguments to provide on the debugger command line
pid(int): Process ID to attach to.
path(str): Process to launch.
args(list): List of arguments to provide on the debugger command line.
which(callaable): Function to find the path of a binary.
env(dict): Dictionary containing the debugged process environment variables.
Returns:
A list of arguments to invoke gdbserver.
"""
if [pid, path, args].count(None) != 2:
log.error("Must specify exactly one of pid, path, or args")
if pid is not None:
if [path, args].count(None) != 2:
log.error("Cannot specify both pid and path or args")

elif path is None:
if args:
path = args[0]

path = packing._need_bytes(path, min_wrong=0x80)

if args is None:
args = [path or str(pid).encode("utf-8")]


if not which:
log.error("Must specify which.")

gdbserver = ''
args = list(map(bytes, args))

if not args:
args = [str(path or pid)]
gdbserver = ''

# Android targets have a distinct gdbserver
if context.bits == 64:
Expand All @@ -285,8 +306,6 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
if not gdbserver:
log.error("gdbserver is not installed")

orig_args = args

gdbserver_args = [gdbserver, '--multi']
if context.aslr:
gdbserver_args += ['--no-disable-randomization']
Expand All @@ -297,13 +316,26 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
gdbserver_args += ['--once', '--attach']

if env is not None:
env_args = []
env_args = {}

for key in tuple(env):
if key.startswith(b'LD_'): # LD_PRELOAD / LD_LIBRARY_PATH etc.
env_args.append(b'%s=%s' % (key, env.pop(key)))
env_args[key] = env.pop(key)
else:
env_args.append(b'%s=%s' % (key, env[key]))
gdbserver_args += ['--wrapper', 'env', '-i'] + env_args + ['--']
env_args[key] = env[key]

python = _find_python(which)

gdbserver_args += ['--wrapper', '%s -c "import os; os.execvpe(%s, %s, %s)"' % (python, bytes(path), args, env_args)] + ['--']

elif not args or path != args[0]:
python = _find_python(which)

gdbserver_args += ['--wrapper', '%s -c "import os; os.execvp(%s, %s)"' % (python, bytes(path), args)] + ['--']

if not args:
# gdbserver won't start with no arguments supplied, so pass some dummy args in order to satisfy it.
args += ["dummy_arg"]

gdbserver_args += ['localhost:0']
gdbserver_args += args
Expand Down

0 comments on commit 29b7ecf

Please sign in to comment.