diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c34af282..0a15d8f23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,8 +75,10 @@ The table below shows which release corresponds to each branch, and what date th ## 5.0.0 (`dev`) - [#2507][2507] Add `+LINUX` and `+WINDOWS` doctest options and start proper testing on Windows +- [#2522][2522] Support starting a kitty debugging window with the 'kitten' command [2507]: https://github.com/Gallopsled/pwntools/pull/2507 +[2522]: https://github.com/Gallopsled/pwntools/pull/2522 ## 4.15.0 (`beta`) - [#2508][2508] Ignore a warning when compiling with asm on nix diff --git a/pwnlib/util/misc.py b/pwnlib/util/misc.py index f2e111edd..58739c151 100644 --- a/pwnlib/util/misc.py +++ b/pwnlib/util/misc.py @@ -1,5 +1,6 @@ from __future__ import division +import json import base64 import errno import os @@ -450,13 +451,11 @@ def run_in_new_terminal(command, terminal=None, args=None, kill_at_exit=True, pr log.debug("Launching a new terminal: %r" % argv) stdin = stdout = stderr = open(os.devnull, 'r+b') - if terminal == 'tmux' or terminal == 'kitty': + if terminal == 'tmux' or terminal in ('kitty', 'kitten'): stdout = subprocess.PIPE p = subprocess.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn) - kittyid = None - if terminal == 'tmux': out, _ = p.communicate() try: @@ -469,9 +468,8 @@ def run_in_new_terminal(command, terminal=None, args=None, kill_at_exit=True, pr with subprocess.Popen((qdbus, konsole_dbus_service, '/Sessions/{}'.format(last_konsole_session), 'org.kde.konsole.Session.processId'), stdout=subprocess.PIPE) as proc: pid = int(proc.communicate()[0].decode()) - elif terminal == 'kitty': - pid = p.pid - + elif terminal in ('kitty', 'kitten'): + pid = None out, _ = p.communicate() try: kittyid = int(out) @@ -479,6 +477,15 @@ def run_in_new_terminal(command, terminal=None, args=None, kill_at_exit=True, pr kittyid = None if kittyid is None: log.error("Could not parse kitty window ID from output (%r)", out) + else: + lsout, _ = subprocess.Popen(["kitten", "@", "ls", "--match", "id:%d" % kittyid], stdin=stdin, stdout=stdout, stderr=stderr).communicate() + try: + lsj = json.loads(lsout) + pid = int(lsj[0]["tabs"][0]["windows"][0]["pid"]) + except json.JSONDecodeError as e: + pid = None + log.error("Json decode failed while parsing 'kitten @ ls' output (%r) (error: %r)", lsout, e) + elif terminal == 'cmd.exe': # p.pid is cmd.exe's pid instead of the WSL process we want to start eventually. # I don't know how to trace the execution through Windows and back into the WSL2 VM. @@ -503,8 +510,6 @@ def kill(): try: if terminal == 'qdbus': os.kill(pid, signal.SIGHUP) - elif terminal == 'kitty': - subprocess.Popen(["kitten", "@", "close-window", "--match", "id:{}".format(kittyid)], stderr=stderr) else: os.kill(pid, signal.SIGTERM) except OSError: