From 216d24875d68e33db9b7d0a14b5924ba4a8b0f87 Mon Sep 17 00:00:00 2001 From: Heap Crash <66139157+heapcrash@users.noreply.github.com> Date: Wed, 3 Mar 2021 16:20:27 -0500 Subject: [PATCH] [run_in_new_terminal] Create a wrapper script automatically if we are given a list or tuple (#1839) * [run_in_new_terminal] Create a wrapper script automatically if we are given a list or tuple * Update CHANGELOG --- CHANGELOG.md | 3 +++ pwnlib/util/misc.py | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4929c0906..f68f161ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ The table below shows which release corresponds to each branch, and what date th - [#1780][1780] Re-add Python2 to the official Dockerfile - [#1941][1941] Disable all Android tests, `pwnlib.adb` is no longer supported in CI - [#1811][1811] Remove unnecessary `pwn.toplevel.__all__` +- [#1839][1839] run_in_new_terminal now creates a runner script if given a list or tuple [1261]: https://github.com/Gallopsled/pwntools/pull/1261 [1695]: https://github.com/Gallopsled/pwntools/pull/1695 @@ -78,8 +79,10 @@ The table below shows which release corresponds to each branch, and what date th [1757]: https://github.com/Gallopsled/pwntools/pull/1757 [1758]: https://github.com/Gallopsled/pwntools/pull/1758 [1780]: https://github.com/Gallopsled/pwntools/pull/1780 + [1941]: https://github.com/Gallopsled/pwntools/pull/1941 [1811]: https://github.com/Gallopsled/pwntools/pull/1811 +[1839]: https://github.com/Gallopsled/pwntools/pull/1839 ## 4.4.0 (`beta`) diff --git a/pwnlib/util/misc.py b/pwnlib/util/misc.py index 191d04b42..c0a0b3317 100644 --- a/pwnlib/util/misc.py +++ b/pwnlib/util/misc.py @@ -10,6 +10,8 @@ import stat import string import subprocess +import sys +import tempfile from pwnlib import atexit from pwnlib.context import context @@ -261,9 +263,26 @@ def run_in_new_terminal(command, terminal=None, args=None, kill_at_exit=True, pr log.error("Cannot use commands with semicolon. Create a script and invoke that directly.") argv += [command] elif isinstance(command, (list, tuple)): - if any(';' in c for c in command): - log.error("Cannot use commands with semicolon. Create a script and invoke that directly.") - argv += list(command) + # Dump the full command line to a temporary file so we can be sure that + # it is parsed correctly, and we do not need to account for shell expansion + script = ''' +#!{executable!s} +import os +os.execve({argv0!r}, {argv!r}, os.environ) +''' + script = script.format(executable=sys.executable, + argv=command, + argv0=which(command[0])) + script = script.lstrip() + + log.debug("Created script for new terminal:\n%s" % script) + + with tempfile.NamedTemporaryFile(delete=False, mode='wt+') as tmp: + tmp.write(script) + tmp.flush() + os.chmod(tmp.name, 0o700) + argv += [tmp.name] + log.debug("Launching a new terminal: %r" % argv)