Skip to content

Commit b9bb255

Browse files
authored
Update gdb.py
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.
1 parent 04f401c commit b9bb255

File tree

1 file changed

+49
-14
lines changed

1 file changed

+49
-14
lines changed

pwnlib/gdb.py

+49-14
Original file line numberDiff line numberDiff line change
@@ -249,31 +249,55 @@ def debug_shellcode(data, gdbscript=None, vma=None, api=False):
249249

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

252+
def _find_python(which):
253+
for py in ["python2.7", "python2", "python", "python3"]:
254+
# python3 os.execve does not support os.exec* with no argv, so it is last resort
255+
found = which(py)
256+
257+
if found is not None:
258+
return found
259+
260+
return None
261+
252262
def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
253263
"""_gdbserver_args(pid=None, path=None, args=None, which=None, env=None) -> list
254264
255265
Sets up a listening gdbserver, to either connect to the specified
256266
PID, or launch the specified binary by its full path.
257267
258268
Arguments:
259-
pid(int): Process ID to attach to
260-
path(str): Process to launch
261-
args(list): List of arguments to provide on the debugger command line
269+
pid(int): Process ID to attach to.
270+
path(str): Process to launch.
271+
args(list): List of arguments to provide on the debugger command line.
262272
which(callaable): Function to find the path of a binary.
273+
env(dict): Dictionary containing the debugged process environment variables.
263274
264275
Returns:
265276
A list of arguments to invoke gdbserver.
266277
"""
267-
if [pid, path, args].count(None) != 2:
268-
log.error("Must specify exactly one of pid, path, or args")
278+
if [path, args, pid].count(None) == 3:
279+
log.error("Must specify at least one of pid, path, or args")
280+
281+
if pid is not None:
282+
if [path, args].count(None) != 2:
283+
log.error("Cannot specify both pid and path or args")
284+
285+
elif path is None:
286+
if args:
287+
path = args[0]
288+
289+
path = packing._need_bytes(path, min_wrong=0x80)
290+
291+
if args is None:
292+
args = [path or str(pid).encode("utf-8")]
293+
269294

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

273-
gdbserver = ''
298+
args = list(map(bytes, args))
274299

275-
if not args:
276-
args = [str(path or pid)]
300+
gdbserver = ''
277301

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

288-
orig_args = args
289-
290312
gdbserver_args = [gdbserver, '--multi']
291313
if context.aslr:
292314
gdbserver_args += ['--no-disable-randomization']
@@ -297,13 +319,26 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
297319
gdbserver_args += ['--once', '--attach']
298320

299321
if env is not None:
300-
env_args = []
322+
env_args = {}
323+
301324
for key in tuple(env):
302325
if key.startswith(b'LD_'): # LD_PRELOAD / LD_LIBRARY_PATH etc.
303-
env_args.append(b'%s=%s' % (key, env.pop(key)))
326+
env_args[key] = env.pop(key)
304327
else:
305-
env_args.append(b'%s=%s' % (key, env[key]))
306-
gdbserver_args += ['--wrapper', 'env', '-i'] + env_args + ['--']
328+
env_args[key] = env[key]
329+
330+
python = _find_python(which)
331+
332+
gdbserver_args += ['--wrapper', '%s -c "import os; os.execvpe(%s, %s, %s)"' % (python, bytes(path), args, env_args)] + ['--']
333+
334+
elif not args or path != args[0]:
335+
python = _find_python(which)
336+
337+
gdbserver_args += ['--wrapper', '%s -c "import os; os.execvp(%s, %s)"' % (python, bytes(path), args)] + ['--']
338+
339+
if not args:
340+
# gdbserver won't start with no arguments supplied, so pass some dummy args in order to satisfy it.
341+
args += ["dummy_arg"]
307342

308343
gdbserver_args += ['localhost:0']
309344
gdbserver_args += args

0 commit comments

Comments
 (0)