diff --git a/pwncat/manager.py b/pwncat/manager.py index d01f75a..4354f9a 100644 --- a/pwncat/manager.py +++ b/pwncat/manager.py @@ -590,12 +590,9 @@ class Manager: data = target.platform.channel.recv(4096) if data != b"" and data is not None: - try: - data = target.platform.process_output(data) - sys.stdout.buffer.write(data) - sys.stdout.buffer.flush() - except RawModeExit: - interactive_complete.set() + data = target.platform.process_output(data) + sys.stdout.buffer.write(data) + sys.stdout.buffer.flush() else: interactive_complete.wait(timeout=0.1) @@ -605,6 +602,9 @@ class Manager: # This is a hack to get the interactive loop out of a blocking # read call. The interactive loop will receive a KeyboardInterrupt os.kill(os.getpid(), signal.SIGINT) + except RawModeExit: + interactive_complete.set() + os.kill(os.getpid(), signal.SIGINT) try: self.target.platform.interactive = True diff --git a/pwncat/platform/windows.py b/pwncat/platform/windows.py index 2221bf8..0e02c8b 100644 --- a/pwncat/platform/windows.py +++ b/pwncat/platform/windows.py @@ -13,7 +13,6 @@ processes and open multiple files with this platform. However, you should be careful to cleanup all processes and files prior to return from your method or code as the C2 will not attempt to garbage collect file or proces handles. """ -import os import sys import gzip import json @@ -46,7 +45,7 @@ PWNCAT_WINDOWS_C2_VERSION = "v0.2.1" PWNCAT_WINDOWS_C2_RELEASE_URL = "https://github.com/calebstewart/pwncat-windows-c2/releases/download/{version}/pwncat-windows-{version}.tar.gz" -class PowershellError(Exception): +class PowershellError(PlatformError): """Executing a powershell script caused an error""" def __init__(self, msg): @@ -55,7 +54,7 @@ class PowershellError(Exception): self.message = msg -class ProtocolError(Exception): +class ProtocolError(PlatformError): def __init__(self, code: int, message: str): self.code = code self.message = message @@ -908,7 +907,7 @@ function prompt { transformed = bytearray(b"") has_cr = False - for b in data: + for idx, b in enumerate(data): # Basically, we just transform bare \r to \r\n if has_cr and b != ord("\n"): @@ -924,10 +923,9 @@ function prompt { if INTERACTIVE_END_MARKER[self.interactive_tracker] == b: self.interactive_tracker += 1 if self.interactive_tracker == len(INTERACTIVE_END_MARKER): - # NOTE: this is a dirty hack to trigger the main input thread - # to leave interactive mode, because it's bound in an input call - os.kill(os.getpid(), signal.SIGINT) - raise pwncat.manager.RawModeExit + self.interactive_tracker = 0 + self.channel.unrecv(data[idx + 1 :]) + raise pwncat.util.RawModeExit else: self.interactive_tracker = 0