-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Misc run_in_new_terminal improvements. #1261
Conversation
Currently, when a gdb window is opened via gdb.debug(), terminating the main pwntools process leaves the gdb window/process around. It is inconvenient to have to close these leftover gdb windows when iterating on an exploit. Add a kill_at_exit parameter to run_in_new_terminal() which attempts to terminate the command at main process exit. This only works for terminals which do not daemonize, or for tmux, which supports returning the command's PID. This change also removes the special case for closing stdin/stdout/stderr on Mac OS X, as the problem no longer reproduces under tmux 2.8.
|
||
if pid == 0: | ||
# Closing the file descriptors makes everything fail under tmux on OSX. | ||
if platform.system() != 'Darwin': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was added in 60e5a80. I wasn't able to repro on my Mac OS X machine with tmux 2.8, but should be straightforward to add back if it is still an issue.
|
||
if kill_at_exit: | ||
if terminal == 'tmux': | ||
atexit.register(lambda: os.kill(pid, signal.SIGTERM)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could kill the wrong process on PID reuse, but unfortunately these are the APIs we have to work with. Hopefully PID reuse is relatively unlikely to happen during the relatively short lifetime a pwntools script.
@@ -195,10 +197,14 @@ def run_in_new_terminal(command, terminal = None, args = None): | |||
- If X11 is detected (by the presence of the ``$DISPLAY`` environment | |||
variable), ``x-terminal-emulator`` is used. | |||
|
|||
If `kill_at_exit` is :const:`True`, try to close the command/terminal when the | |||
current process exits. This may not work for all terminal types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a little unfortunate that this doesn't work nicely for all terminal types. One way to do it would be to wrap the command in a shell script which dumps its pid to a temp file before execing the command. I didn't want to think too hard about shell escaping, which is why I've settled for making it just work in tmux here. Happy to try out a more general approach if you think it'd be useful though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess that it should work quite ok. For shell escaping, there is an excellent sh_string
module in pwntools, so you don't have to think so hard :)
I don't mind the ordering change (since it's useful both on macOS and when ssh'ed into a remote machine on Linux), but I disagree with the other changes, since they appear to break multiple things. Can we split the other stuff out into a separate PR to discuss?
I'm not sure this code was tested, since it breaks immediately if I try to check out this branch.
If you fix up the import, it throws an exception if the spawned process dies before Python exits.
And on my Mac 10.13.6 with iTerm2 3.2.7 and tmux 2.7 it does not actually kill the spawned process if it is left alive and the interpreter closes |
Will split out next chance I get to poke at this. Just responding quickly to some of the comments for now.
Agreed that defaulting to False makes more sense. For calls which start a gdb window (which currently, is all calls), I like the idea of defaulting to True, or at least making the default behavior configurable.
In my admittedly brief testing, gdb detaches cleanly from the debuggee on SIGTERM (edit: Though perhaps things change due to the use of gdbserver). My expectation is that this change shouldn't introduce any new debuggee orphaning behavior compared to what happens today. The most common case is probably the debuggee terminating once its stdin is closed. (The second most common case is probably buggy challenges which infinite loop when stdin is closed - I can see the argument that it's nice to have a gdb window to kill those with.) I'll do some more testing of this later.
Guilty as charged - removing that import was the single last-moment change that I didn't test, because I saw that misc.py did not have any uses of platform. Little did I know that pwn/init.py relied on the side effect of platform being imported. I did test run_in_new_terminal with tmux though.
I only tested run_in_new_terminal in tmux 2.8, but I guess this would be a good argument for using the terminal-agnostic approach I mentioned. |
The lifetime of the
We may want to use I'd also prefer to use the In any case, I'm down to merge the order-of-preference changes in this PR and add the kill-child-process stuff in another PR. I think it makes more sense to offer it as an option to |
…we detect an X11 terminal. See Gallopsled#1261 for original comments
…we detect an X11 terminal. See #1261 for original comments
6009e75
to
6512e5b
Compare
There is no such thing as rwb in py3 apparently
Summary of changes: