@@ -249,31 +249,55 @@ def debug_shellcode(data, gdbscript=None, vma=None, api=False):
249
249
250
250
return debug (tmp_elf , gdbscript = gdbscript , arch = context .arch , api = api )
251
251
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
+
252
262
def _gdbserver_args (pid = None , path = None , args = None , which = None , env = None ):
253
263
"""_gdbserver_args(pid=None, path=None, args=None, which=None, env=None) -> list
254
264
255
265
Sets up a listening gdbserver, to either connect to the specified
256
266
PID, or launch the specified binary by its full path.
257
267
258
268
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.
262
272
which(callaable): Function to find the path of a binary.
273
+ env(dict): Dictionary containing the debugged process environment variables.
263
274
264
275
Returns:
265
276
A list of arguments to invoke gdbserver.
266
277
"""
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
+
269
294
270
295
if not which :
271
296
log .error ("Must specify which." )
272
297
273
- gdbserver = ''
298
+ args = list ( map ( bytes , args ))
274
299
275
- if not args :
276
- args = [str (path or pid )]
300
+ gdbserver = ''
277
301
278
302
# Android targets have a distinct gdbserver
279
303
if context .bits == 64 :
@@ -285,8 +309,6 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
285
309
if not gdbserver :
286
310
log .error ("gdbserver is not installed" )
287
311
288
- orig_args = args
289
-
290
312
gdbserver_args = [gdbserver , '--multi' ]
291
313
if context .aslr :
292
314
gdbserver_args += ['--no-disable-randomization' ]
@@ -297,13 +319,26 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
297
319
gdbserver_args += ['--once' , '--attach' ]
298
320
299
321
if env is not None :
300
- env_args = []
322
+ env_args = {}
323
+
301
324
for key in tuple (env ):
302
325
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 )
304
327
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" ]
307
342
308
343
gdbserver_args += ['localhost:0' ]
309
344
gdbserver_args += args
0 commit comments