From 267061517a7e13d1b3cc8f1dc54c295607cb059d Mon Sep 17 00:00:00 2001 From: cytopia Date: Fri, 29 May 2020 23:19:35 +0200 Subject: [PATCH 01/61] Bump version --- CHANGELOG.md | 3 +++ bin/pwncat | 2 +- setup.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd85ff1a..c5aa7b3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ## Unreleased +## Release 0.1.0 + + ## Release 0.0.23-alpha ### Fixed diff --git a/bin/pwncat b/bin/pwncat index dbe9d962..e6fb2562 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -127,7 +127,7 @@ if os.environ.get("MYPY_CHECK", False): APPNAME = "pwncat" APPREPO = "https://github.com/cytopia/pwncat" -VERSION = "0.0.23-alpha" +VERSION = "0.1.0" # Default timeout for timeout-based sys.stdin and socket.recv TIMEOUT_READ_STDIN = 0.1 diff --git a/setup.py b/setup.py index a81d743c..a4d96b3d 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name="pwncat", - version="0.0.23-alpha", + version="0.1.0", description="Netcat on steroids with Firewall, IDS/IPS evasion, bind and reverse shell and port forwarding magic - and its fully scriptable with Python (PSE).", license="MIT", long_description=long_description, From 0d66fbeca3ad60bd8f53377e30b96ef463f1491e Mon Sep 17 00:00:00 2001 From: cytopia Date: Fri, 29 May 2020 23:21:18 +0200 Subject: [PATCH 02/61] Fixes UTF-8 char handling --- CHANGELOG.md | 4 ++++ bin/pwncat | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5aa7b3f..6b7119a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,10 @@ ## Release 0.0.22-alpha +## Fixes +- Fixes UTF-8 char conversion + + ### Added - Feature: Rebind forever: `--rebind`: #44 - Feature: Wait between rebind attempts: `--rebind-wait`: #45 diff --git a/bin/pwncat b/bin/pwncat index e6fb2562..a9f662d9 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -1014,7 +1014,12 @@ class StringEncoder(object): return data.encode(self.__codec) except UnicodeEncodeError: # TODO: Add logging - return data.encode(self.__fallback) + try: + return data.encode(self.__fallback) + except UnicodeEncodeError: + # TODO: Add logging + return data.encode("utf-8") + return data # type: ignore def decode(self, data): From bcf259c5219a300315f9076c6e36fc58fcf359c3 Mon Sep 17 00:00:00 2001 From: cytopia Date: Fri, 29 May 2020 23:23:56 +0200 Subject: [PATCH 03/61] Fix pydoc return statement --- bin/pwncat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/pwncat b/bin/pwncat index a9f662d9..b59a3997 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -1546,7 +1546,7 @@ class Sock(_Singleton("SingletonMeta", (object,), {})): # type: ignore fstop (Callable[[], bool]): A function that returns True if abort is requested. Returns: - socket.socket: Returns the connection socket (whatever protocol was faster). + (socket.socket, str, int): Returns tuple of socket, address and port of client. Raises: socket.error: Raised if server cannot accept connection or stop signal is requested. From 539995c5187275a2e04b52098b7679bf9d69c11f Mon Sep 17 00:00:00 2001 From: cytopia Date: Fri, 29 May 2020 23:24:59 +0200 Subject: [PATCH 04/61] Fix send byte calculation --- bin/pwncat | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/pwncat b/bin/pwncat index b59a3997..67c940c3 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -1798,9 +1798,8 @@ class Net(object): curr = 0 # bytes send during one loop iteration send = 0 # total bytes send - size = len(data) # bytes of data that needs to be send byte = self.__enc.encode(data) - assert size == len(byte), "Encoding messed up string length, might need to do len() after." + size = len(byte) # bytes of data that needs to be send # Loop until all bytes have been send # TODO: Does this make it impossible to send nullbytes (Ctrl+d) From a78d1e6a32bd321470fcb3efb362d1352c31e485 Mon Sep 17 00:00:00 2001 From: cytopia Date: Fri, 29 May 2020 23:29:37 +0200 Subject: [PATCH 05/61] Adjust timings and comments --- bin/pwncat | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/bin/pwncat b/bin/pwncat index 67c940c3..8c9036d1 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -1802,7 +1802,6 @@ class Net(object): size = len(byte) # bytes of data that needs to be send # Loop until all bytes have been send - # TODO: Does this make it impossible to send nullbytes (Ctrl+d) while send < size: self.__log.debug( "Trying to send %d bytes to %s:%d", @@ -1850,7 +1849,7 @@ class Net(object): socket.timeout: Except here to do an action when the socket is not busy. AttributeError: Except here when current instance has closed itself (Ctrl+c). socket.error: Except here when unconnected or connection was forcibly closed. - EOFError: Except here when upstream has closed the connection. + EOFError: Except here when upstream has closed the connection via EOF. """ # This is required for a UDP server that has no connected clients yet # and is waiting for data receival for the first time on either IPv4 or IPv6 @@ -1866,9 +1865,9 @@ class Net(object): 0 ] # type: List[socket.socket] # E.g.: ValueError: file descriptor cannot be a negative integer (-1) - except (ValueError, AttributeError): - msg = "Connection was closed by self." - self.__log.warning(msg) + except (ValueError, AttributeError) as error: + msg = "Connection was closed by self: [1]: {}".format(error) + self.__log.debug(msg) raise AttributeError(msg) if not conns: # This is raised for the calling function to determine what to do @@ -1883,9 +1882,9 @@ class Net(object): (byte, addr) = conn.recvfrom(self.__options.bufsize) # [1/5] When closing itself (e.g.: via Ctrl+c and the socket_close() funcs are called) - except AttributeError: - msg = "Connection was closed by self." - self.__log.warning(msg) + except AttributeError as error: + msg = "Connection was closed by self: [2]: {}".format(error) + self.__log.debug(msg) raise AttributeError(msg) # [2/5] Connection was forcibly closed @@ -1900,7 +1899,7 @@ class Net(object): # In TCP, there is no such thing as an empty message, so zero means a peer disconnect. # In UDP, there is no such thing as a peer disconnect, so zero means an empty datagram. if not byte: - msg = "Upstream has closed the connection." + msg = "EOF: Remote finished sending." self.__log.info(msg) raise EOFError(msg) @@ -2890,7 +2889,7 @@ class IONetworkScanner(IO): return self.__sock.create_socket(family, socket.SOCK_DGRAM) return self.__sock.create_socket(family, socket.SOCK_STREAM) except socket.error: - time.sleep(0.1) + time.sleep(0.1) # This can be bigger to give the system some time to release fd's def __get_banner_version(self, banner): # type: (str) -> Optional[str] @@ -2931,13 +2930,12 @@ class IONetworkScanner(IO): sock.send(self.__enc.encode(payload)) self.__log.debug("%s:%d - payload sent: %s", addr, port, repr(payload)) - sock.settimeout(0.1) + sock.settimeout(0.5) banner = sock.recv(self.__sock_opts.bufsize) version = self.__get_banner_version(self.__enc.decode(banner)) self.__log.debug("%s:%d - respone received: %s", addr, port, repr(banner)) return (True, version) except socket.timeout: - time.sleep(0.1) continue except (OSError, socket.error): return (False, None) @@ -3582,7 +3580,7 @@ class Runner(object): thread.start() break except (RuntimeError, Exception): # pylint: disable=broad-except - time.sleep(0.1) + time.sleep(0.1) # This can be big to give the system some time to release fd's self.__threads[key] = thread # Start available timers in a thread for key in self.__timers: From 497130794696ed4bfc7d424148ad42c763e6af39 Mon Sep 17 00:00:00 2001 From: cytopia Date: Sat, 30 May 2020 00:24:24 +0200 Subject: [PATCH 06/61] Fix encoding/decoding for Python3 --- bin/pwncat | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/bin/pwncat b/bin/pwncat index 8c9036d1..3ef0b56f 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -1000,8 +1000,11 @@ class StringEncoder(object): self.__py3 = sys.version_info >= (3, 0) # type: bool # https://stackoverflow.com/questions/606191/27527728#27527728 - self.__codec = "cp437" - self.__fallback = "latin-1" + self.__codecs = [ + "utf-8", + "cp437", + "latin-1", + ] # -------------------------------------------------------------------------- # Public Functions @@ -1010,23 +1013,24 @@ class StringEncoder(object): # type: (str) -> bytes """Convert string into a byte type for Python3.""" if self.__py3: - try: - return data.encode(self.__codec) - except UnicodeEncodeError: - # TODO: Add logging + for codec in self.__codecs: try: - return data.encode(self.__fallback) + return data.encode(codec) except UnicodeEncodeError: - # TODO: Add logging - return data.encode("utf-8") - + pass + raise UnicodeEncodeError(self.__codecs[-1], "Unable to encode", data, 0, len(data)-1) return data # type: ignore def decode(self, data): # type: (bytes) -> str """Convert bytes into a string type for Python3.""" if self.__py3: - return data.decode(self.__codec) + for codec in self.__codecs: + try: + return data.decode(codec) + except UnicodeDecodeError: + pass + raise UnicodeDecodeError(self.__codecs[-1], "Unable to encode", data, 0, len(data)-1) return data # type: ignore def base64_encode(self, data): From 4594b3765b509c2e4ba9f879fad5452683bcfddf Mon Sep 17 00:00:00 2001 From: cytopia Date: Mon, 1 Jun 2020 19:02:21 +0200 Subject: [PATCH 07/61] Implement signal handler --- bin/pwncat | 762 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 496 insertions(+), 266 deletions(-) diff --git a/bin/pwncat b/bin/pwncat index 3ef0b56f..854b9755 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -9,7 +9,7 @@ # 4. Transformer # 5. IO modules # 6. PSE Store -# 7. IO Runner +# 7. IO Runner / InterruptHandler # 8. Command & Control # 9. Command line arguments # 10. Main entrypoint @@ -49,7 +49,7 @@ # # 4. Signaling / Interrupts # ------------------------------------ -# The StopSignal instance is distributed across all Threads and and the Runner instance and +# The InterruptHandler instance is distributed across all Threads and and the Runner instance and # is a way to let other Threads know that a stop signal has been requested. # Producer/Consumer can implement their own interrupt function so they can be stopped from # inside (if they do non-blocking stuff) or from outside (if they do blocking stuff). @@ -63,12 +63,12 @@ from subprocess import Popen from subprocess import STDOUT import argparse -import atexit import base64 import logging import os import re import select +import signal import socket import sys import threading @@ -130,9 +130,9 @@ APPREPO = "https://github.com/cytopia/pwncat" VERSION = "0.1.0" # Default timeout for timeout-based sys.stdin and socket.recv -TIMEOUT_READ_STDIN = 0.1 -TIMEOUT_RECV_SOCKET = 0.1 -TIMEOUT_RECV_SOCKET_RETRY = 2 +TIMEOUT_READ_STDIN = 0.05 +TIMEOUT_RECV_SOCKET = 0.05 +TIMEOUT_RECV_SOCKET_RETRY = 1 # https://docs.python.org/3/library/subprocess.html#popen-constructor # * 0 means unbuffered (read and write are one system call and can return short) @@ -332,10 +332,10 @@ class DsRunnerTimer(object): return self.__kwargs @property - def signal(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance.""" - return self.__signal + def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig # -------------------------------------------------------------------------- # Constructor @@ -343,7 +343,7 @@ class DsRunnerTimer(object): def __init__( self, action, # type: Callable[..., None] - signal, # type: StopSignal + ssig, # type: InterruptHandler intvl, # type: int *args, # type: Tuple[Any, ...] **kwargs # type: Dict[str, Any] @@ -352,7 +352,7 @@ class DsRunnerTimer(object): assert type(intvl) is int, type(intvl) assert type(kwargs) is dict, type(kwargs) self.__action = action - self.__signal = signal + self.__ssig = ssig self.__intvl = intvl self.__args = args self.__kwargs = kwargs @@ -398,10 +398,10 @@ class DsRunnerRepeater(object): return self.__kwargs @property - def signal(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance.""" - return self.__signal + def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig # -------------------------------------------------------------------------- # Constructor @@ -409,7 +409,7 @@ class DsRunnerRepeater(object): def __init__( self, action, # type: Callable[..., None] - signal, # type: StopSignal + ssig, # type: InterruptHandler repeat, # type: int pause, # type: float *args, # type: Tuple[Any, ...] @@ -420,7 +420,7 @@ class DsRunnerRepeater(object): assert type(pause) is float, type(pause) assert type(kwargs) is dict, type(kwargs) self.__action = action - self.__signal = signal + self.__ssig = ssig self.__repeat = repeat self.__pause = pause self.__args = args @@ -765,8 +765,8 @@ class DsTransformSafeword(object): # -------------------------------------------------------------------------- @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance to trigger a shutdown signal.""" + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance to trigger a shutdown signal.""" return self.__ssig @property @@ -779,7 +779,7 @@ class DsTransformSafeword(object): # Constructor # -------------------------------------------------------------------------- def __init__(self, ssig, safeword): - # type: (StopSignal, str) -> None + # type: (InterruptHandler, str) -> None super(DsTransformSafeword, self).__init__() self.__ssig = ssig self.__safeword = safeword @@ -869,7 +869,7 @@ class DsIOCommand(object): # ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (1/4) TraceLogger +# [3/11 LIBRARY CLASSES]: (1/3) TraceLogger # ------------------------------------------------------------------------------------------------- class TraceLogger(logging.getLoggerClass()): # type: ignore """Extend Python's default logger class with TRACE level logging.""" @@ -909,7 +909,7 @@ class TraceLogger(logging.getLoggerClass()): # type: ignore # ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (2/4) ColoredLogFormatter +# [3/11 LIBRARY CLASSES]: (2/3) ColoredLogFormatter # ------------------------------------------------------------------------------------------------- class ColoredLogFormatter(logging.Formatter): """Custom log formatter which adds different details and color support.""" @@ -982,7 +982,7 @@ class ColoredLogFormatter(logging.Formatter): # ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (3/4) StringEncoder +# [3/11 LIBRARY CLASSES]: (3/3) StringEncoder # ------------------------------------------------------------------------------------------------- class StringEncoder(object): """Takes care about Python 2/3 string encoding/decoding. @@ -1014,11 +1014,13 @@ class StringEncoder(object): """Convert string into a byte type for Python3.""" if self.__py3: for codec in self.__codecs: + # On the last codec, do not catch the exception and let it trigger if it fails + if self.__codecs[-1] == codec: + return data.encode(codec) try: return data.encode(codec) except UnicodeEncodeError: pass - raise UnicodeEncodeError(self.__codecs[-1], "Unable to encode", data, 0, len(data)-1) return data # type: ignore def decode(self, data): @@ -1026,11 +1028,13 @@ class StringEncoder(object): """Convert bytes into a string type for Python3.""" if self.__py3: for codec in self.__codecs: + # On the last codec, do not catch the exception and let it trigger if it fails + if self.__codecs[-1] == codec: + return data.decode(codec) try: return data.decode(codec) except UnicodeDecodeError: pass - raise UnicodeDecodeError(self.__codecs[-1], "Unable to encode", data, 0, len(data)-1) return data # type: ignore def base64_encode(self, data): @@ -1039,34 +1043,6 @@ class StringEncoder(object): return self.decode(base64.b64encode(self.encode(data))) -# ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (4/4): StopSignal -# ------------------------------------------------------------------------------------------------- -class StopSignal(object): - """Provide a simple boolean switch.""" - - # -------------------------------------------------------------------------- - # Constructor - # -------------------------------------------------------------------------- - def __init__(self): - # type: () -> None - """Create a StopSignal instance.""" - self.__stop = False - - # -------------------------------------------------------------------------- - # Public Functions - # -------------------------------------------------------------------------- - def has_stop(self): - # type: () -> bool - """Check if a stop signal has been raised.""" - return self.__stop - - def raise_stop(self): - # type: () -> None - """Raise a stop signal.""" - self.__stop = True - - # ################################################################################################# # ################################################################################################# # ### @@ -1539,15 +1515,21 @@ class Sock(_Singleton("SingletonMeta", (object,), {})): # type: ignore self.__log.error(msg) raise socket.error(msg) - def accept(self, sockets, fstop): - # type: (List[socket.socket], Callable[[], bool]) -> Tuple[socket.socket, Tuple[str, int]] + def accept( + self, + sockets, # type: List[socket.socket] + has_quit, # type: Callable[[], bool] + select_timeout=0.01, # type: float + ): + # type: (...) -> Tuple[socket.socket, Tuple[str, int]] """Accept a single connection from given list of sockets. Given sockets must be bound to an addr and listening for connections. Args: sock ([socket.socket]): List of sockets IPv4 and/or IPv6 to accept on. - fstop (Callable[[], bool]): A function that returns True if abort is requested. + has_quit (Callable[[], bool]): A function that returns True if abort is requested. + select_timeout (float): Timeout to poll sockets for connected clients. Returns: (socket.socket, str, int): Returns tuple of socket, address and port of client. @@ -1557,9 +1539,11 @@ class Sock(_Singleton("SingletonMeta", (object,), {})): # type: ignore """ self.__log.debug("Waiting for TCP client") while True: - ssockets = select.select(sockets, [], [], 0.01)[0] # type: List[socket.socket] - if fstop(): - raise socket.error("StopSignal acknknowledged") + ssockets = select.select(sockets, [], [], select_timeout)[ + 0 + ] # type: List[socket.socket] + if has_quit(): + raise socket.error("SOCK-QUIT signal ACK for accept(): raised socket.error()") for sock in ssockets: try: conn, addr = sock.accept() @@ -1597,13 +1581,18 @@ class Sock(_Singleton("SingletonMeta", (object,), {})): # type: ignore port (int): Port of server to connect to. Returns: - Tuple[str,int]: Adress/port tuple of local bin of the client. + Tuple[str,int]: Adress/port tuple of local bind of the client. Raises: socker.error: If client cannot connect to remote peer or custom bind did not succeed. """ - sock_family_name = self.get_family_name(sock.family) - sock_type_name = self.get_type_name(sock.type) + try: + # If the socket was already closed elsewhere, it won't have family or type anymore + sock_family_name = self.get_family_name(sock.family) + sock_type_name = self.get_type_name(sock.type) + except AttributeError as error: + raise socket.error(error) + # Bind to a custom addr/port if src_addr is not None and src_port is not None: try: @@ -1704,12 +1693,12 @@ class Net(object): # Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, encoder, ssig, options): - # type: (StringEncoder, StopSignal, DsSock) -> None + # type: (StringEncoder, InterruptHandler, DsSock) -> None """Instantiate Sock class. Args: encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). - ssig (StopSignal): Used to stop blocking loops. + ssig (InterruptHandler): Used to stop blocking loops. options (DsSock): Instance of DsSock. """ self.__log = logging.getLogger(__name__) # type: logging.Logger @@ -1787,6 +1776,9 @@ class Net(object): Returns: int: Returns total bytes sent. + + Raises: + socket.error: Except here when unconnected or connection was forcibly closed. """ # UDP has some specialities as its socket is unconnected. # See also recv() for specialities on that side. @@ -1798,6 +1790,11 @@ class Net(object): if not self.__active: self.__log.warning("UDP client has not yet connected. Queueing message") while not self.__active: + if self.__ssig.has_sock_quit(): + self.__log.trace( # type: ignore + "SOCK-QUIT signal ACK in Net.send (while waiting for UDP client)" + ) + return -1 time.sleep(0.01) curr = 0 # bytes send during one loop iteration @@ -1837,9 +1834,9 @@ class Net(object): self.__active["remote_port"], size - send, ) - except (OSError, socket.error) as error: - self.__log.error("Socket OS Error: %s", error) - return send + except (BrokenPipeError, OSError, socket.error) as error: + msg = "Socket send Error: {}".format(error) + raise socket.error(msg) return send def receive(self): @@ -1896,7 +1893,7 @@ class Net(object): # [Errno 10054] An existing connection was forcibly closed by the remote host # [WinError 10054] An existing connection was forcibly closed by the remote host except (OSError, socket.error) as error: - self.__log.warning("Connection error: %s", error) + self.__log.debug("Connection error: %s", error) raise socket.error(error) # [3/5] Upstream (server or client) is gone. @@ -2178,24 +2175,27 @@ class Net(object): return False # (2/3) Accept + remove = {} try: conn, client = self.__sock.accept( - [conns[family]["sock"] for family in conns], self.__ssig.has_stop + [conns[family]["sock"] for family in conns], self.__ssig.has_sock_quit ) conns[conn.family]["conn"] = conn conns[conn.family]["remote_addr"] = client[0] conns[conn.family]["remote_port"] = client[1] except socket.error as err: - # On error, remove all bind sockets - for family in conns: - self.__log.debug( - "Removing (family %d/%s) due to: %s", - family, - self.__sock.get_family_name(family), - err, - ) - self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) - del conns[family] + remove = {family: str(err) for family in conns} + # On error, remove all bind sockets + for family in remove: + self.__log.debug( + "Removing (family %d/%s) due to: %s", + family, + self.__sock.get_family_name(family), + remove[family], + ) + self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) + del conns[family] + if not conns: return False # (3/3) Store connections @@ -2228,7 +2228,7 @@ class Net(object): # [2/3] Accept try: conn, client = self.__sock.accept( - [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_stop + [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_sock_quit ) except socket.error: return False @@ -2415,8 +2415,8 @@ class TransformSafeword(Transform): str: The string as it is without changes """ if self.__opts.safeword in data: - self.__log.info("Received safeword: raising stop signal.") - self.__opts.ssig.raise_stop() + self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore + self.__opts.ssig.raise_terminate() return data @@ -2452,8 +2452,8 @@ class IO(ABC): # type: ignore # -------------------------------------------------------------------------- @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: Read only property to provide a StopSignal instance to IO.""" + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" return self.__ssig @property @@ -2467,11 +2467,11 @@ class IO(ABC): # type: ignore # -------------------------------------------------------------------------- @abstractmethod def __init__(self, ssig): - # type: (StopSignal) -> None + # type: (InterruptHandler) -> None """Set specific options for this IO module. Args: - ssig (StopSignal): StopSignal instance used by the interrupter. + ssig (InterruptHandler): InterruptHandler instance used by the interrupter. """ super(IO, self).__init__() self.__ssig = ssig @@ -2509,8 +2509,6 @@ class IO(ABC): # type: ignore Various producer might call blocking functions and they won't be able to stop themself as they hang on that blocking function. NOTE: This method is triggered from outside and is supposed to stop/shutdown the producer. - - You should at least implement it with "self.ssig.raise_stop()" """ @@ -2525,7 +2523,7 @@ class IONetwork(IO): # -------------------------------------------------------------------------- def __init__( self, - ssig, # type: StopSignal + ssig, # type: InterruptHandler encoder, # type: StringEncoder host, # type: str ports, # type: List[int] @@ -2538,7 +2536,7 @@ class IONetwork(IO): """Create a Pwncat instance of either a server or a client. Args: - ssig (StopSignal): Stop signal instance + ssig (InterruptHandler): Instance of InterruptHandler. encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). host (str): The hostname to resolve. ports ([int]): List of ports to connect to or listen on. @@ -2556,6 +2554,9 @@ class IONetwork(IO): self.__srv_opts = srv_opts self.__cli_opts = cli_opts + # Did we already run cleanup + self.__cleaned_up = False + # Internally store addresses for reconn or rebind functions self.__host = host self.__ports = ports @@ -2590,9 +2591,9 @@ class IONetwork(IO): try: yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action - except socket.timeout: + except socket.timeout as err: # Let's ask the interrupter() function if we should terminate? - if not self.ssig.has_stop(): + if not self.ssig.has_sock_quit(): continue # Stop signal is raied when my own side of the network was closed. # Happened most likely that the user pressed Ctrl+c @@ -2607,12 +2608,19 @@ class IONetwork(IO): curr_recv_timeout_retry += 1 continue # We ware all done reading, shut down - self.ssig.raise_stop() + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [1]: %s", err + ) + self.__cleanup() return - # [3/3] Upstream is gone - except (EOFError, AttributeError, socket.error): + # [3/3] Upstream is gone (in one way or another) + except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [2]: %s", err + ) + self.__cleanup() return # Do we re-accept new clients? if self.__sock_opts.udp: @@ -2622,27 +2630,39 @@ class IONetwork(IO): continue if self.__role == "client" and self.__client_reconnect_to_server(): continue + # Inform everybody that we are quitting + self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() return def consumer(self, data): # type: (str) -> None """Send data to a socket.""" - self.__net.send(data) + try: + self.__net.send(data) + except socket.error: + pass def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace( # type: ignore - "[IONetwork] socket.close was raised by calling interrupt() externally." - ) - self.__net.close_conn_sock() - self.__net.close_bind_sock() - # Raise stop signal - self.ssig.raise_stop() + self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() # -------------------------------------------------------------------------- # Private Functions # -------------------------------------------------------------------------- + def __cleanup(self): + # type: () -> None + """Cleanup function.""" + if not self.__cleaned_up: + self.log.trace("SOCK-QUIT-CLEANUP: Closing sockets") # type: ignore + self.__net.close_conn_sock() + self.__net.close_bind_sock() + self.__cleaned_up = True + def __client_reconnect_to_server(self): # type: () -> bool """Ensure the client re-connects to the remote server, if the remote server hang up. @@ -2655,13 +2675,14 @@ class IONetwork(IO): # reconn < 0 (endlessly) # reconn > 0 (reconnect until counter reaches zero) while self.__cli_opts.reconn != 0: - # [1/6] Let's ask the interrupter() function if we should terminate? # We need a little wait here in order for the stop signal to propagate. # Don't know how fast the other threads are. - # time.sleep(0.1) - # if self.ssig.has_stop(): - # return False + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" + ) + return False # [2/6] Wait time.sleep(self.__cli_opts.reconn_wait) @@ -2669,7 +2690,10 @@ class IONetwork(IO): # [3/6] Let's ask the interrupter() function if we should terminate? # In case the other threads were slower as the sleep time in [1/5] # we will check again here. - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" + ) return False # [4/6] Increment the port numer (if --reconn-robin has multiple) @@ -2713,7 +2737,10 @@ class IONetwork(IO): while self.__srv_opts.rebind != 0: # [1/7] Let's ask the interrupter() function if we should terminate? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_rebind [1]" + ) return False # [2/7] Increment the port numer (if --reconn-robin has multiple) @@ -2746,7 +2773,10 @@ class IONetwork(IO): # [6/7] Let's ask the interrupter() function if we should terminate? # In case the other threads were slower as the sleep time in [1/7] # we will check again here. - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_rebind [2]" + ) return False # [6/7] Recurse until True or reconnect count is used up @@ -2775,9 +2805,12 @@ class IONetwork(IO): # [MAYBE] Check stop signal and otherwise try until success. while True: - time.sleep(0.1) + time.sleep(0.01) # [NO] We have a stop signal - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_reaccept_from_client" + ) return False # [YES] Re-accept indefinitely self.log.info("Re-accepting new clients") @@ -2818,7 +2851,7 @@ class IONetworkScanner(IO): # -------------------------------------------------------------------------- def __init__( self, - ssig, # type: StopSignal + ssig, # type: InterruptHandler encoder, # type: StringEncoder host, # type: str banner, # type: bool @@ -2829,7 +2862,7 @@ class IONetworkScanner(IO): """Create a Pwncat Network Scanner instance. Args: - ssig (StopSignal): Stop signal instance + ssig (InterruptHandler): Instance of InterruptHandler. encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). host (str): The hostname to resolve. banner (bool): Determines if we do banner grabbing as well. @@ -2838,19 +2871,19 @@ class IONetworkScanner(IO): """ super(IONetworkScanner, self).__init__(ssig) + self.__ssig = ssig self.__enc = encoder self.__cli_opts = cli_opts self.__sock_opts = sock_opts self.__banner = banner self.__log = logging.getLogger(__name__) - self.__net = Net(encoder, ssig, sock_opts) self.__sock = Sock() self.__screen_lock = threading.Semaphore() # Keep track of local binds (addr-port) of the threaded scanner # clients as we do not want to treat them as open ports (false posistives) - self.__local_binds = [] # type: List[str] + self.__local_binds = {} # type: Dict[str, socket.socket] # Compile our regexes if using banner detection if banner: @@ -2868,13 +2901,13 @@ class IONetworkScanner(IO): int(socket.AF_INET), ] self.__targets = {} - try: - for family in families: + for family in families: + try: self.__targets[family] = self.__sock.gethostbyname( host, family, not self.__sock_opts.nodns ) - except socket.gaierror: - pass + except socket.gaierror: + pass # -------------------------------------------------------------------------- # Public Functions @@ -2882,18 +2915,24 @@ class IONetworkScanner(IO): def __get_socket(self, family): # type: (Union[socket.AddressFamily, int]) -> socket.socket """Create socket for specific address family endlessly until resources are available.""" - # The scanner is starting many threads, each creating a single socket - # and we might hit the max allowed open files limit, so we will - # endlessly ask the system for a new socket until success. - # Also adding a delay, which will give other threads the time to - # release their sockets. + # The scanner starts one thread for each port to scan. Each thread will also create + # one socket and we might hit the max_allowed_files limit (ulimit). + # That's why we loop through creating sockets until we hit a success + # as in the meantime, other threads might have already released sockets/fd's. while True: + delay = 0.0 + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner._getsocket" + ) + raise socket.error("quit") try: if self.__sock_opts.udp: return self.__sock.create_socket(family, socket.SOCK_DGRAM) return self.__sock.create_socket(family, socket.SOCK_STREAM) except socket.error: - time.sleep(0.1) # This can be bigger to give the system some time to release fd's + delay += 0.1 + time.sleep(delay) # This can be bigger to give the system some time to release fd's def __get_banner_version(self, banner): # type: (str) -> Optional[str] @@ -2929,6 +2968,12 @@ class IONetworkScanner(IO): payloads = self.BANNER_PAYLOADS[0] for payload in payloads: + # Break the loop on terminate signal + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner._getbanner: %s-%d", addr, port + ) + return (False, None) try: if payload is not None: sock.send(self.__enc.encode(payload)) @@ -2961,13 +3006,25 @@ class IONetworkScanner(IO): # Loop over adress families for family in self.__targets: + # [1/7] Check for termination request + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner.producer" + ) + return + addr = self.__targets[family] - # [1/5] Get socket - sock = self.__get_socket(family) + # [2/7] Get socket + try: + sock = self.__get_socket(family) + sock_type = sock.type + except (AttributeError, socket.error): + # Exception is triggered due to stop stignal and we + # will abort here in that case. + return - # [2/5] Connect scan - succ_conn = False + # [3/7] Connect scan try: laddr, lport = self.__sock.connect( sock, @@ -2981,42 +3038,42 @@ class IONetworkScanner(IO): 0.1, ) # Append local binds (addr-port) to check against during port scan - self.__local_binds.append(str(laddr + "-" + str(lport))) - succ_conn = True + key = str(laddr + "-" + str(lport)) + self.__local_binds[key] = sock except socket.error: - succ_conn = False + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + continue - # [3/5] Banner grabbing + # [4/7] False positives + # Connect was successful, but against a local bind of one of our + # port scanners, so this is a false positive. + if str(addr + "-" + str(port)) in self.__local_binds: + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + del self.__local_binds[key] + continue + + # [5/7] Banner grabbing succ_banner = True banner = None if self.__banner: (succ_banner, banner) = self.__get_banner(sock, addr, port) - # [4/5] Evaluation - if banner is not None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({}): {}".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - banner, - ) - if banner is None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({})".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - ) + # [6/7] Evaluation + if banner is not None and succ_banner: + yield "[+] {:>5}/{} open ({}): {}".format( + port, + self.__sock.get_type_name(sock_type), + self.__sock.get_family_name(family), + banner, + ) + if banner is None and succ_banner: + yield "[+] {:>5}/{} open ({})".format( + port, self.__sock.get_type_name(sock_type), self.__sock.get_family_name(family), + ) - # [5/5] Cleanup - self.__sock.close(sock, addr + "-" + str(port)) - try: - self.__local_binds.remove(str(addr + "-" + str(port))) - except ValueError: - pass + # [7/7] Cleanup + self.__sock.close(sock, key) + del self.__local_binds[key] def consumer(self, data): # type: (str) -> None @@ -3037,8 +3094,20 @@ class IONetworkScanner(IO): self.__screen_lock.release() def interrupt(self): - # type: (str) -> None - """Not required.""" + # type: () -> None + """Stop function that can be called externally to close this instance.""" + self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore + self.ssig.raise_sock_quit() + + # NOTE: Closing up to 65535 sockets (single thread) takes very very long + # Se we leave this up to Python itself, once the program exits. + # self.log.trace("SOCK-QUIT-CLEANUP: Closing sockets") # type: ignore + # # Double loop to prevent: Dictionary size changed during iteration + # remove = {} + # for key in self.__local_binds: + # remove[key] = self.__local_binds[key] + # for key in remove: + # self.__sock.close(remove[key], key) # ------------------------------------------------------------------------------------------------- @@ -3056,17 +3125,18 @@ class IOStdinStdout(IO): # Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, ssig, opts): - # type: (StopSignal, DsIOStdinStdout) -> None + # type: (InterruptHandler, DsIOStdinStdout) -> None """Set specific options for this I/O module. Args: - ssig (StopSignal): StopSignal instance. + ssig (InterruptHandler): InterruptHandler instance. opts (DsIOStdinStdout): IO options. """ super(IOStdinStdout, self).__init__(ssig) self.__opts = opts self.__py3 = sys.version_info >= (3, 0) # type: bool self.__win = os.name != "posix" # posix or nt + self.__abort = False # -------------------------------------------------------------------------- # Public Functions @@ -3082,8 +3152,13 @@ class IOStdinStdout(IO): # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-1") # type: ignore + if self.__abort: + self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore + return + if self.ssig.has_stdin_quit(): + self.log.trace( # type: ignore + "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]" + ) return try: data = self.__read_stdin() @@ -3091,8 +3166,10 @@ class IOStdinStdout(IO): # When using select() with timeout, we don't have any input # at this point and simply continue the loop or quit if # a terminate request has been made by other threads. - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-2") # type: ignore + if self.ssig.has_stdin_quit(): + self.log.trace( # type: ignore + "STDIN-QUIT signal ACK in IOStdinStdout.producer [2]" + ) return continue if data: @@ -3101,10 +3178,9 @@ class IOStdinStdout(IO): yield data # EOF or + else: - # DO NOT RETURN HERE BLINDLY, THE UPSTREAM CONNECTION MUST GO FIRST! - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-3") # type: ignore - return + # NOTE: logging is disabled as it produces way too many messages per second. + # self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.producer") # type: ignore + self.ssig.raise_stdin_quit() def consumer(self, data): # type: (str) -> None @@ -3124,12 +3200,14 @@ class IOStdinStdout(IO): def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" + # TODO: Does not work on windows as it has blocking read of stdin + self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore + self.ssig.raise_stdin_quit() + self.log.trace( # type: ignore - "[IOStdinStdout] interrupt() invoked" + "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" ) - # Raise stop signal - # TODO: Check if this is required??? - self.ssig.raise_stop() + self.__abort = True # -------------------------------------------------------------------------- # Private Functions @@ -3212,19 +3290,19 @@ class IOCommand(IO): # Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, ssig, opts): - # type: (StopSignal, DsIOCommand) -> None + # type: (InterruptHandler, DsIOCommand) -> None """Set specific options for this I/O module. Args: - ssig (StopSignal): Instance of StopSignal. + ssig (InterruptHandler): Instance of InterruptHandler. opts (DsIOCommand): Custom module options. """ super(IOCommand, self).__init__(ssig) self.__opts = opts self.log.debug("Setting '%s' as executable", self.__opts.executable) - # Define destructor - atexit.register(self.__destruct__) + # Did we already run cleanup + self.__cleaned_up = False # Open executable to wait for commands env = os.environ.copy() @@ -3246,14 +3324,6 @@ class IOCommand(IO): self.log.error("Specified executable '%s' not found", self.__opts.executable) sys.exit(1) - def __destruct__(self): - # type: () -> None - """Destructor.""" - self.log.trace( # type: ignore - "Killing executable: %s with pid %d", self.__opts.executable, self.proc.pid - ) - self.proc.kill() - # -------------------------------------------------------------------------- # Public Functions # -------------------------------------------------------------------------- @@ -3266,8 +3336,9 @@ class IOCommand(IO): """ assert self.proc.stdout is not None while True: - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged in Command") # type: ignore + if self.ssig.has_command_quit(): + self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.__cleanup() return self.log.trace("Reading command output") # type: ignore # Byte-wise reading is required to make it work for remote ends being in raw mode @@ -3276,8 +3347,10 @@ class IOCommand(IO): data = self.proc.stdout.read(1) self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: - self.log.trace("Command output was empty. Exiting loop.") # type: ignore - break + self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + return yield self.__opts.enc.decode(data) def consumer(self, data): @@ -3296,13 +3369,22 @@ class IOCommand(IO): def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace( # type: ignore - "[IOCommand] subprocess.kill() was raised by input_unterrupter()" - ) - self.proc.kill() - # Raise stop signal - # TODO: Check if this is required??? - self.ssig.raise_stop() + self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + + def __cleanup(self): + # type: () -> None + """Cleanup function.""" + if not self.__cleaned_up: + self.log.trace( # type: ignore + "CMD-QUIT-CLEANUP: killing executable: %s with pid %d", + self.__opts.executable, + self.proc.pid, + ) + self.proc.kill() + self.__cleaned_up = True + return False # ################################################################################################# @@ -3322,7 +3404,7 @@ class PSEStore(object): The same instance of this class will be available to your send and receive scripts that allow you to exchange data or manipulate themselves. You even have access to the currently used instance of the networking class to manipulate the active socket. - As well as to the logger and StopSignal instances. + As well as to the logger and InterruptHandler instances. """ @property @@ -3349,8 +3431,8 @@ class PSEStore(object): @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: Instance of Logging.logger class.""" + # type: () -> InterruptHandler + """`InterruptHandler`: Instance of InterruptHandler class.""" return self.__ssig @property @@ -3366,11 +3448,11 @@ class PSEStore(object): return self.__log def __init__(self, ssig, net): - # type: (StopSignal, List[IONetwork]) -> None + # type: (InterruptHandler, List[IONetwork]) -> None """Instantiate the PSE class. Args: - ssig (StopSignal): Instance of the StopSignal class to force a shutdown. + ssig (InterruptHandler): Instance InterruptHandler. net (IONetwork): Instance of the current network class to manipulate the socket. """ self.__messages = {} @@ -3389,7 +3471,104 @@ class PSEStore(object): # ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [8/11 IO RUNNER]: (1/1) Runner +# [8/11 IO RUNNER]: (1/2) InterruptHandler +# ------------------------------------------------------------------------------------------------- +class InterruptHandler(object): + """Pwncat interrupt handler. + + It allows all threads to raise various signal on certain actions, + as well as to ask the Interrupt Handler what to do. + The Interrupt handler will internally decide (based on pwncat's + command line arguments) what to do. + """ + + # -------------------------------------------------------------------------- + # Constructor + # -------------------------------------------------------------------------- + def __init__(self, keep_open, no_shutdown): + # type: (bool, bool) -> None + """Instantiate InterruptHandler. + + Args: + keep_open (bool): `--keep-open` command line argument. + no_shutdown (bool): `--no-shutdown` command line argument. + """ + self.__log = logging.getLogger(__name__) # type: logging.Logger + self.__keep_open = keep_open + self.__no_shutdown = no_shutdown + + self.__terminate = False + self.__sock_quit = False + self.__stdin_quit = False + self.__command_quit = False + + def handler(signum, frame): # type: ignore # pylint: disable=unused-argument + self.__log.trace("Ctrl+c caught.") # type: ignore + self.raise_terminate() + + # Handle Ctrl+C + signal.signal(signal.SIGINT, handler) + + # -------------------------------------------------------------------------- + # Ask for action + # -------------------------------------------------------------------------- + def has_terminate(self): + # type: () -> bool + """`bool`: Switch to be checked if pwncat should be terminated.""" + return self.__terminate + + def has_sock_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the socket connection should be closed.""" + return self.__sock_quit + + def has_stdin_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the STDIN should be closed.""" + return self.__stdin_quit + + def has_command_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the command should be closed.""" + return self.__command_quit + + # -------------------------------------------------------------------------- + # Raise signals + # -------------------------------------------------------------------------- + def raise_terminate(self): + # type: () -> None + """Signal the application that Socket should be quit.""" + self.__log.trace("SIGNAL TERMINATE raised") # type: ignore + self.__terminate = True + self.__sock_quit = True + self.__stdin_quit = True + self.__command_quit = True + + def raise_sock_quit(self): + # type: () -> None + """Signal the application that Socket should be quit.""" + self.__log.trace("SIGNAL SOCK-QUIT raised") # type: ignore + self.__sock_quit = True + self.raise_terminate() + + def raise_stdin_quit(self): + # type: () -> None + """Signal the application that STDIN should be quit.""" + if not (self.__no_shutdown or self.__keep_open): + self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore + self.__stdin_quit = True + self.raise_terminate() + + def raise_command_quit(self): + # type: () -> None + """Signal the application that Command should be quit.""" + self.__log.trace("SIGNAL CMD-QUIT raised") # type: ignore + self.__command_quit = True + self.raise_terminate() + + +# ------------------------------------------------------------------------------------------------- +# [8/11 IO RUNNER]: (2/2) Runner # ------------------------------------------------------------------------------------------------- class Runner(object): """Runner class that takes care about putting everything into threads.""" @@ -3397,11 +3576,12 @@ class Runner(object): # -------------------------------------------------------------------------- # Constructor / Destructor # -------------------------------------------------------------------------- - def __init__(self, pse): - # type: (PSEStore) -> None + def __init__(self, ssig, pse): + # type: (InterruptHandler, PSEStore) -> None """Create a new Runner object. Args: + ssig (InterruptHandler): Instance of InterruptHandler. pse (PSEStore): Pwncat Scripting Engine store. """ self.log = logging.getLogger(__name__) @@ -3423,6 +3603,7 @@ class Runner(object): # {"name": ""} self.__threads = {} # type: Dict[str, threading.Thread] + self.__ssig = ssig self.__pse = pse # -------------------------------------------------------------------------- @@ -3515,22 +3696,24 @@ class Runner(object): self.log.trace("[%s] Producer Stop", name) # type: ignore def run_timer(name, action, intvl, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, InterruptHandler, Any, Any) -> None """Timer run function to be thrown into a thread (Execs periodic tasks). Args: name (str): Name for logging output action (function): Function to be called in a given intervall intvl (float): Intervall at which the action function will be called - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ self.log.trace("[%s] Timer Start (exec every %f sec)", name, intvl) # type: ignore time_last = int(time.time()) while True: - if ssig.has_stop(): - self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore + if ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for timer action [%s]", name + ) return time_now = int(time.time()) if time_now > time_last + intvl: @@ -3540,7 +3723,7 @@ class Runner(object): time.sleep(0.1) def run_repeater(name, action, repeat, pause, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, float, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, float, InterruptHandler, Any, Any) -> None """Repeater run function to be thrown into a thread (Execs periodic tasks). Args: @@ -3548,23 +3731,30 @@ class Runner(object): action (function): Function to be called repeat (int): Repeat the function so many times before quitting pause (float): Pause between repeated calls - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ cycles = 1 self.log.trace("Repeater Start (%d/%d)", cycles, repeat) # type: ignore while cycles <= repeat: - if ssig.has_stop(): - self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore + if ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for repeater action [%s]", name + ) return self.log.debug("Executing repeated function (%d/%d)", cycles, repeat) action(*args, **kwargs) cycles += 1 time.sleep(pause) - # Start available action in a thread + # [1/3] Start available action in a thread for key in self.__actions: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [1]: [%s]", key + ) + break # Create Thread object thread = threading.Thread( target=run_action, @@ -3577,16 +3767,27 @@ class Runner(object): self.__actions[key].code, ), ) - thread.daemon = False + # Daemon threads are easier to kill + thread.daemon = True + # Add delay if threads cannot be started + delay = 0.0 while True: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [2]: [%s]", key + ) + break try: + # Start and break the loop upon success to go to the next thread to start thread.start() break except (RuntimeError, Exception): # pylint: disable=broad-except - time.sleep(0.1) # This can be big to give the system some time to release fd's + delay += 0.1 + time.sleep(delay) # Give the system some time to release open fd's self.__threads[key] = thread - # Start available timers in a thread + + # [2/3] Start available timers in a thread for key in self.__timers: # Create Thread object thread = threading.Thread( @@ -3596,14 +3797,15 @@ class Runner(object): key, self.__timers[key].action, self.__timers[key].intvl, - self.__timers[key].signal, + self.__timers[key].ssig, self.__timers[key].args, ), kwargs=self.__timers[key].kwargs, ) thread.daemon = False thread.start() - # Start available repeaters in a thread + + # [3/3] Start available repeaters in a thread for key in self.__repeaters: # Create Thread object thread = threading.Thread( @@ -3614,7 +3816,7 @@ class Runner(object): self.__repeaters[key].action, self.__repeaters[key].repeat, self.__repeaters[key].pause, - self.__repeaters[key].signal, + self.__repeaters[key].ssig, self.__repeaters[key].args, ), kwargs=self.__repeaters[key].kwargs, @@ -3622,22 +3824,14 @@ class Runner(object): thread.daemon = False thread.start() - def check_stop(force): - # type: (int) -> bool + def check_stop(): + # type: () -> bool """Stop threads.""" - for key in self.__threads: - if not self.__threads[key].is_alive() or force: - # TODO: How are we gonna call the stop signal now? - # # [1/3] Inform all threads (inside) about a stop signal. - # # All threads with non-blocking funcs will be able to stop themselves - # self.log.trace( # type: ignore - # "Raise stop signal: StopSignal.stop() for thread [%s]", - # self.__threads[key].getName(), - # ) - # self.__actions[key].signal.raise_stop() - # [2/3] Call external interrupters - # These will shutdown all blocking functions inside a thread, - # so that they are actually able to join + # TODO: This is a workaround for using daemon threads. + # Python < 3.3 is unable to detect Ctrl+c signal during + # thread.join() operation in a fast loop (Port scan). + if self.__ssig.has_terminate(): + for key in self.__threads: for interrupt in self.__actions[key].interrupts: self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", @@ -3646,24 +3840,53 @@ class Runner(object): self.__threads[key].getName(), ) interrupt() - # [3/3] All blocking events inside the threads are gone, now join them - self.log.trace("Joining %s", self.__threads[key].getName()) # type: ignore - self.__threads[key].join(timeout=0.1) - # If all threads have died or force is requested, then exit - if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + return True + # If all threads are done, also stop + if not all([self.__threads[key].is_alive() for key in self.__threads]): return True return False + # NOTE: This was for previous non-daemon threads + # for key in self.__threads: + # if not self.__threads[key].is_alive() or force: + # # TODO: How are we gonna call the stop signal now? + # # # [1/3] Inform all threads (inside) about a stop signal. + # # # All threads with non-blocking funcs will be able to stop themselves + # # self.log.trace( # type: ignore + # # "Raise stop signal: StopSignal.stop() for thread [%s]", + # # self.__threads[key].getName(), + # # ) + # # self.__actions[key].signal.signal_quit() + # # [2/3] Call external interrupters + # # These will shutdown all blocking functions inside a thread, + # # so that they are actually able to join + # for interrupt in self.__actions[key].interrupts: + # self.log.trace( # type: ignore + # "Call INTERRUPT: %s.%s() for %s", + # getattr(interrupt, "__self__").__class__.__name__, + # interrupt.__name__, + # self.__threads[key].getName(), + # ) + # interrupt() + # # [3/3] All blocking events inside the threads are gone, now join them + # try: + # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore + # # NOTE: The thread.join() operating will also block the signal handler + # #self.__threads[key].join(timeout=0.1) + # self.__threads[key].join() + # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore + # except RuntimeError as err: + # print(err) + # #pass + # # If all threads have died or force is requested, then exit + # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + # return True + # return False - try: - while True: - if check_stop(False): - sys.exit(0) - # Need a timeout to not skyrocket the CPU - time.sleep(0.1) - except KeyboardInterrupt: - print() - check_stop(True) - sys.exit(1) + while True: + if check_stop(): + sys.exit(0) + # Need a timeout to not skyrocket the CPU + time.sleep(0.01) # ################################################################################################# @@ -4509,6 +4732,18 @@ CR on MacOS). default=False, help="""Do not resolve DNS. +""", + ) + optional.add_argument( + "--no-shutdown", + action="store_true", + default=False, + help="""Do not shutdown into half-duplex mode. +If this option is passed, pwncat won't invoke shutdown +on a socket after seeing EOF on stdin. This is provided +for backward-compatibility with OpenBSD netcat, which +exhibits this behavior. + """, ) optional.add_argument( @@ -5091,8 +5326,8 @@ def main(): # Initialize encoder enc = StringEncoder() - # Initialize StopSignal - ssig = StopSignal() + # Initialize interrupt handler + ssig = InterruptHandler(args.keep_open, args.no_shutdown) # Initialize transformers transformers = [] @@ -5128,7 +5363,7 @@ def main(): net_srv = IONetwork(ssig, enc, lhost, [lport], "server", srv_opts, cli_opts, sock_opts) net_cli = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(PSEStore(ssig, [net_srv, net_cli])) + run = Runner(ssig, PSEStore(ssig, [net_srv, net_cli])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -5163,7 +5398,7 @@ def main(): net_cli_l = IONetwork(ssig, enc, lhost, [lport], "client", srv_opts, cli_opts, sock_opts) net_cli_r = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(PSEStore(ssig, [net_cli_l, net_cli_r])) + run = Runner(ssig, PSEStore(ssig, [net_cli_l, net_cli_r])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -5190,14 +5425,14 @@ def main(): if mode == "scan": print("Scanning {} ports".format(len(ports))) net = IONetworkScanner(ssig, enc, host, args.banner, cli_opts, sock_opts) - run = Runner(PSEStore(ssig, [net])) + run = Runner(ssig, PSEStore(ssig, [net])) for port in ports: run.add_action( "PORT-{}".format(port), DsRunnerAction( DsCallableProducer(net.producer, port), # Send port scans net.consumer, # Output results - [], + [net.interrupt], transformers, None, ), @@ -5215,7 +5450,7 @@ def main(): cnc_cmd, cnc_host, cnc_port = args.self_inject.split(":") cnc_ports = ArgValidator.get_port_list_from_string(cnc_port) CNCAutoDeploy(enc, net.consumer, net.producer, cnc_cmd, cnc_host, cnc_ports) - run = Runner(PSEStore(ssig, [net])) + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( @@ -5243,7 +5478,7 @@ def main(): net = IONetwork( ssig, enc, host, ports + args.reconn_robin, "client", srv_opts, cli_opts, sock_opts ) - run = Runner(PSEStore(ssig, [net])) + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( @@ -5281,9 +5516,4 @@ def main(): # [11/11 MAIN ENTRYPOINT]: (2/2) start # ------------------------------------------------------------------------------------------------- if __name__ == "__main__": - # Catch Ctrl+c and exit without error message - try: - main() - except KeyboardInterrupt: - print() - sys.exit(1) + main() From dded7809d43ec3e835668fd0a29237542aa3a0da Mon Sep 17 00:00:00 2001 From: cytopia Date: Mon, 1 Jun 2020 19:20:09 +0200 Subject: [PATCH 08/61] Heavy refactoring --- CHANGELOG.md | 20 +- Makefile | 2 +- README.md | 9 + bin/pwncat | 473 ++- docs/index.html | 9 + docs/pwncat.api.html | 3708 ++++++++++++----- docs/pwncat.man.html | 15 + docs/pwncat.type.html | 1756 ++++++-- man/pwncat.1 | 15 + setup.cfg | 6 +- ...s_killed---client_default---before_send.sh | 28 +- ...client_default---after_client_sent_data.sh | 28 +- ...client_default---after_server_sent_data.sh | 28 +- ...s_killed---client_command---before_send.sh | 28 +- ...ent_command---after_server_sent_command.sh | 28 +- ...s_killed---client_default---before_send.sh | 28 +- ...client_default---after_client_sent_data.sh | 28 +- ...client_default---after_server_sent_data.sh | 28 +- ...s_killed---client_command---before_send.sh | 28 +- ...-client_stays---when_valid_http_request.sh | 10 +- ...ient_quites---when_invalid_http_request.sh | 10 +- ...s_killed---server_default---before_send.sh | 28 +- ...server_default---after_client_sent_data.sh | 28 +- ...server_default---after_server_sent_data.sh | 28 +- ...s_killed---server_command---before_send.sh | 28 +- ...ver_command---after_client_sent_command.sh | 28 +- ...s_killed---server_default---before_send.sh | 28 +- ...server_default---after_client_sent_data.sh | 28 +- ...s_killed---server_command---before_send.sh | 28 +- ...er_command---after_client_sends_command.sh | 28 +- ...server_default---after_client_sent_data.sh | 28 +- ...ver_command---after_client_sent_command.sh | 28 +- .../000---tcp---www-forward.sh | 30 +- .../000---tcp---www-forward.sh | 30 +- .../000---tcp---client_nodns.sh | 22 +- .../001---udp---client_nodns.sh | 22 +- .../100---tcp---server_nodns.sh | 22 +- .../101---udp---server_nodns.sh | 22 +- ...cp---client_crlf_crlf---server_sends_lf.sh | 30 +- ...cp---client_crlf_crlf---server_sends_cr.sh | 30 +- ...---client_crlf_crlf---server_sends_crlf.sh | 30 +- ...cp---server_crlf_crlf---client_sends_lf.sh | 30 +- ...cp---server_crlf_crlf---client_sends_cr.sh | 30 +- ...---server_crlf_crlf---client_sends_crlf.sh | 30 +- ...-tcp---client_crlf_lf---server_sends_lf.sh | 30 +- ...-tcp---client_crlf_lf---server_sends_cr.sh | 30 +- ...cp---client_crlf_lf---server_sends_crlf.sh | 30 +- ...-tcp---server_crlf_lf---client_sends_lf.sh | 30 +- ...-tcp---server_crlf_lf---client_sends_cr.sh | 30 +- ...cp---server_crlf_lf---client_sends_crlf.sh | 30 +- ...-tcp---client_crlf_cr---server_sends_lf.sh | 30 +- ...-tcp---client_crlf_cr---server_sends_cr.sh | 30 +- ...cp---client_crlf_cr---server_sends_crlf.sh | 30 +- ...-tcp---server_crlf_cr---client_sends_lf.sh | 30 +- ...-tcp---server_crlf_cr---client_sends_cr.sh | 30 +- ...cp---server_crlf_cr---client_sends_crlf.sh | 30 +- ...-tcp---client_crlf_no---server_sends_lf.sh | 30 +- ...-tcp---client_crlf_no---server_sends_cr.sh | 30 +- ...cp---client_crlf_no---server_sends_crlf.sh | 30 +- ...-tcp---server_crlf_no---client_sends_lf.sh | 30 +- ...-tcp---server_crlf_no---client_sends_cr.sh | 30 +- ...cp---server_crlf_no---client_sends_crlf.sh | 30 +- ...efault---cli_nosend-cli_nosend-cli_send.sh | 28 +- ..._default---cli_nosend-cli_send-cli_send.sh | 28 +- ...er_default---cli_send-cli_send-cli_send.sh | 28 +- ..._default---srv_send-cli_nosend-cli_send.sh | 28 +- ...er_default---srv_send-cli_send-cli_send.sh | 28 +- ...ommand---cli_nosend-cli_nosend-cli_send.sh | 28 +- ..._command---cli_nosend-cli_send-cli_send.sh | 28 +- ...er_command---cli_send-cli_send-cli_send.sh | 28 +- ...cli_send-srv_nosend-srv_nosend-srv_send.sh | 28 +- ...n_cli_send-srv_nosend-srv_send-srv_send.sh | 28 +- ...own_cli_send-srv_send-srv_send-srv_send.sh | 28 +- .../000---udp---reverse-shell.sh | 30 +- .../000---udp---reverse-shell.sh | 30 +- .../200---tcp---keep_open/docker-compose.yml | 6 +- .../start_client_send.sh | 2 +- 77 files changed, 5254 insertions(+), 2583 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b7119a8..8a702b3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ ## Release 0.1.0 +### Fixes +- Fixed UTF-8 char conversion for Python3 +- Fixed calculation for socket bytes sent +- Fixed shutdown handling for port scanner +- Fixed false positives for port scanner +- FIxed sending binary data from stdin + +### Added +- Implemented signal handler to distribute shutdown signals across threads +- Feature: `--no-shutdown` to copy the behaviour of OpenBSD netcat to keep stdin open after EOF +- Feature: `--http` +- Feature: `send-on-eof` + +### Changed +- Changed behaviour to close after EOF on stdin (can be reverted via `--no-shutdown`) + ## Release 0.0.23-alpha @@ -18,10 +34,6 @@ ## Release 0.0.22-alpha -## Fixes -- Fixes UTF-8 char conversion - - ### Added - Feature: Rebind forever: `--rebind`: #44 - Feature: Wait between rebind attempts: `--rebind-wait`: #45 diff --git a/Makefile b/Makefile index 81757b57..62788ed5 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ INTPATH = tests/integration/ BINNAME = pwncat FL_VERSION = 0.3 -FL_IGNORES = .git/,.github/,$(BINNAME).egg-info,docs/$(BINNAME).api.html,docs/,data/,.mypy_cache/ +FL_IGNORES = .git/,.github/,$(BINNAME).egg-info,docs/$(BINNAME).api.html,docs/,data/,.mypy_cache/,rtfm/venv,rtfm/_build UID := $(shell id -u) GID := $(shell id -g) diff --git a/README.md b/README.md index 4848792b..2ac86e05 100644 --- a/README.md +++ b/README.md @@ -468,6 +468,15 @@ optional arguments: -n, --nodns Do not resolve DNS. + --send-on-eof Buffer data received on stdin until EOF and send + everything in one chunk. + + --no-shutdown Do not shutdown into half-duplex mode. + If this option is passed, pwncat won't invoke shutdown + on a socket after seeing EOF on stdin. This is provided + for backward-compatibility with OpenBSD netcat, which + exhibits this behavior. + -v, --verbose Be verbose and print info to stderr. Use -v, -vv, -vvv or -vvvv for more verbosity. The server performance will decrease drastically if you use more than three times. diff --git a/bin/pwncat b/bin/pwncat index 854b9755..259394e0 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -58,6 +58,7 @@ from __future__ import print_function from abc import abstractmethod from abc import ABCMeta +from datetime import datetime from subprocess import PIPE from subprocess import Popen from subprocess import STDOUT @@ -214,7 +215,7 @@ class DsCallableProducer(object): # -------------------------------------------------------------------------- @property def function(self): - # type: () -> Callable[..., Iterator[str]] + # type: () -> Callable[..., Iterator[bytes]] """`IO.producer`: Callable funtcion function.""" return self.__function @@ -234,7 +235,7 @@ class DsCallableProducer(object): # Contrcutor # -------------------------------------------------------------------------- def __init__(self, function, *args, **kwargs): - # type: (Callable[..., Iterator[str]], Any, Any) -> None + # type: (Callable[..., Iterator[bytes]], Any, Any) -> None self.__function = function self.__args = args self.__kwargs = kwargs @@ -257,7 +258,7 @@ class DsRunnerAction(object): @property def consumer(self): - # type: () -> Callable[[str], None] + # type: () -> Callable[[bytes], None] """`IO.consumer`: Data consumer function.""" return self.__consumer @@ -285,7 +286,7 @@ class DsRunnerAction(object): def __init__( self, producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] interrupts, # type: List[Callable[[], None]] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] @@ -806,14 +807,21 @@ class DsIOStdinStdout(object): """`float`: Input timeout in seconds for non-blocking read or `None` for blocking.""" return self.__input_timeout + @property + def send_on_eof(self): + # type: () -> bool + """`float`: Determines if we buffer STDIN until EOF before sending.""" + return self.__send_on_eof + # -------------------------------------------------------------------------- # Constructor # -------------------------------------------------------------------------- - def __init__(self, encoder, input_timeout): - # type: (StringEncoder, Optional[float]) -> None + def __init__(self, encoder, input_timeout, send_on_eof): + # type: (StringEncoder, Optional[float], bool) -> None super(DsIOStdinStdout, self).__init__() self.__enc = encoder self.__input_timeout = input_timeout + self.__send_on_eof = send_on_eof # ------------------------------------------------------------------------------------------------- @@ -991,31 +999,51 @@ class StringEncoder(object): classes or functions as strings to keep full Python 2/3 compat. """ - # -------------------------------------------------------------------------- - # Constructor - # -------------------------------------------------------------------------- - def __init__(self): - # type: () -> None - """Create a StringEncoder instance which converts str/bytes according to Python version.""" - self.__py3 = sys.version_info >= (3, 0) # type: bool - - # https://stackoverflow.com/questions/606191/27527728#27527728 - self.__codecs = [ - "utf-8", - "cp437", - "latin-1", - ] + CODECS = [ + "utf-8", + "cp437", + "latin-1", + ] # -------------------------------------------------------------------------- - # Public Functions - # -------------------------------------------------------------------------- - def encode(self, data): + # Class methods + # -------------------------------------------------------------------------- + @classmethod + def rstrip(cls, data, search=None): + # type: (Union[bytes, str], Optional[str]) -> Union[bytes, str] + """Implementation of rstring which works on bytes or strings.""" + # We have a bytes object in Python3 + if sys.version_info >= (3, 0) and type(data) is not str: + # Strip whitespace + if search is None: + while True: + new = data + new = cls.rstrip(new, " ") + new = cls.rstrip(new, "\n") + new = cls.rstrip(new, "\r") + new = cls.rstrip(new, "\t") + # Loop until no more changes occur + if new == data: + return new + else: + bsearch = StringEncoder.encode(search) + while data[-1:] == bsearch: + data = data[:-1] + return data + + # Use native function + if search is None: + return data.rstrip() + return data.rstrip(search) # type: ignore + + @classmethod + def encode(cls, data): # type: (str) -> bytes """Convert string into a byte type for Python3.""" - if self.__py3: - for codec in self.__codecs: + if sys.version_info >= (3, 0): + for codec in cls.CODECS: # On the last codec, do not catch the exception and let it trigger if it fails - if self.__codecs[-1] == codec: + if codec == cls.CODECS[-1]: return data.encode(codec) try: return data.encode(codec) @@ -1023,13 +1051,14 @@ class StringEncoder(object): pass return data # type: ignore - def decode(self, data): + @classmethod + def decode(cls, data): # type: (bytes) -> str """Convert bytes into a string type for Python3.""" - if self.__py3: - for codec in self.__codecs: + if sys.version_info >= (3, 0): + for codec in cls.CODECS: # On the last codec, do not catch the exception and let it trigger if it fails - if self.__codecs[-1] == codec: + if codec == cls.CODECS[-1]: return data.decode(codec) try: return data.decode(codec) @@ -1037,11 +1066,6 @@ class StringEncoder(object): pass return data # type: ignore - def base64_encode(self, data): - # type: (str) -> str - """Convert string into a base64 encoded string.""" - return self.decode(base64.b64encode(self.encode(data))) - # ################################################################################################# # ################################################################################################# @@ -1055,7 +1079,7 @@ class StringEncoder(object): # [4/11 NETWORK]: (1/1) Sock # ------------------------------------------------------------------------------------------------- class Sock(_Singleton("SingletonMeta", (object,), {})): # type: ignore - """Thread-safe singleton Socket helper to emulate a module within the same file.""" + """Thread-safe singleton Socket wrapper to emulate a module within the same file.""" def __init__(self): # type: () -> None @@ -1768,11 +1792,11 @@ class Net(object): # Public Send / Receive Functions # -------------------------------------------------------------------------- def send(self, data): - # type: (str) -> int + # type: (bytes) -> int """Send data through a connected (TCP) or unconnected (UDP) socket. Args: - data (str): The data to send. + data (bytes): The data to send. Returns: int: Returns total bytes sent. @@ -1799,8 +1823,7 @@ class Net(object): curr = 0 # bytes send during one loop iteration send = 0 # total bytes send - byte = self.__enc.encode(data) - size = len(byte) # bytes of data that needs to be send + size = len(data) # bytes of data that needs to be send # Loop until all bytes have been send while send < size: @@ -1810,23 +1833,23 @@ class Net(object): self.__active["remote_addr"], self.__active["remote_port"], ) - self.__log.trace("Trying to send: %s", repr(byte)) # type: ignore + self.__log.trace("Trying to send: %s", repr(data)) # type: ignore try: # Only UDP server has not made a connect() to the socket, all others # are already connected and need to use send() instead of sendto() if self.__udp_mode_server: curr = self.__active["conn"].sendto( - byte, (self.__active["remote_addr"], self.__active["remote_port"]) + data, (self.__active["remote_addr"], self.__active["remote_port"]) ) send += curr else: - curr = self.__active["conn"].send(byte) + curr = self.__active["conn"].send(data) send += curr if curr == 0: self.__log.error("No bytes send during loop round.") return 0 # Remove 'curr' many bytes from byte for the next round - byte = byte[curr:] + data = data[curr:] self.__log.debug( "Sent %d bytes to %s:%d (%d bytes remaining)", curr, @@ -1840,11 +1863,11 @@ class Net(object): return send def receive(self): - # type: () -> str + # type: () -> bytes """Receive and return data from the connected (TCP) or unconnected (UDP) socket. Returns: - str: Returns received data from connected (TCP) or unconnected (UDP) socket. + bytes: Returns received data from connected (TCP) or unconnected (UDP) socket. Raises: socket.timeout: Except here to do an action when the socket is not busy. @@ -1880,7 +1903,7 @@ class Net(object): conn = conns[0] # type: socket.socket try: # https://manpages.debian.org/buster/manpages-dev/recv.2.en.html - (byte, addr) = conn.recvfrom(self.__options.bufsize) + (data, addr) = conn.recvfrom(self.__options.bufsize) # [1/5] When closing itself (e.g.: via Ctrl+c and the socket_close() funcs are called) except AttributeError as error: @@ -1899,7 +1922,7 @@ class Net(object): # [3/5] Upstream (server or client) is gone. # In TCP, there is no such thing as an empty message, so zero means a peer disconnect. # In UDP, there is no such thing as a peer disconnect, so zero means an empty datagram. - if not byte: + if not data: msg = "EOF: Remote finished sending." self.__log.info(msg) raise EOFError(msg) @@ -1938,7 +1961,6 @@ class Net(object): } # [5/5] We have data to process - data = self.__enc.decode(byte) self.__log.debug( "Received %d bytes from %s:%d", len(data), @@ -2269,7 +2291,7 @@ class Net(object): # ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (1/3): Transform +# [5/11 TRANSFORM]: (1/5): Transform # ------------------------------------------------------------------------------------------------- class Transform(ABC): # type: ignore """Abstract class to for pwncat I/O transformers. @@ -2301,16 +2323,19 @@ class Transform(ABC): # type: ignore # -------------------------------------------------------------------------- @abstractmethod def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Implement a transformer function which transforms a string.. + Args: + data (bytes): data to be transformed. + Returns: - str: The transformed string. + bytes: The transformed string. """ # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (2/3) TransformLinefeed +# [5/11 TRANSFORM]: (2/5) TransformLinefeed # ------------------------------------------------------------------------------------------------- class TransformLinefeed(Transform): """Implement basic linefeed replacement.""" @@ -2333,7 +2358,7 @@ class TransformLinefeed(Transform): # Public Functions # -------------------------------------------------------------------------- def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Transform linefeeds to CRLF, LF or CR if requested. Returns: @@ -2345,46 +2370,46 @@ class TransformLinefeed(Transform): # ? -> No line feeds if self.__opts.crlf == "no": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Removing CRLF") return data[:-2] - if data.endswith("\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Removing LF") return data[:-1] - if data.endswith("\r"): + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Removing CR") return data[:-1] # ? -> CRLF - if self.__opts.crlf == "crlf" and not data.endswith("\r\n"): - if data.endswith("\n"): + if self.__opts.crlf == "crlf" and data[-2:] != StringEncoder.encode("\r\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CRLF") - return data[:-1] + "\r\n" - if data.endswith("\r"): + return data[:-1] + StringEncoder.encode("\r\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with CRLF") - return data[:-1] + "\r\n" + return data[:-1] + StringEncoder.encode("\r\n") # ? -> LF if self.__opts.crlf == "lf": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with LF") - return data[:-2] + "\n" - if data.endswith("\r"): + return data[:-2] + StringEncoder.encode("\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with LF") - return data[:-1] + "\n" + return data[:-1] + StringEncoder.encode("\n") # ? -> CR if self.__opts.crlf == "cr": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with CR") - return data[:-2] + "\r" - if data.endswith("\n"): + return data[:-2] + StringEncoder.encode("\r") + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CR") - return data[:-1] + "\r" + return data[:-1] + StringEncoder.encode("\r") # Otherwise just return it as it is return data # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (3/3) TransformSafeword +# [5/11 TRANSFORM]: (3/5) TransformSafeword # ------------------------------------------------------------------------------------------------- class TransformSafeword(Transform): """Implement a trigger to emergency shutdown upon receival of a specific safeword.""" @@ -2408,18 +2433,166 @@ class TransformSafeword(Transform): # Public Functions # -------------------------------------------------------------------------- def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Raise a stop signal upon receiving the safeword. Returns: str: The string as it is without changes """ - if self.__opts.safeword in data: + if StringEncoder.encode(self.__opts.safeword) in data: self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore self.__opts.ssig.raise_terminate() return data +# ------------------------------------------------------------------------------------------------- +# [5/11 TRANSFORM]: (4/5) TransformHttpPack +# ------------------------------------------------------------------------------------------------- +class TransformHttpPack(Transform): + """Implement a transformation to pack data into HTTP packets.""" + + # -------------------------------------------------------------------------- + # Constructor / Destructor + # -------------------------------------------------------------------------- + def __init__(self, opts): + # type: (Dict[str, str]) -> None + """Set specific options for this transformer. + + Args: + opts (DsTransformLinefeed): Transformer options. + + """ + super(TransformHttpPack, self).__init__() + self.__opts = opts + self.__log = logging.getLogger(__name__) + + assert "reply" in opts + assert opts["reply"] in ["request", "response"] + + # Initial default header + self.__headers = [ + "Accept-Charset: utf-8", + ] + + self.__response_headers_sent = False + + # -------------------------------------------------------------------------- + # Public Functions + # -------------------------------------------------------------------------- + def transform(self, data): + # type: (bytes) -> bytes + """Wrap data into a HTTP packet. + + Returns: + bytes: The wrapped string. + """ + request_header = [ + "POST / HTTP/1.1", + "Host: {}".format(self.__opts["host"]), + "User-Agent: pwncat", + "Accept: */*", + "Conent-Length: {}".format(len(data)), + "Content-Type: text/plain; charset=UTF-8", + ] + response_header = [ + "HTTP/1.1 200 OK", + "Date: {}".format(self.__get_date()), + "Server: pwncat", + "Conent-Length: {}".format(len(data)), + "Connection: close", + ] + + self.__response_headers_sent = True + + if self.__opts["reply"] == "request": + header = StringEncoder.encode( + "\n".join(request_header) + "\n" + "\n".join(self.__headers) + "\n\n" + ) + else: + header = StringEncoder.encode( + "\n".join(response_header) + "\n" + "\n".join(self.__headers) + "\n\n" + ) + return header + data + + # -------------------------------------------------------------------------- + # Private Functions + # -------------------------------------------------------------------------- + def __get_date(self): # pylint: disable=no-self-use + # type: () -> str + now = datetime.utcnow() + weekday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][now.weekday()] + month = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ][now.month - 1] + return "%s, %02d %s %04d %02d:%02d:%02d GMT" % ( + weekday, + now.day, + month, + now.year, + now.hour, + now.minute, + now.second, + ) + + +# ------------------------------------------------------------------------------------------------- +# [5/11 TRANSFORM]: (5/5) TransformHttpUnpack +# ------------------------------------------------------------------------------------------------- +class TransformHttpUnpack(Transform): + """Implement a transformation to unpack data from HTTP packets.""" + + # -------------------------------------------------------------------------- + # Constructor / Destructor + # -------------------------------------------------------------------------- + def __init__(self, opts): + # type: (Dict[str, str]) -> None + """Set specific options for this transformer. + + Args: + opts (DsTransformLinefeed): Transformer options. + + """ + super(TransformHttpUnpack, self).__init__() + self.__opts = opts + self.__log = logging.getLogger(__name__) + + # -------------------------------------------------------------------------- + # Public Functions + # -------------------------------------------------------------------------- + def transform(self, data): + # type: (bytes) -> bytes + """Unwrap data from a HTTP packet. + + Returns: + str: The wrapped string. + """ + request = StringEncoder.encode(r"^(GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH)") + response = StringEncoder.encode(r"^HTTP/[.0-9]+") + + # Did not receive a valid HTTP request, so we return the original untransformed message + if not (re.match(request, data) or re.match(response, data)): + return data + + body = StringEncoder.encode(r"(\r\n\r\n|\n\n)(.*)") + match = re.search(body, data) + + # Check if we can separate headers and body + if match is None or len(match.group()) < 2: + return data + return match.group(2) + + # ################################################################################################# # ################################################################################################# # ### @@ -2482,7 +2655,7 @@ class IO(ABC): # type: ignore # -------------------------------------------------------------------------- @abstractmethod def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Implement a generator function which constantly yields data. The data could be from various sources such as: received from a socket, @@ -2494,7 +2667,7 @@ class IO(ABC): # type: ignore @abstractmethod def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Define a consumer callback which will apply an action on the producer output. Args: @@ -2575,7 +2748,7 @@ class IONetwork(IO): # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Network receive generator which hooks into the receive function and adds features. Yields: @@ -2637,7 +2810,7 @@ class IONetwork(IO): return def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Send data to a socket.""" try: self.__net.send(data) @@ -2949,7 +3122,7 @@ class IONetworkScanner(IO): for reg in self.BANNER_REG_COMP: match = re.search(reg, banner) if match: - return match.group(1).rstrip() + return StringEncoder.rstrip(match.group(1)) # type: ignore # Nothing found, return first non-empty line for line in lines: @@ -2991,7 +3164,7 @@ class IONetworkScanner(IO): return (True, None) def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Port scanner yielding open/closed string for given port. Args: @@ -3060,23 +3233,25 @@ class IONetworkScanner(IO): # [6/7] Evaluation if banner is not None and succ_banner: - yield "[+] {:>5}/{} open ({}): {}".format( + msg = "[+] {:>5}/{} open ({}): {}".format( port, self.__sock.get_type_name(sock_type), self.__sock.get_family_name(family), banner, ) + yield self.__enc.encode(msg) if banner is None and succ_banner: - yield "[+] {:>5}/{} open ({})".format( + msg = "[+] {:>5}/{} open ({})".format( port, self.__sock.get_type_name(sock_type), self.__sock.get_family_name(family), ) + yield self.__enc.encode(msg) # [7/7] Cleanup self.__sock.close(sock, key) del self.__local_binds[key] def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Print received data to stdout.""" # For issues with flush (when using tail -F or equal) see links below: # https://stackoverflow.com/questions/26692284 @@ -3142,12 +3317,15 @@ class IOStdinStdout(IO): # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Constantly ask for user input. Yields: str: Data read from stdin. """ + # On --send-on-eof we will return all of its contents at once: + lines = [] + # https://stackoverflow.com/questions/1450393/#38670261 # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time @@ -3175,20 +3353,29 @@ class IOStdinStdout(IO): if data: self.log.debug("Received %d bytes from STDIN", len(data)) self.log.trace("Received: %s", repr(data)) # type: ignore - yield data + # [send-on-eof] Append data + if self.__opts.send_on_eof: + lines.append(data) + else: + yield data # EOF or + else: - # NOTE: logging is disabled as it produces way too many messages per second. - # self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.producer") # type: ignore + # [send-on-eof] Dump data before quitting + if lines and self.__opts.send_on_eof: + yield StringEncoder.encode("").join(lines) self.ssig.raise_stdin_quit() def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Print received data to stdout.""" - # For issues with flush (when using tail -F or equal) see links below: - # https://stackoverflow.com/questions/26692284 - # https://docs.python.org/3/library/signal.html#note-on-sigpipe - print(data, end="") + if self.__py3: + sys.stdout.buffer.write(data) + else: + # For issues with flush (when using tail -F or equal) see links below: + # https://stackoverflow.com/questions/26692284 + # https://docs.python.org/3/library/signal.html#note-on-sigpipe + print(data, end="") + try: sys.stdout.flush() except (BrokenPipeError, IOError): @@ -3328,7 +3515,7 @@ class IOCommand(IO): # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Constantly ask for input. Yields: @@ -3351,19 +3538,18 @@ class IOCommand(IO): self.ssig.raise_command_quit() self.__cleanup() return - yield self.__opts.enc.decode(data) + yield data def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Send data received to stdin (command input). Args: data (str): Command to execute. """ assert self.proc.stdin is not None - byte = self.__opts.enc.encode(data) - self.log.trace("Appending to stdin: %s", repr(byte)) # type: ignore - self.proc.stdin.write(byte) + self.log.trace("Appending to stdin: %s", repr(data)) # type: ignore + self.proc.stdin.write(data) self.proc.stdin.flush() def interrupt(self): @@ -3384,7 +3570,6 @@ class IOCommand(IO): ) self.proc.kill() self.__cleaned_up = True - return False # ################################################################################################# @@ -3409,13 +3594,13 @@ class PSEStore(object): @property def messages(self): - # type: () -> Dict[str, List[str]] - """`Dict[str, List[str]]`: Stores sent and received messages by its thread name.""" + # type: () -> Dict[str, List[bytes]] + """`Dict[str, List[bytes]]`: Stores sent and received messages by its thread name.""" return self.__messages @messages.setter def messages(self, value): - # type: (Dict[str, List[str]]) -> None + # type: (Dict[str, List[bytes]]) -> None self.__messages = value @property @@ -3646,7 +3831,7 @@ class Runner(object): def run_action( name, # type: str producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] ): @@ -3926,7 +4111,7 @@ class CNC(object): "/opt/python3.8/bin", ] - __PYTHON_VERSIONS = [ + __PYTHON_NAMES = [ "python", "python2", "python2.7", @@ -3958,7 +4143,7 @@ class CNC(object): # Constructor # -------------------------------------------------------------------------- def __init__(self, enc, fsend, frecv): - # type: (StringEncoder, Callable[[str], None], Callable[[], Iterator[str]]) -> None + # type: (StringEncoder, Callable[[bytes], None], Callable[..., Iterator[bytes]]) -> None """Instantiate Command and Control class. Args: @@ -4010,7 +4195,8 @@ class CNC(object): command (str): The command to execute on the remote end. """ # TODO: determine remote host line feeds and set accordingly. - self.__fsend(command + "\n") + # TODO: handle exception + self.__fsend(StringEncoder.encode(command + "\n")) def create_remote_tmpfile(self): # type: () -> Optional[str] @@ -4033,7 +4219,7 @@ class CNC(object): self.print_info("Creating tmpfile:", False, True) for response in self.__frecv(): if response: - tmpfile = response.rstrip() + tmpfile = StringEncoder.decode(response).rstrip() self.print_info("Creating tmpfile: {}".format(tmpfile), True, True) return tmpfile @@ -4075,13 +4261,17 @@ class CNC(object): """ # TODO: Make windows compatible for path in self.__PYTHON_PATHS: - for version in self.__PYTHON_VERSIONS: - python = path + "/" + version + for name in self.__PYTHON_NAMES: + + python = path + "/" + name self.print_info("Probing for: {}".format(python)) self.remote_command("test -f {p} && echo {p} || echo;".format(p=python)) - for response in self.__frecv(): - reg = re.search(r"^([.0-9]+)", response) - if response.rstrip() == python.rstrip(): + + for byte in self.__frecv(): + + response = StringEncoder.decode(byte) + match = re.search(r"^([.0-9]+)", response) + if StringEncoder.rstrip(response) == StringEncoder.rstrip(python): self.print_info("Potential path: {}".format(python)) command = [] command.append("{} -c '".format(python)) @@ -4092,18 +4282,18 @@ class CNC(object): data = "".join(command) self.remote_command(data) continue - if reg: - match = reg.group(1) - if match[0] == "2": + if match: + version = match.group(1) + if version[0] == "2": self.__py3 = False - elif match[0] == "3": + elif version[0] == "3": self.__py3 = True else: - self.print_info( - "Could not determine major version: {}".format(reg.group(1)) - ) + self.print_info("Could not determine major version: {}".format(version)) return False - self.print_info("Found valid Python{} version: {}".format(match[0], match)) + self.print_info( + "Found valid Python{} version: {}".format(version[0], version) + ) self.__python = python return True # Nothing matched, break the innter loop @@ -4130,7 +4320,7 @@ class CNC(object): self.print_info( "Uploading: {} -> {} ({}/{})".format(lpath, rpath, curr, count), False, True ) - b64 = self.__enc.base64_encode(line) + b64 = StringEncoder.decode(base64.b64encode(StringEncoder.encode(line))) if first: self.remote_command('echo "{}" > {}'.format(b64, rpath)) first = False @@ -4177,8 +4367,8 @@ class CNCAutoDeploy(CNC): def __init__( self, enc, # type: StringEncoder - send, # type: Callable[[str], None] - recv, # type: Callable[[], Iterator[str]] + send, # type: Callable[[bytes], None] + recv, # type: Callable[[], Iterator[bytes]] cmd, # type: str host, # type: str ports, # type: List[int] @@ -4732,6 +4922,15 @@ CR on MacOS). default=False, help="""Do not resolve DNS. +""", + ) + optional.add_argument( + "--send-on-eof", + action="store_true", + default=False, + help="""Buffer data received on stdin until EOF and send +everything in one chunk. + """, ) optional.add_argument( @@ -5226,7 +5425,7 @@ The default is to send a null byte sting: '\\0'. sys.exit(1) # Deny unimplemented modes - if args.http or args.https: + if args.https: print("Unimplemented options", file=sys.stderr) sys.exit(1) @@ -5349,7 +5548,7 @@ def main(): mod = IOCommand(ssig, DsIOCommand(enc, args.cmd, POPEN_BUFSIZE)) # Use output module else: - mod = IOStdinStdout(ssig, DsIOStdinStdout(enc, TIMEOUT_READ_STDIN)) + mod = IOStdinStdout(ssig, DsIOStdinStdout(enc, TIMEOUT_READ_STDIN, args.send_on_eof)) # Run local port-forward # -> listen locally and forward traffic to remote (connect) @@ -5433,7 +5632,7 @@ def main(): DsCallableProducer(net.producer, port), # Send port scans net.consumer, # Output results [net.interrupt], - transformers, + [], None, ), ) @@ -5450,6 +5649,14 @@ def main(): cnc_cmd, cnc_host, cnc_port = args.self_inject.split(":") cnc_ports = ArgValidator.get_port_list_from_string(cnc_port) CNCAutoDeploy(enc, net.consumer, net.producer, cnc_cmd, cnc_host, cnc_ports) + + if args.http: + trans_recv = [TransformHttpUnpack({})] + transformers + trans_send = [TransformHttpPack({"host": host, "reply": "response"})] + transformers + else: + trans_recv = transformers + trans_send = transformers + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", @@ -5457,7 +5664,7 @@ def main(): DsCallableProducer(net.producer), # receive data mod.consumer, [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err - transformers, + trans_recv, code_recv, ), ) @@ -5467,7 +5674,7 @@ def main(): DsCallableProducer(mod.producer), net.consumer, # send data [mod.interrupt], # Externally stop the produer itself - transformers, + trans_send, code_send, ), ) @@ -5478,6 +5685,14 @@ def main(): net = IONetwork( ssig, enc, host, ports + args.reconn_robin, "client", srv_opts, cli_opts, sock_opts ) + + if args.http: + trans_recv = [TransformHttpUnpack({})] + transformers + trans_send = [TransformHttpPack({"host": host, "reply": "response"})] + transformers + else: + trans_recv = transformers + trans_send = transformers + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", @@ -5485,7 +5700,7 @@ def main(): DsCallableProducer(net.producer), # receive data mod.consumer, [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err - transformers, + trans_recv, code_recv, ), ) @@ -5495,7 +5710,7 @@ def main(): DsCallableProducer(mod.producer), net.consumer, # send data [net.interrupt, mod.interrupt], # Externally stop the produer itself - transformers, + trans_send, code_send, ), ) diff --git a/docs/index.html b/docs/index.html index 7648e7be..9187f760 100644 --- a/docs/index.html +++ b/docs/index.html @@ -404,6 +404,15 @@

Usage

-n, --nodns Do not resolve DNS. + --send-on-eof Buffer data received on stdin until EOF and send + everything in one chunk. + + --no-shutdown Do not shutdown into half-duplex mode. + If this option is passed, pwncat won't invoke shutdown + on a socket after seeing EOF on stdin. This is provided + for backward-compatibility with OpenBSD netcat, which + exhibits this behavior. + -v, --verbose Be verbose and print info to stderr. Use -v, -vv, -vvv or -vvvv for more verbosity. The server performance will decrease drastically if you use more than three times. diff --git a/docs/pwncat.api.html b/docs/pwncat.api.html index 02a813cf..44fda8d0 100644 --- a/docs/pwncat.api.html +++ b/docs/pwncat.api.html @@ -36,7 +36,7 @@

Module pwncat

# 4. Transformer # 5. IO modules # 6. PSE Store -# 7. IO Runner +# 7. IO Runner / InterruptHandler # 8. Command & Control # 9. Command line arguments # 10. Main entrypoint @@ -76,7 +76,7 @@

Module pwncat

# # 4. Signaling / Interrupts # ------------------------------------ -# The StopSignal instance is distributed across all Threads and and the Runner instance and +# The InterruptHandler instance is distributed across all Threads and and the Runner instance and # is a way to let other Threads know that a stop signal has been requested. # Producer/Consumer can implement their own interrupt function so they can be stopped from # inside (if they do non-blocking stuff) or from outside (if they do blocking stuff). @@ -85,17 +85,18 @@

Module pwncat

from abc import abstractmethod from abc import ABCMeta +from datetime import datetime from subprocess import PIPE from subprocess import Popen from subprocess import STDOUT import argparse -import atexit import base64 import logging import os import re import select +import signal import socket import sys import threading @@ -106,12 +107,15 @@

Module pwncat

import ipaddress except ImportError: pass +<<<<<<< HEAD # Posix terminal try: import tty import termios except ImportError: pass +======= +>>>>>>> Heavy refactoring # Windows try: import msvcrt @@ -154,12 +158,16 @@

Module pwncat

APPNAME = "pwncat" APPREPO = "https://github.com/cytopia/pwncat" +<<<<<<< HEAD VERSION = "0.0.23-alpha" +======= +VERSION = "0.1.0" +>>>>>>> Heavy refactoring # Default timeout for timeout-based sys.stdin and socket.recv -TIMEOUT_READ_STDIN = 0.1 -TIMEOUT_RECV_SOCKET = 0.1 -TIMEOUT_RECV_SOCKET_RETRY = 2 +TIMEOUT_READ_STDIN = 0.05 +TIMEOUT_RECV_SOCKET = 0.05 +TIMEOUT_RECV_SOCKET_RETRY = 1 # https://docs.python.org/3/library/subprocess.html#popen-constructor # * 0 means unbuffered (read and write are one system call and can return short) @@ -241,7 +249,7 @@

Module pwncat

# -------------------------------------------------------------------------- @property def function(self): - # type: () -> Callable[..., Iterator[str]] + # type: () -> Callable[..., Iterator[bytes]] """`IO.producer`: Callable funtcion function.""" return self.__function @@ -261,7 +269,7 @@

Module pwncat

# Contrcutor # -------------------------------------------------------------------------- def __init__(self, function, *args, **kwargs): - # type: (Callable[..., Iterator[str]], Any, Any) -> None + # type: (Callable[..., Iterator[bytes]], Any, Any) -> None self.__function = function self.__args = args self.__kwargs = kwargs @@ -284,7 +292,7 @@

Module pwncat

@property def consumer(self): - # type: () -> Callable[[str], None] + # type: () -> Callable[[bytes], None] """`IO.consumer`: Data consumer function.""" return self.__consumer @@ -312,7 +320,7 @@

Module pwncat

def __init__( self, producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] interrupts, # type: List[Callable[[], None]] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] @@ -359,10 +367,10 @@

Module pwncat

return self.__kwargs @property - def signal(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance.""" - return self.__signal + def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig # -------------------------------------------------------------------------- # Constructor @@ -370,7 +378,7 @@

Module pwncat

def __init__( self, action, # type: Callable[..., None] - signal, # type: StopSignal + ssig, # type: InterruptHandler intvl, # type: int *args, # type: Tuple[Any, ...] **kwargs # type: Dict[str, Any] @@ -379,7 +387,7 @@

Module pwncat

assert type(intvl) is int, type(intvl) assert type(kwargs) is dict, type(kwargs) self.__action = action - self.__signal = signal + self.__ssig = ssig self.__intvl = intvl self.__args = args self.__kwargs = kwargs @@ -425,10 +433,10 @@

Module pwncat

return self.__kwargs @property - def signal(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance.""" - return self.__signal + def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig # -------------------------------------------------------------------------- # Constructor @@ -436,7 +444,7 @@

Module pwncat

def __init__( self, action, # type: Callable[..., None] - signal, # type: StopSignal + ssig, # type: InterruptHandler repeat, # type: int pause, # type: float *args, # type: Tuple[Any, ...] @@ -447,7 +455,7 @@

Module pwncat

assert type(pause) is float, type(pause) assert type(kwargs) is dict, type(kwargs) self.__action = action - self.__signal = signal + self.__ssig = ssig self.__repeat = repeat self.__pause = pause self.__args = args @@ -792,8 +800,8 @@

Module pwncat

# -------------------------------------------------------------------------- @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance to trigger a shutdown signal.""" + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance to trigger a shutdown signal.""" return self.__ssig @property @@ -806,7 +814,7 @@

Module pwncat

# Constructor # -------------------------------------------------------------------------- def __init__(self, ssig, safeword): - # type: (StopSignal, str) -> None + # type: (InterruptHandler, str) -> None super(DsTransformSafeword, self).__init__() self.__ssig = ssig self.__safeword = safeword @@ -833,14 +841,21 @@

Module pwncat

"""`float`: Input timeout in seconds for non-blocking read or `None` for blocking.""" return self.__input_timeout + @property + def send_on_eof(self): + # type: () -> bool + """`float`: Determines if we buffer STDIN until EOF before sending.""" + return self.__send_on_eof + # -------------------------------------------------------------------------- # Constructor # -------------------------------------------------------------------------- - def __init__(self, encoder, input_timeout): - # type: (StringEncoder, Optional[float]) -> None + def __init__(self, encoder, input_timeout, send_on_eof): + # type: (StringEncoder, Optional[float], bool) -> None super(DsIOStdinStdout, self).__init__() self.__enc = encoder self.__input_timeout = input_timeout + self.__send_on_eof = send_on_eof # ------------------------------------------------------------------------------------------------- @@ -896,7 +911,7 @@

Module pwncat

# ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (1/4) TraceLogger +# [3/11 LIBRARY CLASSES]: (1/3) TraceLogger # ------------------------------------------------------------------------------------------------- class TraceLogger(logging.getLoggerClass()): # type: ignore """Extend Python's default logger class with TRACE level logging.""" @@ -936,7 +951,7 @@

Module pwncat

# ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (2/4) ColoredLogFormatter +# [3/11 LIBRARY CLASSES]: (2/3) ColoredLogFormatter # ------------------------------------------------------------------------------------------------- class ColoredLogFormatter(logging.Formatter): """Custom log formatter which adds different details and color support.""" @@ -1009,7 +1024,7 @@

Module pwncat

# ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (3/4) StringEncoder +# [3/11 LIBRARY CLASSES]: (3/3) StringEncoder # ------------------------------------------------------------------------------------------------- class StringEncoder(object): """Takes care about Python 2/3 string encoding/decoding. @@ -1018,72 +1033,73 @@

Module pwncat

classes or functions as strings to keep full Python 2/3 compat. """ - # -------------------------------------------------------------------------- - # Constructor - # -------------------------------------------------------------------------- - def __init__(self): - # type: () -> None - """Create a StringEncoder instance which converts str/bytes according to Python version.""" - self.__py3 = sys.version_info >= (3, 0) # type: bool - - # https://stackoverflow.com/questions/606191/27527728#27527728 - self.__codec = "cp437" - self.__fallback = "latin-1" + CODECS = [ + "utf-8", + "cp437", + "latin-1", + ] # -------------------------------------------------------------------------- - # Public Functions - # -------------------------------------------------------------------------- - def encode(self, data): + # Class methods + # -------------------------------------------------------------------------- + @classmethod + def rstrip(cls, data, search=None): + # type: (Union[bytes, str], Optional[str]) -> Union[bytes, str] + """Implementation of rstring which works on bytes or strings.""" + # We have a bytes object in Python3 + if sys.version_info >= (3, 0) and type(data) is not str: + # Strip whitespace + if search is None: + while True: + new = data + new = cls.rstrip(new, " ") + new = cls.rstrip(new, "\n") + new = cls.rstrip(new, "\r") + new = cls.rstrip(new, "\t") + # Loop until no more changes occur + if new == data: + return new + else: + bsearch = StringEncoder.encode(search) + while data[-1:] == bsearch: + data = data[:-1] + return data + + # Use native function + if search is None: + return data.rstrip() + return data.rstrip(search) # type: ignore + + @classmethod + def encode(cls, data): # type: (str) -> bytes """Convert string into a byte type for Python3.""" - if self.__py3: - try: - return data.encode(self.__codec) - except UnicodeEncodeError: - # TODO: Add logging - return data.encode(self.__fallback) + if sys.version_info >= (3, 0): + for codec in cls.CODECS: + # On the last codec, do not catch the exception and let it trigger if it fails + if codec == cls.CODECS[-1]: + return data.encode(codec) + try: + return data.encode(codec) + except UnicodeEncodeError: + pass return data # type: ignore - def decode(self, data): + @classmethod + def decode(cls, data): # type: (bytes) -> str """Convert bytes into a string type for Python3.""" - if self.__py3: - return data.decode(self.__codec) + if sys.version_info >= (3, 0): + for codec in cls.CODECS: + # On the last codec, do not catch the exception and let it trigger if it fails + if codec == cls.CODECS[-1]: + return data.decode(codec) + try: + return data.decode(codec) + except UnicodeDecodeError: + pass return data # type: ignore - def base64_encode(self, data): - # type: (str) -> str - """Convert string into a base64 encoded string.""" - return self.decode(base64.b64encode(self.encode(data))) - - -# ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (4/4): StopSignal -# ------------------------------------------------------------------------------------------------- -class StopSignal(object): - """Provide a simple boolean switch.""" - - # -------------------------------------------------------------------------- - # Constructor - # -------------------------------------------------------------------------- - def __init__(self): - # type: () -> None - """Create a StopSignal instance.""" - self.__stop = False - - # -------------------------------------------------------------------------- - # Public Functions - # -------------------------------------------------------------------------- - def has_stop(self): - # type: () -> bool - """Check if a stop signal has been raised.""" - return self.__stop - - def raise_stop(self): - # type: () -> None - """Raise a stop signal.""" - self.__stop = True - # ################################################################################################# # ################################################################################################# @@ -1097,7 +1113,7 @@

Module pwncat

# [4/11 NETWORK]: (1/1) Sock # ------------------------------------------------------------------------------------------------- class Sock(_Singleton("SingletonMeta", (object,), {})): # type: ignore - """Thread-safe singleton Socket helper to emulate a module within the same file.""" + """Thread-safe singleton Socket wrapper to emulate a module within the same file.""" def __init__(self): # type: () -> None @@ -1557,27 +1573,35 @@

Module pwncat

self.__log.error(msg) raise socket.error(msg) - def accept(self, sockets, fstop): - # type: (List[socket.socket], Callable[[], bool]) -> Tuple[socket.socket, Tuple[str, int]] + def accept( + self, + sockets, # type: List[socket.socket] + has_quit, # type: Callable[[], bool] + select_timeout=0.01, # type: float + ): + # type: (...) -> Tuple[socket.socket, Tuple[str, int]] """Accept a single connection from given list of sockets. Given sockets must be bound to an addr and listening for connections. Args: sock ([socket.socket]): List of sockets IPv4 and/or IPv6 to accept on. - fstop (Callable[[], bool]): A function that returns True if abort is requested. + has_quit (Callable[[], bool]): A function that returns True if abort is requested. + select_timeout (float): Timeout to poll sockets for connected clients. Returns: - socket.socket: Returns the connection socket (whatever protocol was faster). + (socket.socket, str, int): Returns tuple of socket, address and port of client. Raises: socket.error: Raised if server cannot accept connection or stop signal is requested. """ self.__log.debug("Waiting for TCP client") while True: - ssockets = select.select(sockets, [], [], 0.01)[0] # type: List[socket.socket] - if fstop(): - raise socket.error("StopSignal acknknowledged") + ssockets = select.select(sockets, [], [], select_timeout)[ + 0 + ] # type: List[socket.socket] + if has_quit(): + raise socket.error("SOCK-QUIT signal ACK for accept(): raised socket.error()") for sock in ssockets: try: conn, addr = sock.accept() @@ -1615,13 +1639,18 @@

Module pwncat

port (int): Port of server to connect to. Returns: - Tuple[str,int]: Adress/port tuple of local bin of the client. + Tuple[str,int]: Adress/port tuple of local bind of the client. Raises: socker.error: If client cannot connect to remote peer or custom bind did not succeed. """ - sock_family_name = self.get_family_name(sock.family) - sock_type_name = self.get_type_name(sock.type) + try: + # If the socket was already closed elsewhere, it won't have family or type anymore + sock_family_name = self.get_family_name(sock.family) + sock_type_name = self.get_type_name(sock.type) + except AttributeError as error: + raise socket.error(error) + # Bind to a custom addr/port if src_addr is not None and src_port is not None: try: @@ -1722,12 +1751,12 @@

Module pwncat

# Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, encoder, ssig, options): - # type: (StringEncoder, StopSignal, DsSock) -> None + # type: (StringEncoder, InterruptHandler, DsSock) -> None """Instantiate Sock class. Args: encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). - ssig (StopSignal): Used to stop blocking loops. + ssig (InterruptHandler): Used to stop blocking loops. options (DsSock): Instance of DsSock. """ self.__log = logging.getLogger(__name__) # type: logging.Logger @@ -1797,14 +1826,17 @@

Module pwncat

# Public Send / Receive Functions # -------------------------------------------------------------------------- def send(self, data): - # type: (str) -> int + # type: (bytes) -> int """Send data through a connected (TCP) or unconnected (UDP) socket. Args: - data (str): The data to send. + data (bytes): The data to send. Returns: int: Returns total bytes sent. + + Raises: + socket.error: Except here when unconnected or connection was forcibly closed. """ # UDP has some specialities as its socket is unconnected. # See also recv() for specialities on that side. @@ -1816,16 +1848,18 @@

Module pwncat

if not self.__active: self.__log.warning("UDP client has not yet connected. Queueing message") while not self.__active: + if self.__ssig.has_sock_quit(): + self.__log.trace( # type: ignore + "SOCK-QUIT signal ACK in Net.send (while waiting for UDP client)" + ) + return -1 time.sleep(0.01) curr = 0 # bytes send during one loop iteration send = 0 # total bytes send size = len(data) # bytes of data that needs to be send - byte = self.__enc.encode(data) - assert size == len(byte), "Encoding messed up string length, might need to do len() after." # Loop until all bytes have been send - # TODO: Does this make it impossible to send nullbytes (Ctrl+d) while send < size: self.__log.debug( "Trying to send %d bytes to %s:%d", @@ -1833,23 +1867,23 @@

Module pwncat

self.__active["remote_addr"], self.__active["remote_port"], ) - self.__log.trace("Trying to send: %s", repr(byte)) # type: ignore + self.__log.trace("Trying to send: %s", repr(data)) # type: ignore try: # Only UDP server has not made a connect() to the socket, all others # are already connected and need to use send() instead of sendto() if self.__udp_mode_server: curr = self.__active["conn"].sendto( - byte, (self.__active["remote_addr"], self.__active["remote_port"]) + data, (self.__active["remote_addr"], self.__active["remote_port"]) ) send += curr else: - curr = self.__active["conn"].send(byte) + curr = self.__active["conn"].send(data) send += curr if curr == 0: self.__log.error("No bytes send during loop round.") return 0 # Remove 'curr' many bytes from byte for the next round - byte = byte[curr:] + data = data[curr:] self.__log.debug( "Sent %d bytes to %s:%d (%d bytes remaining)", curr, @@ -1857,23 +1891,23 @@

Module pwncat

self.__active["remote_port"], size - send, ) - except (OSError, socket.error) as error: - self.__log.error("Socket OS Error: %s", error) - return send + except (BrokenPipeError, OSError, socket.error) as error: + msg = "Socket send Error: {}".format(error) + raise socket.error(msg) return send def receive(self): - # type: () -> str + # type: () -> bytes """Receive and return data from the connected (TCP) or unconnected (UDP) socket. Returns: - str: Returns received data from connected (TCP) or unconnected (UDP) socket. + bytes: Returns received data from connected (TCP) or unconnected (UDP) socket. Raises: socket.timeout: Except here to do an action when the socket is not busy. AttributeError: Except here when current instance has closed itself (Ctrl+c). socket.error: Except here when unconnected or connection was forcibly closed. - EOFError: Except here when upstream has closed the connection. + EOFError: Except here when upstream has closed the connection via EOF. """ # This is required for a UDP server that has no connected clients yet # and is waiting for data receival for the first time on either IPv4 or IPv6 @@ -1889,9 +1923,9 @@

Module pwncat

0 ] # type: List[socket.socket] # E.g.: ValueError: file descriptor cannot be a negative integer (-1) - except (ValueError, AttributeError): - msg = "Connection was closed by self." - self.__log.warning(msg) + except (ValueError, AttributeError) as error: + msg = "Connection was closed by self: [1]: {}".format(error) + self.__log.debug(msg) raise AttributeError(msg) if not conns: # This is raised for the calling function to determine what to do @@ -1903,12 +1937,12 @@

Module pwncat

conn = conns[0] # type: socket.socket try: # https://manpages.debian.org/buster/manpages-dev/recv.2.en.html - (byte, addr) = conn.recvfrom(self.__options.bufsize) + (data, addr) = conn.recvfrom(self.__options.bufsize) # [1/5] When closing itself (e.g.: via Ctrl+c and the socket_close() funcs are called) - except AttributeError: - msg = "Connection was closed by self." - self.__log.warning(msg) + except AttributeError as error: + msg = "Connection was closed by self: [2]: {}".format(error) + self.__log.debug(msg) raise AttributeError(msg) # [2/5] Connection was forcibly closed @@ -1916,14 +1950,14 @@

Module pwncat

# [Errno 10054] An existing connection was forcibly closed by the remote host # [WinError 10054] An existing connection was forcibly closed by the remote host except (OSError, socket.error) as error: - self.__log.warning("Connection error: %s", error) + self.__log.debug("Connection error: %s", error) raise socket.error(error) # [3/5] Upstream (server or client) is gone. # In TCP, there is no such thing as an empty message, so zero means a peer disconnect. # In UDP, there is no such thing as a peer disconnect, so zero means an empty datagram. - if not byte: - msg = "Upstream has closed the connection." + if not data: + msg = "EOF: Remote finished sending." self.__log.info(msg) raise EOFError(msg) @@ -1961,7 +1995,6 @@

Module pwncat

} # [5/5] We have data to process - data = self.__enc.decode(byte) self.__log.debug( "Received %d bytes from %s:%d", len(data), @@ -2198,24 +2231,27 @@

Module pwncat

return False # (2/3) Accept + remove = {} try: conn, client = self.__sock.accept( - [conns[family]["sock"] for family in conns], self.__ssig.has_stop + [conns[family]["sock"] for family in conns], self.__ssig.has_sock_quit ) conns[conn.family]["conn"] = conn conns[conn.family]["remote_addr"] = client[0] conns[conn.family]["remote_port"] = client[1] except socket.error as err: - # On error, remove all bind sockets - for family in conns: - self.__log.debug( - "Removing (family %d/%s) due to: %s", - family, - self.__sock.get_family_name(family), - err, - ) - self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) - del conns[family] + remove = {family: str(err) for family in conns} + # On error, remove all bind sockets + for family in remove: + self.__log.debug( + "Removing (family %d/%s) due to: %s", + family, + self.__sock.get_family_name(family), + remove[family], + ) + self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) + del conns[family] + if not conns: return False # (3/3) Store connections @@ -2248,7 +2284,7 @@

Module pwncat

# [2/3] Accept try: conn, client = self.__sock.accept( - [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_stop + [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_sock_quit ) except socket.error: return False @@ -2289,7 +2325,7 @@

Module pwncat

# ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (1/3): Transform +# [5/11 TRANSFORM]: (1/5): Transform # ------------------------------------------------------------------------------------------------- class Transform(ABC): # type: ignore """Abstract class to for pwncat I/O transformers. @@ -2321,16 +2357,19 @@

Module pwncat

# -------------------------------------------------------------------------- @abstractmethod def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Implement a transformer function which transforms a string.. + Args: + data (bytes): data to be transformed. + Returns: - str: The transformed string. + bytes: The transformed string. """ # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (2/3) TransformLinefeed +# [5/11 TRANSFORM]: (2/5) TransformLinefeed # ------------------------------------------------------------------------------------------------- class TransformLinefeed(Transform): """Implement basic linefeed replacement.""" @@ -2353,7 +2392,7 @@

Module pwncat

# Public Functions # -------------------------------------------------------------------------- def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Transform linefeeds to CRLF, LF or CR if requested. Returns: @@ -2365,46 +2404,46 @@

Module pwncat

# ? -> No line feeds if self.__opts.crlf == "no": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Removing CRLF") return data[:-2] - if data.endswith("\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Removing LF") return data[:-1] - if data.endswith("\r"): + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Removing CR") return data[:-1] # ? -> CRLF - if self.__opts.crlf == "crlf" and not data.endswith("\r\n"): - if data.endswith("\n"): + if self.__opts.crlf == "crlf" and data[-2:] != StringEncoder.encode("\r\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CRLF") - return data[:-1] + "\r\n" - if data.endswith("\r"): + return data[:-1] + StringEncoder.encode("\r\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with CRLF") - return data[:-1] + "\r\n" + return data[:-1] + StringEncoder.encode("\r\n") # ? -> LF if self.__opts.crlf == "lf": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with LF") - return data[:-2] + "\n" - if data.endswith("\r"): + return data[:-2] + StringEncoder.encode("\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with LF") - return data[:-1] + "\n" + return data[:-1] + StringEncoder.encode("\n") # ? -> CR if self.__opts.crlf == "cr": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with CR") - return data[:-2] + "\r" - if data.endswith("\n"): + return data[:-2] + StringEncoder.encode("\r") + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CR") - return data[:-1] + "\r" + return data[:-1] + StringEncoder.encode("\r") # Otherwise just return it as it is return data # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (3/3) TransformSafeword +# [5/11 TRANSFORM]: (3/5) TransformSafeword # ------------------------------------------------------------------------------------------------- class TransformSafeword(Transform): """Implement a trigger to emergency shutdown upon receival of a specific safeword.""" @@ -2428,18 +2467,166 @@

Module pwncat

# Public Functions # -------------------------------------------------------------------------- def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Raise a stop signal upon receiving the safeword. Returns: str: The string as it is without changes """ - if self.__opts.safeword in data: - self.__log.info("Received safeword: raising stop signal.") - self.__opts.ssig.raise_stop() + if StringEncoder.encode(self.__opts.safeword) in data: + self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore + self.__opts.ssig.raise_terminate() return data +# ------------------------------------------------------------------------------------------------- +# [5/11 TRANSFORM]: (4/5) TransformHttpPack +# ------------------------------------------------------------------------------------------------- +class TransformHttpPack(Transform): + """Implement a transformation to pack data into HTTP packets.""" + + # -------------------------------------------------------------------------- + # Constructor / Destructor + # -------------------------------------------------------------------------- + def __init__(self, opts): + # type: (Dict[str, str]) -> None + """Set specific options for this transformer. + + Args: + opts (DsTransformLinefeed): Transformer options. + + """ + super(TransformHttpPack, self).__init__() + self.__opts = opts + self.__log = logging.getLogger(__name__) + + assert "reply" in opts + assert opts["reply"] in ["request", "response"] + + # Initial default header + self.__headers = [ + "Accept-Charset: utf-8", + ] + + self.__response_headers_sent = False + + # -------------------------------------------------------------------------- + # Public Functions + # -------------------------------------------------------------------------- + def transform(self, data): + # type: (bytes) -> bytes + """Wrap data into a HTTP packet. + + Returns: + bytes: The wrapped string. + """ + request_header = [ + "POST / HTTP/1.1", + "Host: {}".format(self.__opts["host"]), + "User-Agent: pwncat", + "Accept: */*", + "Conent-Length: {}".format(len(data)), + "Content-Type: text/plain; charset=UTF-8", + ] + response_header = [ + "HTTP/1.1 200 OK", + "Date: {}".format(self.__get_date()), + "Server: pwncat", + "Conent-Length: {}".format(len(data)), + "Connection: close", + ] + + self.__response_headers_sent = True + + if self.__opts["reply"] == "request": + header = StringEncoder.encode( + "\n".join(request_header) + "\n" + "\n".join(self.__headers) + "\n\n" + ) + else: + header = StringEncoder.encode( + "\n".join(response_header) + "\n" + "\n".join(self.__headers) + "\n\n" + ) + return header + data + + # -------------------------------------------------------------------------- + # Private Functions + # -------------------------------------------------------------------------- + def __get_date(self): # pylint: disable=no-self-use + # type: () -> str + now = datetime.utcnow() + weekday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][now.weekday()] + month = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ][now.month - 1] + return "%s, %02d %s %04d %02d:%02d:%02d GMT" % ( + weekday, + now.day, + month, + now.year, + now.hour, + now.minute, + now.second, + ) + + +# ------------------------------------------------------------------------------------------------- +# [5/11 TRANSFORM]: (5/5) TransformHttpUnpack +# ------------------------------------------------------------------------------------------------- +class TransformHttpUnpack(Transform): + """Implement a transformation to unpack data from HTTP packets.""" + + # -------------------------------------------------------------------------- + # Constructor / Destructor + # -------------------------------------------------------------------------- + def __init__(self, opts): + # type: (Dict[str, str]) -> None + """Set specific options for this transformer. + + Args: + opts (DsTransformLinefeed): Transformer options. + + """ + super(TransformHttpUnpack, self).__init__() + self.__opts = opts + self.__log = logging.getLogger(__name__) + + # -------------------------------------------------------------------------- + # Public Functions + # -------------------------------------------------------------------------- + def transform(self, data): + # type: (bytes) -> bytes + """Unwrap data from a HTTP packet. + + Returns: + str: The wrapped string. + """ + request = StringEncoder.encode(r"^(GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH)") + response = StringEncoder.encode(r"^HTTP/[.0-9]+") + + # Did not receive a valid HTTP request, so we return the original untransformed message + if not (re.match(request, data) or re.match(response, data)): + return data + + body = StringEncoder.encode(r"(\r\n\r\n|\n\n)(.*)") + match = re.search(body, data) + + # Check if we can separate headers and body + if match is None or len(match.group()) < 2: + return data + return match.group(2) + + # ################################################################################################# # ################################################################################################# # ### @@ -2472,8 +2659,8 @@

Module pwncat

# -------------------------------------------------------------------------- @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: Read only property to provide a StopSignal instance to IO.""" + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" return self.__ssig @property @@ -2487,11 +2674,11 @@

Module pwncat

# -------------------------------------------------------------------------- @abstractmethod def __init__(self, ssig): - # type: (StopSignal) -> None + # type: (InterruptHandler) -> None """Set specific options for this IO module. Args: - ssig (StopSignal): StopSignal instance used by the interrupter. + ssig (InterruptHandler): InterruptHandler instance used by the interrupter. """ super(IO, self).__init__() self.__ssig = ssig @@ -2502,7 +2689,7 @@

Module pwncat

# -------------------------------------------------------------------------- @abstractmethod def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Implement a generator function which constantly yields data. The data could be from various sources such as: received from a socket, @@ -2514,7 +2701,7 @@

Module pwncat

@abstractmethod def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Define a consumer callback which will apply an action on the producer output. Args: @@ -2529,8 +2716,6 @@

Module pwncat

Various producer might call blocking functions and they won't be able to stop themself as they hang on that blocking function. NOTE: This method is triggered from outside and is supposed to stop/shutdown the producer. - - You should at least implement it with "self.ssig.raise_stop()" """ @@ -2545,7 +2730,7 @@

Module pwncat

# -------------------------------------------------------------------------- def __init__( self, - ssig, # type: StopSignal + ssig, # type: InterruptHandler encoder, # type: StringEncoder host, # type: str ports, # type: List[int] @@ -2558,7 +2743,7 @@

Module pwncat

"""Create a Pwncat instance of either a server or a client. Args: - ssig (StopSignal): Stop signal instance + ssig (InterruptHandler): Instance of InterruptHandler. encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). host (str): The hostname to resolve. ports ([int]): List of ports to connect to or listen on. @@ -2576,6 +2761,9 @@

Module pwncat

self.__srv_opts = srv_opts self.__cli_opts = cli_opts + # Did we already run cleanup + self.__cleaned_up = False + # Internally store addresses for reconn or rebind functions self.__host = host self.__ports = ports @@ -2594,7 +2782,7 @@

Module pwncat

# Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Network receive generator which hooks into the receive function and adds features. Yields: @@ -2610,9 +2798,9 @@

Module pwncat

try: yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action - except socket.timeout: + except socket.timeout as err: # Let's ask the interrupter() function if we should terminate? - if not self.ssig.has_stop(): + if not self.ssig.has_sock_quit(): continue # Stop signal is raied when my own side of the network was closed. # Happened most likely that the user pressed Ctrl+c @@ -2627,12 +2815,19 @@

Module pwncat

curr_recv_timeout_retry += 1 continue # We ware all done reading, shut down - self.ssig.raise_stop() + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [1]: %s", err + ) + self.__cleanup() return - # [3/3] Upstream is gone - except (EOFError, AttributeError, socket.error): + # [3/3] Upstream is gone (in one way or another) + except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [2]: %s", err + ) + self.__cleanup() return # Do we re-accept new clients? if self.__sock_opts.udp: @@ -2642,27 +2837,39 @@

Module pwncat

continue if self.__role == "client" and self.__client_reconnect_to_server(): continue + # Inform everybody that we are quitting + self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() return def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Send data to a socket.""" - self.__net.send(data) + try: + self.__net.send(data) + except socket.error: + pass def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace( # type: ignore - "[IONetwork] socket.close was raised by calling interrupt() externally." - ) - self.__net.close_conn_sock() - self.__net.close_bind_sock() - # Raise stop signal - self.ssig.raise_stop() + self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() # -------------------------------------------------------------------------- # Private Functions # -------------------------------------------------------------------------- + def __cleanup(self): + # type: () -> None + """Cleanup function.""" + if not self.__cleaned_up: + self.log.trace("SOCK-QUIT-CLEANUP: Closing sockets") # type: ignore + self.__net.close_conn_sock() + self.__net.close_bind_sock() + self.__cleaned_up = True + def __client_reconnect_to_server(self): # type: () -> bool """Ensure the client re-connects to the remote server, if the remote server hang up. @@ -2675,13 +2882,14 @@

Module pwncat

# reconn < 0 (endlessly) # reconn > 0 (reconnect until counter reaches zero) while self.__cli_opts.reconn != 0: - # [1/6] Let's ask the interrupter() function if we should terminate? # We need a little wait here in order for the stop signal to propagate. # Don't know how fast the other threads are. - # time.sleep(0.1) - # if self.ssig.has_stop(): - # return False + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" + ) + return False # [2/6] Wait time.sleep(self.__cli_opts.reconn_wait) @@ -2689,7 +2897,10 @@

Module pwncat

# [3/6] Let's ask the interrupter() function if we should terminate? # In case the other threads were slower as the sleep time in [1/5] # we will check again here. - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" + ) return False # [4/6] Increment the port numer (if --reconn-robin has multiple) @@ -2733,7 +2944,10 @@

Module pwncat

while self.__srv_opts.rebind != 0: # [1/7] Let's ask the interrupter() function if we should terminate? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_rebind [1]" + ) return False # [2/7] Increment the port numer (if --reconn-robin has multiple) @@ -2766,7 +2980,10 @@

Module pwncat

# [6/7] Let's ask the interrupter() function if we should terminate? # In case the other threads were slower as the sleep time in [1/7] # we will check again here. - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_rebind [2]" + ) return False # [6/7] Recurse until True or reconnect count is used up @@ -2795,9 +3012,12 @@

Module pwncat

# [MAYBE] Check stop signal and otherwise try until success. while True: - time.sleep(0.1) + time.sleep(0.01) # [NO] We have a stop signal - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_reaccept_from_client" + ) return False # [YES] Re-accept indefinitely self.log.info("Re-accepting new clients") @@ -2838,7 +3058,7 @@

Module pwncat

# -------------------------------------------------------------------------- def __init__( self, - ssig, # type: StopSignal + ssig, # type: InterruptHandler encoder, # type: StringEncoder host, # type: str banner, # type: bool @@ -2849,7 +3069,7 @@

Module pwncat

"""Create a Pwncat Network Scanner instance. Args: - ssig (StopSignal): Stop signal instance + ssig (InterruptHandler): Instance of InterruptHandler. encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). host (str): The hostname to resolve. banner (bool): Determines if we do banner grabbing as well. @@ -2858,19 +3078,19 @@

Module pwncat

""" super(IONetworkScanner, self).__init__(ssig) + self.__ssig = ssig self.__enc = encoder self.__cli_opts = cli_opts self.__sock_opts = sock_opts self.__banner = banner self.__log = logging.getLogger(__name__) - self.__net = Net(encoder, ssig, sock_opts) self.__sock = Sock() self.__screen_lock = threading.Semaphore() # Keep track of local binds (addr-port) of the threaded scanner # clients as we do not want to treat them as open ports (false posistives) - self.__local_binds = [] # type: List[str] + self.__local_binds = {} # type: Dict[str, socket.socket] # Compile our regexes if using banner detection if banner: @@ -2888,13 +3108,13 @@

Module pwncat

int(socket.AF_INET), ] self.__targets = {} - try: - for family in families: + for family in families: + try: self.__targets[family] = self.__sock.gethostbyname( host, family, not self.__sock_opts.nodns ) - except socket.gaierror: - pass + except socket.gaierror: + pass # -------------------------------------------------------------------------- # Public Functions @@ -2902,18 +3122,24 @@

Module pwncat

def __get_socket(self, family): # type: (Union[socket.AddressFamily, int]) -> socket.socket """Create socket for specific address family endlessly until resources are available.""" - # The scanner is starting many threads, each creating a single socket - # and we might hit the max allowed open files limit, so we will - # endlessly ask the system for a new socket until success. - # Also adding a delay, which will give other threads the time to - # release their sockets. + # The scanner starts one thread for each port to scan. Each thread will also create + # one socket and we might hit the max_allowed_files limit (ulimit). + # That's why we loop through creating sockets until we hit a success + # as in the meantime, other threads might have already released sockets/fd's. while True: + delay = 0.0 + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner._getsocket" + ) + raise socket.error("quit") try: if self.__sock_opts.udp: return self.__sock.create_socket(family, socket.SOCK_DGRAM) return self.__sock.create_socket(family, socket.SOCK_STREAM) except socket.error: - time.sleep(0.1) + delay += 0.1 + time.sleep(delay) # This can be bigger to give the system some time to release fd's def __get_banner_version(self, banner): # type: (str) -> Optional[str] @@ -2930,7 +3156,7 @@

Module pwncat

for reg in self.BANNER_REG_COMP: match = re.search(reg, banner) if match: - return match.group(1).rstrip() + return StringEncoder.rstrip(match.group(1)) # type: ignore # Nothing found, return first non-empty line for line in lines: @@ -2949,25 +3175,30 @@

Module pwncat

payloads = self.BANNER_PAYLOADS[0] for payload in payloads: + # Break the loop on terminate signal + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner._getbanner: %s-%d", addr, port + ) + return (False, None) try: if payload is not None: sock.send(self.__enc.encode(payload)) self.__log.debug("%s:%d - payload sent: %s", addr, port, repr(payload)) - sock.settimeout(0.1) + sock.settimeout(0.5) banner = sock.recv(self.__sock_opts.bufsize) version = self.__get_banner_version(self.__enc.decode(banner)) self.__log.debug("%s:%d - respone received: %s", addr, port, repr(banner)) return (True, version) except socket.timeout: - time.sleep(0.1) continue except (OSError, socket.error): return (False, None) return (True, None) def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Port scanner yielding open/closed string for given port. Args: @@ -2982,13 +3213,25 @@

Module pwncat

# Loop over adress families for family in self.__targets: + # [1/7] Check for termination request + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner.producer" + ) + return + addr = self.__targets[family] - # [1/5] Get socket - sock = self.__get_socket(family) + # [2/7] Get socket + try: + sock = self.__get_socket(family) + sock_type = sock.type + except (AttributeError, socket.error): + # Exception is triggered due to stop stignal and we + # will abort here in that case. + return - # [2/5] Connect scan - succ_conn = False + # [3/7] Connect scan try: laddr, lport = self.__sock.connect( sock, @@ -3002,45 +3245,47 @@

Module pwncat

0.1, ) # Append local binds (addr-port) to check against during port scan - self.__local_binds.append(str(laddr + "-" + str(lport))) - succ_conn = True + key = str(laddr + "-" + str(lport)) + self.__local_binds[key] = sock except socket.error: - succ_conn = False + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + continue + + # [4/7] False positives + # Connect was successful, but against a local bind of one of our + # port scanners, so this is a false positive. + if str(addr + "-" + str(port)) in self.__local_binds: + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + del self.__local_binds[key] + continue - # [3/5] Banner grabbing + # [5/7] Banner grabbing succ_banner = True banner = None if self.__banner: (succ_banner, banner) = self.__get_banner(sock, addr, port) - # [4/5] Evaluation - if banner is not None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({}): {}".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - banner, - ) - if banner is None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({})".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - ) + # [6/7] Evaluation + if banner is not None and succ_banner: + msg = "[+] {:>5}/{} open ({}): {}".format( + port, + self.__sock.get_type_name(sock_type), + self.__sock.get_family_name(family), + banner, + ) + yield self.__enc.encode(msg) + if banner is None and succ_banner: + msg = "[+] {:>5}/{} open ({})".format( + port, self.__sock.get_type_name(sock_type), self.__sock.get_family_name(family), + ) + yield self.__enc.encode(msg) - # [5/5] Cleanup - self.__sock.close(sock, addr + "-" + str(port)) - try: - self.__local_binds.remove(str(addr + "-" + str(port))) - except ValueError: - pass + # [7/7] Cleanup + self.__sock.close(sock, key) + del self.__local_binds[key] def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Print received data to stdout.""" # For issues with flush (when using tail -F or equal) see links below: # https://stackoverflow.com/questions/26692284 @@ -3058,8 +3303,20 @@

Module pwncat

self.__screen_lock.release() def interrupt(self): - # type: (str) -> None - """Not required.""" + # type: () -> None + """Stop function that can be called externally to close this instance.""" + self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore + self.ssig.raise_sock_quit() + + # NOTE: Closing up to 65535 sockets (single thread) takes very very long + # Se we leave this up to Python itself, once the program exits. + # self.log.trace("SOCK-QUIT-CLEANUP: Closing sockets") # type: ignore + # # Double loop to prevent: Dictionary size changed during iteration + # remove = {} + # for key in self.__local_binds: + # remove[key] = self.__local_binds[key] + # for key in remove: + # self.__sock.close(remove[key], key) # ------------------------------------------------------------------------------------------------- @@ -3077,63 +3334,111 @@

Module pwncat

# Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, ssig, opts): - # type: (StopSignal, DsIOStdinStdout) -> None + # type: (InterruptHandler, DsIOStdinStdout) -> None """Set specific options for this I/O module. Args: - ssig (StopSignal): StopSignal instance. + ssig (InterruptHandler): InterruptHandler instance. opts (DsIOStdinStdout): IO options. """ super(IOStdinStdout, self).__init__(ssig) self.__opts = opts self.__py3 = sys.version_info >= (3, 0) # type: bool +<<<<<<< HEAD self.__win = os.name != "posix" # posix or nt +======= + self.__abort = False +>>>>>>> Heavy refactoring # -------------------------------------------------------------------------- # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Constantly ask for user input. Yields: str: Data read from stdin. """ + # On --send-on-eof we will return all of its contents at once: + lines = [] + # https://stackoverflow.com/questions/1450393/#38670261 # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-1") # type: ignore + if self.__abort: + self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore + return + if self.ssig.has_stdin_quit(): + self.log.trace( # type: ignore + "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]" + ) return try: +<<<<<<< HEAD data = self.__read_stdin() +======= + # TODO: select() does not work for windows on stdin/stdout + if os.name != "nt": + self.__set_input_timeout() + if self.__py3: + line = sys.stdin.buffer.readline() + else: + if sys.platform == "win32": + # Python 2 on Windows opens sys.stdin in text mode, and + # binary data that read from it becomes corrupted on \r\n. + # Setting sys.stdin to binary mode fixes that. + if hasattr(os, "O_BINARY"): + msvcrt.setmode( + sys.stdin.fileno(), os.O_BINARY, # pylint: disable=no-member + ) + line = sys.stdin.readline() # type: ignore + +>>>>>>> Heavy refactoring except EOFError: # When using select() with timeout, we don't have any input # at this point and simply continue the loop or quit if # a terminate request has been made by other threads. - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-2") # type: ignore + if self.ssig.has_stdin_quit(): + self.log.trace( # type: ignore + "STDIN-QUIT signal ACK in IOStdinStdout.producer [2]" + ) return continue +<<<<<<< HEAD if data: self.log.debug("Received %d bytes from STDIN", len(data)) self.log.trace("Received: %s", repr(data)) # type: ignore yield data +======= + if line: + self.log.debug("Received %d bytes from STDIN", len(line)) + self.log.trace("Received: %s", repr(line)) # type: ignore + # [send-on-eof] Append data + if self.__opts.send_on_eof: + lines.append(line) + else: + yield line +>>>>>>> Heavy refactoring # EOF or <Ctrl>+<d> else: - # DO NOT RETURN HERE BLINDLY, THE UPSTREAM CONNECTION MUST GO FIRST! - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-3") # type: ignore - return + # [send-on-eof] Dump data before quitting + if lines and self.__opts.send_on_eof: + yield StringEncoder.encode("").join(lines) + self.ssig.raise_stdin_quit() def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Print received data to stdout.""" - # For issues with flush (when using tail -F or equal) see links below: - # https://stackoverflow.com/questions/26692284 - # https://docs.python.org/3/library/signal.html#note-on-sigpipe - print(data, end="") + if self.__py3: + sys.stdout.buffer.write(data) + else: + # For issues with flush (when using tail -F or equal) see links below: + # https://stackoverflow.com/questions/26692284 + # https://docs.python.org/3/library/signal.html#note-on-sigpipe + print(data, end="") + try: sys.stdout.flush() except (BrokenPipeError, IOError): @@ -3145,12 +3450,14 @@

Module pwncat

def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" + # TODO: Does not work on windows as it has blocking read of stdin + self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore + self.ssig.raise_stdin_quit() + self.log.trace( # type: ignore - "[IOStdinStdout] interrupt() invoked" + "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" ) - # Raise stop signal - # TODO: Check if this is required??? - self.ssig.raise_stop() + self.__abort = True # -------------------------------------------------------------------------- # Private Functions @@ -3233,19 +3540,19 @@

Module pwncat

# Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, ssig, opts): - # type: (StopSignal, DsIOCommand) -> None + # type: (InterruptHandler, DsIOCommand) -> None """Set specific options for this I/O module. Args: - ssig (StopSignal): Instance of StopSignal. + ssig (InterruptHandler): Instance of InterruptHandler. opts (DsIOCommand): Custom module options. """ super(IOCommand, self).__init__(ssig) self.__opts = opts self.log.debug("Setting '%s' as executable", self.__opts.executable) - # Define destructor - atexit.register(self.__destruct__) + # Did we already run cleanup + self.__cleaned_up = False # Open executable to wait for commands env = os.environ.copy() @@ -3267,19 +3574,11 @@

Module pwncat

self.log.error("Specified executable '%s' not found", self.__opts.executable) sys.exit(1) - def __destruct__(self): - # type: () -> None - """Destructor.""" - self.log.trace( # type: ignore - "Killing executable: %s with pid %d", self.__opts.executable, self.proc.pid - ) - self.proc.kill() - # -------------------------------------------------------------------------- # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Constantly ask for input. Yields: @@ -3287,44 +3586,60 @@

Module pwncat

""" assert self.proc.stdout is not None while True: - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged in Command") # type: ignore + if self.ssig.has_command_quit(): + self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.__cleanup() return self.log.trace("Reading command output") # type: ignore +<<<<<<< HEAD # Byte-wise reading is required to make it work for remote ends being in raw mode # However, the performance of self.proc.stdout.readline() is way faster. # To improve performance we will get rid of all other logging calls here. data = self.proc.stdout.read(1) +======= + # Much better performance than self.proc.read(1) + # TODO: check if self.proc.read(1) might be better in raw mode + data = self.proc.stdout.readline() +>>>>>>> Heavy refactoring self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: - self.log.trace("Command output was empty. Exiting loop.") # type: ignore - break - yield self.__opts.enc.decode(data) + self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + return + yield data def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Send data received to stdin (command input). Args: data (str): Command to execute. """ assert self.proc.stdin is not None - byte = self.__opts.enc.encode(data) - self.log.trace("Appending to stdin: %s", repr(byte)) # type: ignore - self.proc.stdin.write(byte) + self.log.trace("Appending to stdin: %s", repr(data)) # type: ignore + self.proc.stdin.write(data) self.proc.stdin.flush() def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace( # type: ignore - "[IOCommand] subprocess.kill() was raised by input_unterrupter()" - ) - self.proc.kill() - # Raise stop signal - # TODO: Check if this is required??? - self.ssig.raise_stop() - + self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + + def __cleanup(self): + # type: () -> None + """Cleanup function.""" + if not self.__cleaned_up: + self.log.trace( # type: ignore + "CMD-QUIT-CLEANUP: killing executable: %s with pid %d", + self.__opts.executable, + self.proc.pid, + ) + self.proc.kill() + self.__cleaned_up = True + # ################################################################################################# # ################################################################################################# @@ -3343,18 +3658,18 @@

Module pwncat

The same instance of this class will be available to your send and receive scripts that allow you to exchange data or manipulate themselves. You even have access to the currently used instance of the networking class to manipulate the active socket. - As well as to the logger and StopSignal instances. + As well as to the logger and InterruptHandler instances. """ @property def messages(self): - # type: () -> Dict[str, List[str]] - """`Dict[str, List[str]]`: Stores sent and received messages by its thread name.""" + # type: () -> Dict[str, List[bytes]] + """`Dict[str, List[bytes]]`: Stores sent and received messages by its thread name.""" return self.__messages @messages.setter def messages(self, value): - # type: (Dict[str, List[str]]) -> None + # type: (Dict[str, List[bytes]]) -> None self.__messages = value @property @@ -3370,8 +3685,8 @@

Module pwncat

@property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: Instance of Logging.logger class.""" + # type: () -> InterruptHandler + """`InterruptHandler`: Instance of InterruptHandler class.""" return self.__ssig @property @@ -3387,11 +3702,11 @@

Module pwncat

return self.__log def __init__(self, ssig, net): - # type: (StopSignal, List[IONetwork]) -> None + # type: (InterruptHandler, List[IONetwork]) -> None """Instantiate the PSE class. Args: - ssig (StopSignal): Instance of the StopSignal class to force a shutdown. + ssig (InterruptHandler): Instance InterruptHandler. net (IONetwork): Instance of the current network class to manipulate the socket. """ self.__messages = {} @@ -3410,7 +3725,104 @@

Module pwncat

# ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [8/11 IO RUNNER]: (1/1) Runner +# [8/11 IO RUNNER]: (1/2) InterruptHandler +# ------------------------------------------------------------------------------------------------- +class InterruptHandler(object): + """Pwncat interrupt handler. + + It allows all threads to raise various signal on certain actions, + as well as to ask the Interrupt Handler what to do. + The Interrupt handler will internally decide (based on pwncat's + command line arguments) what to do. + """ + + # -------------------------------------------------------------------------- + # Constructor + # -------------------------------------------------------------------------- + def __init__(self, keep_open, no_shutdown): + # type: (bool, bool) -> None + """Instantiate InterruptHandler. + + Args: + keep_open (bool): `--keep-open` command line argument. + no_shutdown (bool): `--no-shutdown` command line argument. + """ + self.__log = logging.getLogger(__name__) # type: logging.Logger + self.__keep_open = keep_open + self.__no_shutdown = no_shutdown + + self.__terminate = False + self.__sock_quit = False + self.__stdin_quit = False + self.__command_quit = False + + def handler(signum, frame): # type: ignore # pylint: disable=unused-argument + self.__log.trace("Ctrl+c caught.") # type: ignore + self.raise_terminate() + + # Handle Ctrl+C + signal.signal(signal.SIGINT, handler) + + # -------------------------------------------------------------------------- + # Ask for action + # -------------------------------------------------------------------------- + def has_terminate(self): + # type: () -> bool + """`bool`: Switch to be checked if pwncat should be terminated.""" + return self.__terminate + + def has_sock_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the socket connection should be closed.""" + return self.__sock_quit + + def has_stdin_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the STDIN should be closed.""" + return self.__stdin_quit + + def has_command_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the command should be closed.""" + return self.__command_quit + + # -------------------------------------------------------------------------- + # Raise signals + # -------------------------------------------------------------------------- + def raise_terminate(self): + # type: () -> None + """Signal the application that Socket should be quit.""" + self.__log.trace("SIGNAL TERMINATE raised") # type: ignore + self.__terminate = True + self.__sock_quit = True + self.__stdin_quit = True + self.__command_quit = True + + def raise_sock_quit(self): + # type: () -> None + """Signal the application that Socket should be quit.""" + self.__log.trace("SIGNAL SOCK-QUIT raised") # type: ignore + self.__sock_quit = True + self.raise_terminate() + + def raise_stdin_quit(self): + # type: () -> None + """Signal the application that STDIN should be quit.""" + if not (self.__no_shutdown or self.__keep_open): + self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore + self.__stdin_quit = True + self.raise_terminate() + + def raise_command_quit(self): + # type: () -> None + """Signal the application that Command should be quit.""" + self.__log.trace("SIGNAL CMD-QUIT raised") # type: ignore + self.__command_quit = True + self.raise_terminate() + + +# ------------------------------------------------------------------------------------------------- +# [8/11 IO RUNNER]: (2/2) Runner # ------------------------------------------------------------------------------------------------- class Runner(object): """Runner class that takes care about putting everything into threads.""" @@ -3418,11 +3830,12 @@

Module pwncat

# -------------------------------------------------------------------------- # Constructor / Destructor # -------------------------------------------------------------------------- - def __init__(self, pse): - # type: (PSEStore) -> None + def __init__(self, ssig, pse): + # type: (InterruptHandler, PSEStore) -> None """Create a new Runner object. Args: + ssig (InterruptHandler): Instance of InterruptHandler. pse (PSEStore): Pwncat Scripting Engine store. """ self.log = logging.getLogger(__name__) @@ -3444,6 +3857,7 @@

Module pwncat

# {"name": "<thread>"} self.__threads = {} # type: Dict[str, threading.Thread] + self.__ssig = ssig self.__pse = pse # -------------------------------------------------------------------------- @@ -3486,7 +3900,7 @@

Module pwncat

def run_action( name, # type: str producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] ): @@ -3536,22 +3950,24 @@

Module pwncat

self.log.trace("[%s] Producer Stop", name) # type: ignore def run_timer(name, action, intvl, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, InterruptHandler, Any, Any) -> None """Timer run function to be thrown into a thread (Execs periodic tasks). Args: name (str): Name for logging output action (function): Function to be called in a given intervall intvl (float): Intervall at which the action function will be called - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ self.log.trace("[%s] Timer Start (exec every %f sec)", name, intvl) # type: ignore time_last = int(time.time()) while True: - if ssig.has_stop(): - self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore + if ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for timer action [%s]", name + ) return time_now = int(time.time()) if time_now > time_last + intvl: @@ -3561,7 +3977,7 @@

Module pwncat

time.sleep(0.1) def run_repeater(name, action, repeat, pause, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, float, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, float, InterruptHandler, Any, Any) -> None """Repeater run function to be thrown into a thread (Execs periodic tasks). Args: @@ -3569,23 +3985,30 @@

Module pwncat

action (function): Function to be called repeat (int): Repeat the function so many times before quitting pause (float): Pause between repeated calls - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ cycles = 1 self.log.trace("Repeater Start (%d/%d)", cycles, repeat) # type: ignore while cycles <= repeat: - if ssig.has_stop(): - self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore + if ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for repeater action [%s]", name + ) return self.log.debug("Executing repeated function (%d/%d)", cycles, repeat) action(*args, **kwargs) cycles += 1 time.sleep(pause) - # Start available action in a thread + # [1/3] Start available action in a thread for key in self.__actions: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [1]: [%s]", key + ) + break # Create Thread object thread = threading.Thread( target=run_action, @@ -3598,16 +4021,27 @@

Module pwncat

self.__actions[key].code, ), ) - thread.daemon = False + # Daemon threads are easier to kill + thread.daemon = True + # Add delay if threads cannot be started + delay = 0.0 while True: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [2]: [%s]", key + ) + break try: + # Start and break the loop upon success to go to the next thread to start thread.start() break except (RuntimeError, Exception): # pylint: disable=broad-except - time.sleep(0.1) + delay += 0.1 + time.sleep(delay) # Give the system some time to release open fd's self.__threads[key] = thread - # Start available timers in a thread + + # [2/3] Start available timers in a thread for key in self.__timers: # Create Thread object thread = threading.Thread( @@ -3617,14 +4051,15 @@

Module pwncat

key, self.__timers[key].action, self.__timers[key].intvl, - self.__timers[key].signal, + self.__timers[key].ssig, self.__timers[key].args, ), kwargs=self.__timers[key].kwargs, ) thread.daemon = False thread.start() - # Start available repeaters in a thread + + # [3/3] Start available repeaters in a thread for key in self.__repeaters: # Create Thread object thread = threading.Thread( @@ -3635,7 +4070,7 @@

Module pwncat

self.__repeaters[key].action, self.__repeaters[key].repeat, self.__repeaters[key].pause, - self.__repeaters[key].signal, + self.__repeaters[key].ssig, self.__repeaters[key].args, ), kwargs=self.__repeaters[key].kwargs, @@ -3643,22 +4078,14 @@

Module pwncat

thread.daemon = False thread.start() - def check_stop(force): - # type: (int) -> bool + def check_stop(): + # type: () -> bool """Stop threads.""" - for key in self.__threads: - if not self.__threads[key].is_alive() or force: - # TODO: How are we gonna call the stop signal now? - # # [1/3] Inform all threads (inside) about a stop signal. - # # All threads with non-blocking funcs will be able to stop themselves - # self.log.trace( # type: ignore - # "Raise stop signal: StopSignal.stop() for thread [%s]", - # self.__threads[key].getName(), - # ) - # self.__actions[key].signal.raise_stop() - # [2/3] Call external interrupters - # These will shutdown all blocking functions inside a thread, - # so that they are actually able to join + # TODO: This is a workaround for using daemon threads. + # Python < 3.3 is unable to detect Ctrl+c signal during + # thread.join() operation in a fast loop (Port scan). + if self.__ssig.has_terminate(): + for key in self.__threads: for interrupt in self.__actions[key].interrupts: self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", @@ -3667,24 +4094,53 @@

Module pwncat

self.__threads[key].getName(), ) interrupt() - # [3/3] All blocking events inside the threads are gone, now join them - self.log.trace("Joining %s", self.__threads[key].getName()) # type: ignore - self.__threads[key].join(timeout=0.1) - # If all threads have died or force is requested, then exit - if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + return True + # If all threads are done, also stop + if not all([self.__threads[key].is_alive() for key in self.__threads]): return True return False + # NOTE: This was for previous non-daemon threads + # for key in self.__threads: + # if not self.__threads[key].is_alive() or force: + # # TODO: How are we gonna call the stop signal now? + # # # [1/3] Inform all threads (inside) about a stop signal. + # # # All threads with non-blocking funcs will be able to stop themselves + # # self.log.trace( # type: ignore + # # "Raise stop signal: StopSignal.stop() for thread [%s]", + # # self.__threads[key].getName(), + # # ) + # # self.__actions[key].signal.signal_quit() + # # [2/3] Call external interrupters + # # These will shutdown all blocking functions inside a thread, + # # so that they are actually able to join + # for interrupt in self.__actions[key].interrupts: + # self.log.trace( # type: ignore + # "Call INTERRUPT: %s.%s() for %s", + # getattr(interrupt, "__self__").__class__.__name__, + # interrupt.__name__, + # self.__threads[key].getName(), + # ) + # interrupt() + # # [3/3] All blocking events inside the threads are gone, now join them + # try: + # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore + # # NOTE: The thread.join() operating will also block the signal handler + # #self.__threads[key].join(timeout=0.1) + # self.__threads[key].join() + # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore + # except RuntimeError as err: + # print(err) + # #pass + # # If all threads have died or force is requested, then exit + # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + # return True + # return False - try: - while True: - if check_stop(False): - sys.exit(0) - # Need a timeout to not skyrocket the CPU - time.sleep(0.1) - except KeyboardInterrupt: - print() - check_stop(True) - sys.exit(1) + while True: + if check_stop(): + sys.exit(0) + # Need a timeout to not skyrocket the CPU + time.sleep(0.01) # ################################################################################################# @@ -3724,7 +4180,7 @@

Module pwncat

"/opt/python3.8/bin", ] - __PYTHON_VERSIONS = [ + __PYTHON_NAMES = [ "python", "python2", "python2.7", @@ -3756,7 +4212,7 @@

Module pwncat

# Constructor # -------------------------------------------------------------------------- def __init__(self, enc, fsend, frecv): - # type: (StringEncoder, Callable[[str], None], Callable[[], Iterator[str]]) -> None + # type: (StringEncoder, Callable[[bytes], None], Callable[..., Iterator[bytes]]) -> None """Instantiate Command and Control class. Args: @@ -3808,7 +4264,8 @@

Module pwncat

command (str): The command to execute on the remote end. """ # TODO: determine remote host line feeds and set accordingly. - self.__fsend(command + "\n") + # TODO: handle exception + self.__fsend(StringEncoder.encode(command + "\n")) def create_remote_tmpfile(self): # type: () -> Optional[str] @@ -3831,7 +4288,7 @@

Module pwncat

self.print_info("Creating tmpfile:", False, True) for response in self.__frecv(): if response: - tmpfile = response.rstrip() + tmpfile = StringEncoder.decode(response).rstrip() self.print_info("Creating tmpfile: {}".format(tmpfile), True, True) return tmpfile @@ -3873,13 +4330,17 @@

Module pwncat

""" # TODO: Make windows compatible for path in self.__PYTHON_PATHS: - for version in self.__PYTHON_VERSIONS: - python = path + "/" + version + for name in self.__PYTHON_NAMES: + + python = path + "/" + name self.print_info("Probing for: {}".format(python)) self.remote_command("test -f {p} && echo {p} || echo;".format(p=python)) - for response in self.__frecv(): - reg = re.search(r"^([.0-9]+)", response) - if response.rstrip() == python.rstrip(): + + for byte in self.__frecv(): + + response = StringEncoder.decode(byte) + match = re.search(r"^([.0-9]+)", response) + if StringEncoder.rstrip(response) == StringEncoder.rstrip(python): self.print_info("Potential path: {}".format(python)) command = [] command.append("{} -c '".format(python)) @@ -3890,18 +4351,18 @@

Module pwncat

data = "".join(command) self.remote_command(data) continue - if reg: - match = reg.group(1) - if match[0] == "2": + if match: + version = match.group(1) + if version[0] == "2": self.__py3 = False - elif match[0] == "3": + elif version[0] == "3": self.__py3 = True else: - self.print_info( - "Could not determine major version: {}".format(reg.group(1)) - ) + self.print_info("Could not determine major version: {}".format(version)) return False - self.print_info("Found valid Python{} version: {}".format(match[0], match)) + self.print_info( + "Found valid Python{} version: {}".format(version[0], version) + ) self.__python = python return True # Nothing matched, break the innter loop @@ -3928,7 +4389,7 @@

Module pwncat

self.print_info( "Uploading: {} -> {} ({}/{})".format(lpath, rpath, curr, count), False, True ) - b64 = self.__enc.base64_encode(line) + b64 = StringEncoder.decode(base64.b64encode(StringEncoder.encode(line))) if first: self.remote_command('echo "{}" > {}'.format(b64, rpath)) first = False @@ -3975,8 +4436,8 @@

Module pwncat

def __init__( self, enc, # type: StringEncoder - send, # type: Callable[[str], None] - recv, # type: Callable[[], Iterator[str]] + send, # type: Callable[[bytes], None] + recv, # type: Callable[[], Iterator[bytes]] cmd, # type: str host, # type: str ports, # type: List[int] @@ -4530,6 +4991,27 @@

Module pwncat

default=False, help="""Do not resolve DNS. +""", + ) + optional.add_argument( + "--send-on-eof", + action="store_true", + default=False, + help="""Buffer data received on stdin until EOF and send +everything in one chunk. + +""", + ) + optional.add_argument( + "--no-shutdown", + action="store_true", + default=False, + help="""Do not shutdown into half-duplex mode. +If this option is passed, pwncat won't invoke shutdown +on a socket after seeing EOF on stdin. This is provided +for backward-compatibility with OpenBSD netcat, which +exhibits this behavior. + """, ) optional.add_argument( @@ -5012,7 +5494,7 @@

Module pwncat

sys.exit(1) # Deny unimplemented modes - if args.http or args.https: + if args.https: print("Unimplemented options", file=sys.stderr) sys.exit(1) @@ -5112,8 +5594,8 @@

Module pwncat

# Initialize encoder enc = StringEncoder() - # Initialize StopSignal - ssig = StopSignal() + # Initialize interrupt handler + ssig = InterruptHandler(args.keep_open, args.no_shutdown) # Initialize transformers transformers = [] @@ -5135,7 +5617,7 @@

Module pwncat

mod = IOCommand(ssig, DsIOCommand(enc, args.cmd, POPEN_BUFSIZE)) # Use output module else: - mod = IOStdinStdout(ssig, DsIOStdinStdout(enc, TIMEOUT_READ_STDIN)) + mod = IOStdinStdout(ssig, DsIOStdinStdout(enc, TIMEOUT_READ_STDIN, args.send_on_eof)) # Run local port-forward # -> listen locally and forward traffic to remote (connect) @@ -5149,7 +5631,7 @@

Module pwncat

net_srv = IONetwork(ssig, enc, lhost, [lport], "server", srv_opts, cli_opts, sock_opts) net_cli = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(PSEStore(ssig, [net_srv, net_cli])) + run = Runner(ssig, PSEStore(ssig, [net_srv, net_cli])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -5184,7 +5666,7 @@

Module pwncat

net_cli_l = IONetwork(ssig, enc, lhost, [lport], "client", srv_opts, cli_opts, sock_opts) net_cli_r = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(PSEStore(ssig, [net_cli_l, net_cli_r])) + run = Runner(ssig, PSEStore(ssig, [net_cli_l, net_cli_r])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -5211,15 +5693,15 @@

Module pwncat

if mode == "scan": print("Scanning {} ports".format(len(ports))) net = IONetworkScanner(ssig, enc, host, args.banner, cli_opts, sock_opts) - run = Runner(PSEStore(ssig, [net])) + run = Runner(ssig, PSEStore(ssig, [net])) for port in ports: run.add_action( "PORT-{}".format(port), DsRunnerAction( DsCallableProducer(net.producer, port), # Send port scans net.consumer, # Output results + [net.interrupt], [], - transformers, None, ), ) @@ -5236,14 +5718,22 @@

Module pwncat

cnc_cmd, cnc_host, cnc_port = args.self_inject.split(":") cnc_ports = ArgValidator.get_port_list_from_string(cnc_port) CNCAutoDeploy(enc, net.consumer, net.producer, cnc_cmd, cnc_host, cnc_ports) - run = Runner(PSEStore(ssig, [net])) + + if args.http: + trans_recv = [TransformHttpUnpack({})] + transformers + trans_send = [TransformHttpPack({"host": host, "reply": "response"})] + transformers + else: + trans_recv = transformers + trans_send = transformers + + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err - transformers, + trans_recv, code_recv, ), ) @@ -5253,7 +5743,7 @@

Module pwncat

DsCallableProducer(mod.producer), net.consumer, # send data [mod.interrupt], # Externally stop the produer itself - transformers, + trans_send, code_send, ), ) @@ -5264,14 +5754,22 @@

Module pwncat

net = IONetwork( ssig, enc, host, ports + args.reconn_robin, "client", srv_opts, cli_opts, sock_opts ) - run = Runner(PSEStore(ssig, [net])) + + if args.http: + trans_recv = [TransformHttpUnpack({})] + transformers + trans_send = [TransformHttpPack({"host": host, "reply": "response"})] + transformers + else: + trans_recv = transformers + trans_send = transformers + + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err - transformers, + trans_recv, code_recv, ), ) @@ -5281,7 +5779,7 @@

Module pwncat

DsCallableProducer(mod.producer), net.consumer, # send data [net.interrupt, mod.interrupt], # Externally stop the produer itself - transformers, + trans_send, code_send, ), ) @@ -5302,12 +5800,7 @@

Module pwncat

# [11/11 MAIN ENTRYPOINT]: (2/2) start # ------------------------------------------------------------------------------------------------- if __name__ == "__main__": - # Catch Ctrl+c and exit without error message - try: - main() - except KeyboardInterrupt: - print() - sys.exit(1) + main()
@@ -5490,6 +5983,27 @@

Functions

default=False, help="""Do not resolve DNS. +""", + ) + optional.add_argument( + "--send-on-eof", + action="store_true", + default=False, + help="""Buffer data received on stdin until EOF and send +everything in one chunk. + +""", + ) + optional.add_argument( + "--no-shutdown", + action="store_true", + default=False, + help="""Do not shutdown into half-duplex mode. +If this option is passed, pwncat won't invoke shutdown +on a socket after seeing EOF on stdin. This is provided +for backward-compatibility with OpenBSD netcat, which +exhibits this behavior. + """, ) optional.add_argument( @@ -5972,7 +6486,7 @@

Functions

sys.exit(1) # Deny unimplemented modes - if args.http or args.https: + if args.https: print("Unimplemented options", file=sys.stderr) sys.exit(1) @@ -6087,8 +6601,8 @@

Functions

# Initialize encoder enc = StringEncoder() - # Initialize StopSignal - ssig = StopSignal() + # Initialize interrupt handler + ssig = InterruptHandler(args.keep_open, args.no_shutdown) # Initialize transformers transformers = [] @@ -6110,7 +6624,7 @@

Functions

mod = IOCommand(ssig, DsIOCommand(enc, args.cmd, POPEN_BUFSIZE)) # Use output module else: - mod = IOStdinStdout(ssig, DsIOStdinStdout(enc, TIMEOUT_READ_STDIN)) + mod = IOStdinStdout(ssig, DsIOStdinStdout(enc, TIMEOUT_READ_STDIN, args.send_on_eof)) # Run local port-forward # -> listen locally and forward traffic to remote (connect) @@ -6124,7 +6638,7 @@

Functions

net_srv = IONetwork(ssig, enc, lhost, [lport], "server", srv_opts, cli_opts, sock_opts) net_cli = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(PSEStore(ssig, [net_srv, net_cli])) + run = Runner(ssig, PSEStore(ssig, [net_srv, net_cli])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -6159,7 +6673,7 @@

Functions

net_cli_l = IONetwork(ssig, enc, lhost, [lport], "client", srv_opts, cli_opts, sock_opts) net_cli_r = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(PSEStore(ssig, [net_cli_l, net_cli_r])) + run = Runner(ssig, PSEStore(ssig, [net_cli_l, net_cli_r])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -6186,15 +6700,15 @@

Functions

if mode == "scan": print("Scanning {} ports".format(len(ports))) net = IONetworkScanner(ssig, enc, host, args.banner, cli_opts, sock_opts) - run = Runner(PSEStore(ssig, [net])) + run = Runner(ssig, PSEStore(ssig, [net])) for port in ports: run.add_action( "PORT-{}".format(port), DsRunnerAction( DsCallableProducer(net.producer, port), # Send port scans net.consumer, # Output results + [net.interrupt], [], - transformers, None, ), ) @@ -6211,14 +6725,22 @@

Functions

cnc_cmd, cnc_host, cnc_port = args.self_inject.split(":") cnc_ports = ArgValidator.get_port_list_from_string(cnc_port) CNCAutoDeploy(enc, net.consumer, net.producer, cnc_cmd, cnc_host, cnc_ports) - run = Runner(PSEStore(ssig, [net])) + + if args.http: + trans_recv = [TransformHttpUnpack({})] + transformers + trans_send = [TransformHttpPack({"host": host, "reply": "response"})] + transformers + else: + trans_recv = transformers + trans_send = transformers + + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err - transformers, + trans_recv, code_recv, ), ) @@ -6228,7 +6750,7 @@

Functions

DsCallableProducer(mod.producer), net.consumer, # send data [mod.interrupt], # Externally stop the produer itself - transformers, + trans_send, code_send, ), ) @@ -6239,14 +6761,22 @@

Functions

net = IONetwork( ssig, enc, host, ports + args.reconn_robin, "client", srv_opts, cli_opts, sock_opts ) - run = Runner(PSEStore(ssig, [net])) + + if args.http: + trans_recv = [TransformHttpUnpack({})] + transformers + trans_send = [TransformHttpPack({"host": host, "reply": "response"})] + transformers + else: + trans_recv = transformers + trans_send = transformers + + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err - transformers, + trans_recv, code_recv, ), ) @@ -6256,7 +6786,7 @@

Functions

DsCallableProducer(mod.producer), net.consumer, # send data [net.interrupt, mod.interrupt], # Externally stop the produer itself - transformers, + trans_send, code_send, ), ) @@ -6804,7 +7334,7 @@

Raises

"/opt/python3.8/bin", ] - __PYTHON_VERSIONS = [ + __PYTHON_NAMES = [ "python", "python2", "python2.7", @@ -6836,7 +7366,7 @@

Raises

# Constructor # -------------------------------------------------------------------------- def __init__(self, enc, fsend, frecv): - # type: (StringEncoder, Callable[[str], None], Callable[[], Iterator[str]]) -> None + # type: (StringEncoder, Callable[[bytes], None], Callable[..., Iterator[bytes]]) -> None """Instantiate Command and Control class. Args: @@ -6888,7 +7418,8 @@

Raises

command (str): The command to execute on the remote end. """ # TODO: determine remote host line feeds and set accordingly. - self.__fsend(command + "\n") + # TODO: handle exception + self.__fsend(StringEncoder.encode(command + "\n")) def create_remote_tmpfile(self): # type: () -> Optional[str] @@ -6911,7 +7442,7 @@

Raises

self.print_info("Creating tmpfile:", False, True) for response in self.__frecv(): if response: - tmpfile = response.rstrip() + tmpfile = StringEncoder.decode(response).rstrip() self.print_info("Creating tmpfile: {}".format(tmpfile), True, True) return tmpfile @@ -6953,13 +7484,17 @@

Raises

""" # TODO: Make windows compatible for path in self.__PYTHON_PATHS: - for version in self.__PYTHON_VERSIONS: - python = path + "/" + version + for name in self.__PYTHON_NAMES: + + python = path + "/" + name self.print_info("Probing for: {}".format(python)) self.remote_command("test -f {p} && echo {p} || echo;".format(p=python)) - for response in self.__frecv(): - reg = re.search(r"^([.0-9]+)", response) - if response.rstrip() == python.rstrip(): + + for byte in self.__frecv(): + + response = StringEncoder.decode(byte) + match = re.search(r"^([.0-9]+)", response) + if StringEncoder.rstrip(response) == StringEncoder.rstrip(python): self.print_info("Potential path: {}".format(python)) command = [] command.append("{} -c '".format(python)) @@ -6970,18 +7505,18 @@

Raises

data = "".join(command) self.remote_command(data) continue - if reg: - match = reg.group(1) - if match[0] == "2": + if match: + version = match.group(1) + if version[0] == "2": self.__py3 = False - elif match[0] == "3": + elif version[0] == "3": self.__py3 = True else: - self.print_info( - "Could not determine major version: {}".format(reg.group(1)) - ) + self.print_info("Could not determine major version: {}".format(version)) return False - self.print_info("Found valid Python{} version: {}".format(match[0], match)) + self.print_info( + "Found valid Python{} version: {}".format(version[0], version) + ) self.__python = python return True # Nothing matched, break the innter loop @@ -7008,7 +7543,7 @@

Raises

self.print_info( "Uploading: {} -> {} ({}/{})".format(lpath, rpath, curr, count), False, True ) - b64 = self.__enc.base64_encode(line) + b64 = StringEncoder.decode(base64.b64encode(StringEncoder.encode(line))) if first: self.remote_command('echo "{}" > {}'.format(b64, rpath)) first = False @@ -7117,7 +7652,7 @@

Returns

self.print_info("Creating tmpfile:", False, True) for response in self.__frecv(): if response: - tmpfile = response.rstrip() + tmpfile = StringEncoder.decode(response).rstrip() self.print_info("Creating tmpfile: {}".format(tmpfile), True, True) return tmpfile @@ -7188,7 +7723,8 @@

Args

command (str): The command to execute on the remote end. """ # TODO: determine remote host line feeds and set accordingly. - self.__fsend(command + "\n") + # TODO: handle exception + self.__fsend(StringEncoder.encode(command + "\n"))
@@ -7269,8 +7805,8 @@

Raises

def __init__( self, enc, # type: StringEncoder - send, # type: Callable[[str], None] - recv, # type: Callable[[], Iterator[str]] + send, # type: Callable[[bytes], None] + recv, # type: Callable[[], Iterator[bytes]] cmd, # type: str host, # type: str ports, # type: List[int] @@ -7472,7 +8008,7 @@

Methods

# -------------------------------------------------------------------------- @property def function(self): - # type: () -> Callable[..., Iterator[str]] + # type: () -> Callable[..., Iterator[bytes]] """`IO.producer`: Callable funtcion function.""" return self.__function @@ -7492,7 +8028,7 @@

Methods

# Contrcutor # -------------------------------------------------------------------------- def __init__(self, function, *args, **kwargs): - # type: (Callable[..., Iterator[str]], Any, Any) -> None + # type: (Callable[..., Iterator[bytes]], Any, Any) -> None self.__function = function self.__args = args self.__kwargs = kwargs
@@ -7522,7 +8058,7 @@

Instance variables

@property
 def function(self):
-    # type: () -> Callable[..., Iterator[str]]
+    # type: () -> Callable[..., Iterator[bytes]]
     """`IO.producer`: Callable funtcion function."""
     return self.__function
@@ -7991,7 +8527,7 @@

Instance variables

class DsIOStdinStdout -(encoder, input_timeout) +(encoder, input_timeout, send_on_eof)

A type-safe data structure for IOStdinStdout options.

@@ -8017,14 +8553,21 @@

Instance variables

"""`float`: Input timeout in seconds for non-blocking read or `None` for blocking.""" return self.__input_timeout + @property + def send_on_eof(self): + # type: () -> bool + """`float`: Determines if we buffer STDIN until EOF before sending.""" + return self.__send_on_eof + # -------------------------------------------------------------------------- # Constructor # -------------------------------------------------------------------------- - def __init__(self, encoder, input_timeout): - # type: (StringEncoder, Optional[float]) -> None + def __init__(self, encoder, input_timeout, send_on_eof): + # type: (StringEncoder, Optional[float], bool) -> None super(DsIOStdinStdout, self).__init__() self.__enc = encoder - self.__input_timeout = input_timeout + self.__input_timeout = input_timeout + self.__send_on_eof = send_on_eof

Instance variables

@@ -8056,6 +8599,20 @@

Instance variables

return self.__input_timeout
+
var send_on_eof
+
+

float: Determines if we buffer STDIN until EOF before sending.

+
+ +Expand source code + +
@property
+def send_on_eof(self):
+    # type: () -> bool
+    """`float`: Determines if we buffer STDIN until EOF before sending."""
+    return self.__send_on_eof
+
+
@@ -8082,7 +8639,7 @@

Instance variables

@property def consumer(self): - # type: () -> Callable[[str], None] + # type: () -> Callable[[bytes], None] """`IO.consumer`: Data consumer function.""" return self.__consumer @@ -8110,7 +8667,7 @@

Instance variables

def __init__( self, producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] interrupts, # type: List[Callable[[], None]] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] @@ -8147,7 +8704,7 @@

Instance variables

@property
 def consumer(self):
-    # type: () -> Callable[[str], None]
+    # type: () -> Callable[[bytes], None]
     """`IO.consumer`: Data consumer function."""
     return self.__consumer
@@ -8198,7 +8755,7 @@

Instance variables

class DsRunnerRepeater -(action, signal, repeat, pause, *args, **kwargs) +(action, ssig, repeat, pause, *args, **kwargs)

A type-safe data structure for repeated functions for the Runner class.

@@ -8243,10 +8800,10 @@

Instance variables

return self.__kwargs @property - def signal(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance.""" - return self.__signal + def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig # -------------------------------------------------------------------------- # Constructor @@ -8254,7 +8811,7 @@

Instance variables

def __init__( self, action, # type: Callable[..., None] - signal, # type: StopSignal + ssig, # type: InterruptHandler repeat, # type: int pause, # type: float *args, # type: Tuple[Any, ...] @@ -8265,7 +8822,7 @@

Instance variables

assert type(pause) is float, type(pause) assert type(kwargs) is dict, type(kwargs) self.__action = action - self.__signal = signal + self.__ssig = ssig self.__repeat = repeat self.__pause = pause self.__args = args @@ -8343,25 +8900,25 @@

Instance variables

return self.__repeat
-
var signal
+
var ssig
-

StopSignal: StopSignal instance.

+

InterruptHandler: InterruptHandler instance.

Expand source code
@property
-def signal(self):
-    # type: () -> StopSignal
-    """`StopSignal`: StopSignal instance."""
-    return self.__signal
+def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig
class DsRunnerTimer -(action, signal, intvl, *args, **kwargs) +(action, ssig, intvl, *args, **kwargs)

A type-safe data structure for Timer functions for the Runner class.

@@ -8400,10 +8957,10 @@

Instance variables

return self.__kwargs @property - def signal(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance.""" - return self.__signal + def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig # -------------------------------------------------------------------------- # Constructor @@ -8411,7 +8968,7 @@

Instance variables

def __init__( self, action, # type: Callable[..., None] - signal, # type: StopSignal + ssig, # type: InterruptHandler intvl, # type: int *args, # type: Tuple[Any, ...] **kwargs # type: Dict[str, Any] @@ -8420,7 +8977,7 @@

Instance variables

assert type(intvl) is int, type(intvl) assert type(kwargs) is dict, type(kwargs) self.__action = action - self.__signal = signal + self.__ssig = ssig self.__intvl = intvl self.__args = args self.__kwargs = kwargs @@ -8483,18 +9040,18 @@

Instance variables

return self.__kwargs
-
var signal
+
var ssig
-

StopSignal: StopSignal instance.

+

InterruptHandler: InterruptHandler instance.

Expand source code
@property
-def signal(self):
-    # type: () -> StopSignal
-    """`StopSignal`: StopSignal instance."""
-    return self.__signal
+def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig
@@ -8892,8 +9449,8 @@

Instance variables

# -------------------------------------------------------------------------- @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance to trigger a shutdown signal.""" + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance to trigger a shutdown signal.""" return self.__ssig @property @@ -8906,7 +9463,7 @@

Instance variables

# Constructor # -------------------------------------------------------------------------- def __init__(self, ssig, safeword): - # type: (StopSignal, str) -> None + # type: (InterruptHandler, str) -> None super(DsTransformSafeword, self).__init__() self.__ssig = ssig self.__safeword = safeword @@ -8929,15 +9486,15 @@

Instance variables

var ssig
-

StopSignal: StopSignal instance to trigger a shutdown signal.

+

InterruptHandler: InterruptHandler instance to trigger a shutdown signal.

Expand source code
@property
 def ssig(self):
-    # type: () -> StopSignal
-    """`StopSignal`: StopSignal instance to trigger a shutdown signal."""
+    # type: () -> InterruptHandler
+    """`InterruptHandler`: InterruptHandler instance to trigger a shutdown signal."""
     return self.__ssig
@@ -8960,8 +9517,8 @@

Instance variables

Set specific options for this IO module.

Args

-
ssig : StopSignal
-
StopSignal instance used by the interrupter.
+
ssig : InterruptHandler
+
InterruptHandler instance used by the interrupter.
@@ -8988,8 +9545,8 @@

Args

# -------------------------------------------------------------------------- @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: Read only property to provide a StopSignal instance to IO.""" + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" return self.__ssig @property @@ -9003,11 +9560,11 @@

Args

# -------------------------------------------------------------------------- @abstractmethod def __init__(self, ssig): - # type: (StopSignal) -> None + # type: (InterruptHandler) -> None """Set specific options for this IO module. Args: - ssig (StopSignal): StopSignal instance used by the interrupter. + ssig (InterruptHandler): InterruptHandler instance used by the interrupter. """ super(IO, self).__init__() self.__ssig = ssig @@ -9018,7 +9575,7 @@

Args

# -------------------------------------------------------------------------- @abstractmethod def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Implement a generator function which constantly yields data. The data could be from various sources such as: received from a socket, @@ -9030,7 +9587,7 @@

Args

@abstractmethod def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Define a consumer callback which will apply an action on the producer output. Args: @@ -9045,8 +9602,6 @@

Args

Various producer might call blocking functions and they won't be able to stop themself as they hang on that blocking function. NOTE: This method is triggered from outside and is supposed to stop/shutdown the producer. - - You should at least implement it with "self.ssig.raise_stop()" """

Ancestors

@@ -9078,15 +9633,15 @@

Instance variables

var ssig
-

StopSignal: Read only property to provide a StopSignal instance to IO.

+

InterruptHandler: InterruptHandler instance.

Expand source code
@property
 def ssig(self):
-    # type: () -> StopSignal
-    """`StopSignal`: Read only property to provide a StopSignal instance to IO."""
+    # type: () -> InterruptHandler
+    """`InterruptHandler`: InterruptHandler instance."""
     return self.__ssig
@@ -9109,7 +9664,7 @@

Args

@abstractmethod
 def consumer(self, data):
-    # type: (str) -> None
+    # type: (bytes) -> None
     """Define a consumer callback which will apply an action on the producer output.
 
     Args:
@@ -9124,8 +9679,7 @@ 

Args

Define an interrupt function which will stop the producer.

Various producer might call blocking functions and they won't be able to stop themself as they hang on that blocking function. -NOTE: This method is triggered from outside and is supposed to stop/shutdown the producer.

-

You should at least implement it with "self.ssig.raise_stop()"

+NOTE: This method is triggered from outside and is supposed to stop/shutdown the producer.

Expand source code @@ -9138,8 +9692,6 @@

Args

Various producer might call blocking functions and they won't be able to stop themself as they hang on that blocking function. NOTE: This method is triggered from outside and is supposed to stop/shutdown the producer. - - You should at least implement it with "self.ssig.raise_stop()" """
@@ -9161,7 +9713,7 @@

Yields

@abstractmethod
 def producer(self, *args, **kwargs):
-    # type: (Any, Any) -> Iterator[str]
+    # type: (Any, Any) -> Iterator[bytes]
     """Implement a generator function which constantly yields data.
 
     The data could be from various sources such as: received from a socket,
@@ -9188,8 +9740,8 @@ 

Attributes

Set specific options for this I/O module.

Args

-
ssig : StopSignal
-
Instance of StopSignal.
+
ssig : InterruptHandler
+
Instance of InterruptHandler.
opts : DsIOCommand
Custom module options.
@@ -9208,19 +9760,19 @@

Args

# Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, ssig, opts): - # type: (StopSignal, DsIOCommand) -> None + # type: (InterruptHandler, DsIOCommand) -> None """Set specific options for this I/O module. Args: - ssig (StopSignal): Instance of StopSignal. + ssig (InterruptHandler): Instance of InterruptHandler. opts (DsIOCommand): Custom module options. """ super(IOCommand, self).__init__(ssig) self.__opts = opts self.log.debug("Setting '%s' as executable", self.__opts.executable) - # Define destructor - atexit.register(self.__destruct__) + # Did we already run cleanup + self.__cleaned_up = False # Open executable to wait for commands env = os.environ.copy() @@ -9242,19 +9794,11 @@

Args

self.log.error("Specified executable '%s' not found", self.__opts.executable) sys.exit(1) - def __destruct__(self): - # type: () -> None - """Destructor.""" - self.log.trace( # type: ignore - "Killing executable: %s with pid %d", self.__opts.executable, self.proc.pid - ) - self.proc.kill() - # -------------------------------------------------------------------------- # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Constantly ask for input. Yields: @@ -9262,43 +9806,59 @@

Args

""" assert self.proc.stdout is not None while True: - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged in Command") # type: ignore + if self.ssig.has_command_quit(): + self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.__cleanup() return self.log.trace("Reading command output") # type: ignore +<<<<<<< HEAD # Byte-wise reading is required to make it work for remote ends being in raw mode # However, the performance of self.proc.stdout.readline() is way faster. # To improve performance we will get rid of all other logging calls here. data = self.proc.stdout.read(1) +======= + # Much better performance than self.proc.read(1) + # TODO: check if self.proc.read(1) might be better in raw mode + data = self.proc.stdout.readline() +>>>>>>> Heavy refactoring self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: - self.log.trace("Command output was empty. Exiting loop.") # type: ignore - break - yield self.__opts.enc.decode(data) + self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + return + yield data def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Send data received to stdin (command input). Args: data (str): Command to execute. """ assert self.proc.stdin is not None - byte = self.__opts.enc.encode(data) - self.log.trace("Appending to stdin: %s", repr(byte)) # type: ignore - self.proc.stdin.write(byte) + self.log.trace("Appending to stdin: %s", repr(data)) # type: ignore + self.proc.stdin.write(data) self.proc.stdin.flush() def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace( # type: ignore - "[IOCommand] subprocess.kill() was raised by input_unterrupter()" - ) - self.proc.kill() - # Raise stop signal - # TODO: Check if this is required??? - self.ssig.raise_stop()
+ self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + + def __cleanup(self): + # type: () -> None + """Cleanup function.""" + if not self.__cleaned_up: + self.log.trace( # type: ignore + "CMD-QUIT-CLEANUP: killing executable: %s with pid %d", + self.__opts.executable, + self.proc.pid, + ) + self.proc.kill() + self.__cleaned_up = True

Ancestors

    @@ -9322,16 +9882,15 @@

    Args

    Expand source code
    def consumer(self, data):
    -    # type: (str) -> None
    +    # type: (bytes) -> None
         """Send data received to stdin (command input).
     
         Args:
             data (str): Command to execute.
         """
         assert self.proc.stdin is not None
    -    byte = self.__opts.enc.encode(data)
    -    self.log.trace("Appending to stdin: %s", repr(byte))  # type: ignore
    -    self.proc.stdin.write(byte)
    +    self.log.trace("Appending to stdin: %s", repr(data))  # type: ignore
    +    self.proc.stdin.write(data)
         self.proc.stdin.flush()
    @@ -9347,13 +9906,9 @@

    Args

    def interrupt(self):
         # type: () -> None
         """Stop function that can be called externally to close this instance."""
    -    self.log.trace(  # type: ignore
    -        "[IOCommand] subprocess.kill() was raised by input_unterrupter()"
    -    )
    -    self.proc.kill()
    -    # Raise stop signal
    -    # TODO: Check if this is required???
    -    self.ssig.raise_stop()
    + self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup()
    @@ -9371,7 +9926,7 @@

    Yields

    Expand source code
    def producer(self, *args, **kwargs):
    -    # type: (Any, Any) -> Iterator[str]
    +    # type: (Any, Any) -> Iterator[bytes]
         """Constantly ask for input.
     
         Yields:
    @@ -9379,19 +9934,28 @@ 

    Yields

    """ assert self.proc.stdout is not None while True: - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged in Command") # type: ignore + if self.ssig.has_command_quit(): + self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.__cleanup() return self.log.trace("Reading command output") # type: ignore +<<<<<<< HEAD # Byte-wise reading is required to make it work for remote ends being in raw mode # However, the performance of self.proc.stdout.readline() is way faster. # To improve performance we will get rid of all other logging calls here. data = self.proc.stdout.read(1) +======= + # Much better performance than self.proc.read(1) + # TODO: check if self.proc.read(1) might be better in raw mode + data = self.proc.stdout.readline() +>>>>>>> Heavy refactoring self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: - self.log.trace("Command output was empty. Exiting loop.") # type: ignore - break - yield self.__opts.enc.decode(data)
    + self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + return + yield data
    @@ -9414,8 +9978,8 @@

    Inherited members

    Create a Pwncat instance of either a server or a client.

    Args

    -
    ssig : StopSignal
    -
    Stop signal instance
    +
    ssig : InterruptHandler
    +
    Instance of InterruptHandler.
    encoder : StringEncoder
    Instance of StringEncoder (Python2/3 str/byte compat).
    host : str
    @@ -9443,7 +10007,7 @@

    Args

    # -------------------------------------------------------------------------- def __init__( self, - ssig, # type: StopSignal + ssig, # type: InterruptHandler encoder, # type: StringEncoder host, # type: str ports, # type: List[int] @@ -9456,7 +10020,7 @@

    Args

    """Create a Pwncat instance of either a server or a client. Args: - ssig (StopSignal): Stop signal instance + ssig (InterruptHandler): Instance of InterruptHandler. encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). host (str): The hostname to resolve. ports ([int]): List of ports to connect to or listen on. @@ -9474,6 +10038,9 @@

    Args

    self.__srv_opts = srv_opts self.__cli_opts = cli_opts + # Did we already run cleanup + self.__cleaned_up = False + # Internally store addresses for reconn or rebind functions self.__host = host self.__ports = ports @@ -9492,7 +10059,7 @@

    Args

    # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Network receive generator which hooks into the receive function and adds features. Yields: @@ -9508,9 +10075,9 @@

    Args

    try: yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action - except socket.timeout: + except socket.timeout as err: # Let's ask the interrupter() function if we should terminate? - if not self.ssig.has_stop(): + if not self.ssig.has_sock_quit(): continue # Stop signal is raied when my own side of the network was closed. # Happened most likely that the user pressed Ctrl+c @@ -9525,12 +10092,19 @@

    Args

    curr_recv_timeout_retry += 1 continue # We ware all done reading, shut down - self.ssig.raise_stop() + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [1]: %s", err + ) + self.__cleanup() return - # [3/3] Upstream is gone - except (EOFError, AttributeError, socket.error): + # [3/3] Upstream is gone (in one way or another) + except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [2]: %s", err + ) + self.__cleanup() return # Do we re-accept new clients? if self.__sock_opts.udp: @@ -9540,27 +10114,39 @@

    Args

    continue if self.__role == "client" and self.__client_reconnect_to_server(): continue + # Inform everybody that we are quitting + self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() return def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Send data to a socket.""" - self.__net.send(data) + try: + self.__net.send(data) + except socket.error: + pass def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace( # type: ignore - "[IONetwork] socket.close was raised by calling interrupt() externally." - ) - self.__net.close_conn_sock() - self.__net.close_bind_sock() - # Raise stop signal - self.ssig.raise_stop() + self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() # -------------------------------------------------------------------------- # Private Functions # -------------------------------------------------------------------------- + def __cleanup(self): + # type: () -> None + """Cleanup function.""" + if not self.__cleaned_up: + self.log.trace("SOCK-QUIT-CLEANUP: Closing sockets") # type: ignore + self.__net.close_conn_sock() + self.__net.close_bind_sock() + self.__cleaned_up = True + def __client_reconnect_to_server(self): # type: () -> bool """Ensure the client re-connects to the remote server, if the remote server hang up. @@ -9573,13 +10159,14 @@

    Args

    # reconn < 0 (endlessly) # reconn > 0 (reconnect until counter reaches zero) while self.__cli_opts.reconn != 0: - # [1/6] Let's ask the interrupter() function if we should terminate? # We need a little wait here in order for the stop signal to propagate. # Don't know how fast the other threads are. - # time.sleep(0.1) - # if self.ssig.has_stop(): - # return False + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" + ) + return False # [2/6] Wait time.sleep(self.__cli_opts.reconn_wait) @@ -9587,7 +10174,10 @@

    Args

    # [3/6] Let's ask the interrupter() function if we should terminate? # In case the other threads were slower as the sleep time in [1/5] # we will check again here. - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" + ) return False # [4/6] Increment the port numer (if --reconn-robin has multiple) @@ -9631,7 +10221,10 @@

    Args

    while self.__srv_opts.rebind != 0: # [1/7] Let's ask the interrupter() function if we should terminate? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_rebind [1]" + ) return False # [2/7] Increment the port numer (if --reconn-robin has multiple) @@ -9664,7 +10257,10 @@

    Args

    # [6/7] Let's ask the interrupter() function if we should terminate? # In case the other threads were slower as the sleep time in [1/7] # we will check again here. - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_rebind [2]" + ) return False # [6/7] Recurse until True or reconnect count is used up @@ -9693,9 +10289,12 @@

    Args

    # [MAYBE] Check stop signal and otherwise try until success. while True: - time.sleep(0.1) + time.sleep(0.01) # [NO] We have a stop signal - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_reaccept_from_client" + ) return False # [YES] Re-accept indefinitely self.log.info("Re-accepting new clients") @@ -9719,9 +10318,12 @@

    Methods

    Expand source code
    def consumer(self, data):
    -    # type: (str) -> None
    +    # type: (bytes) -> None
         """Send data to a socket."""
    -    self.__net.send(data)
    + try: + self.__net.send(data) + except socket.error: + pass
    @@ -9736,13 +10338,9 @@

    Methods

    def interrupt(self):
         # type: () -> None
         """Stop function that can be called externally to close this instance."""
    -    self.log.trace(  # type: ignore
    -        "[IONetwork] socket.close was raised by calling interrupt() externally."
    -    )
    -    self.__net.close_conn_sock()
    -    self.__net.close_bind_sock()
    -    # Raise stop signal
    -    self.ssig.raise_stop()
    + self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup()
    @@ -9760,7 +10358,7 @@

    Yields

    Expand source code
    def producer(self, *args, **kwargs):
    -    # type: (Any, Any) -> Iterator[str]
    +    # type: (Any, Any) -> Iterator[bytes]
         """Network receive generator which hooks into the receive function and adds features.
     
         Yields:
    @@ -9776,9 +10374,9 @@ 

    Yields

    try: yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action - except socket.timeout: + except socket.timeout as err: # Let's ask the interrupter() function if we should terminate? - if not self.ssig.has_stop(): + if not self.ssig.has_sock_quit(): continue # Stop signal is raied when my own side of the network was closed. # Happened most likely that the user pressed Ctrl+c @@ -9793,12 +10391,19 @@

    Yields

    curr_recv_timeout_retry += 1 continue # We ware all done reading, shut down - self.ssig.raise_stop() + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [1]: %s", err + ) + self.__cleanup() return - # [3/3] Upstream is gone - except (EOFError, AttributeError, socket.error): + # [3/3] Upstream is gone (in one way or another) + except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [2]: %s", err + ) + self.__cleanup() return # Do we re-accept new clients? if self.__sock_opts.udp: @@ -9808,6 +10413,10 @@

    Yields

    continue if self.__role == "client" and self.__client_reconnect_to_server(): continue + # Inform everybody that we are quitting + self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() return
    @@ -9831,8 +10440,8 @@

    Inherited members

    Create a Pwncat Network Scanner instance.

    Args

    -
    ssig : StopSignal
    -
    Stop signal instance
    +
    ssig : InterruptHandler
    +
    Instance of InterruptHandler.
    encoder : StringEncoder
    Instance of StringEncoder (Python2/3 str/byte compat).
    host : str
    @@ -9878,7 +10487,7 @@

    Args

    # -------------------------------------------------------------------------- def __init__( self, - ssig, # type: StopSignal + ssig, # type: InterruptHandler encoder, # type: StringEncoder host, # type: str banner, # type: bool @@ -9889,7 +10498,7 @@

    Args

    """Create a Pwncat Network Scanner instance. Args: - ssig (StopSignal): Stop signal instance + ssig (InterruptHandler): Instance of InterruptHandler. encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). host (str): The hostname to resolve. banner (bool): Determines if we do banner grabbing as well. @@ -9898,19 +10507,19 @@

    Args

    """ super(IONetworkScanner, self).__init__(ssig) + self.__ssig = ssig self.__enc = encoder self.__cli_opts = cli_opts self.__sock_opts = sock_opts self.__banner = banner self.__log = logging.getLogger(__name__) - self.__net = Net(encoder, ssig, sock_opts) self.__sock = Sock() self.__screen_lock = threading.Semaphore() # Keep track of local binds (addr-port) of the threaded scanner # clients as we do not want to treat them as open ports (false posistives) - self.__local_binds = [] # type: List[str] + self.__local_binds = {} # type: Dict[str, socket.socket] # Compile our regexes if using banner detection if banner: @@ -9928,13 +10537,13 @@

    Args

    int(socket.AF_INET), ] self.__targets = {} - try: - for family in families: + for family in families: + try: self.__targets[family] = self.__sock.gethostbyname( host, family, not self.__sock_opts.nodns ) - except socket.gaierror: - pass + except socket.gaierror: + pass # -------------------------------------------------------------------------- # Public Functions @@ -9942,18 +10551,24 @@

    Args

    def __get_socket(self, family): # type: (Union[socket.AddressFamily, int]) -> socket.socket """Create socket for specific address family endlessly until resources are available.""" - # The scanner is starting many threads, each creating a single socket - # and we might hit the max allowed open files limit, so we will - # endlessly ask the system for a new socket until success. - # Also adding a delay, which will give other threads the time to - # release their sockets. + # The scanner starts one thread for each port to scan. Each thread will also create + # one socket and we might hit the max_allowed_files limit (ulimit). + # That's why we loop through creating sockets until we hit a success + # as in the meantime, other threads might have already released sockets/fd's. while True: + delay = 0.0 + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner._getsocket" + ) + raise socket.error("quit") try: if self.__sock_opts.udp: return self.__sock.create_socket(family, socket.SOCK_DGRAM) return self.__sock.create_socket(family, socket.SOCK_STREAM) except socket.error: - time.sleep(0.1) + delay += 0.1 + time.sleep(delay) # This can be bigger to give the system some time to release fd's def __get_banner_version(self, banner): # type: (str) -> Optional[str] @@ -9970,7 +10585,7 @@

    Args

    for reg in self.BANNER_REG_COMP: match = re.search(reg, banner) if match: - return match.group(1).rstrip() + return StringEncoder.rstrip(match.group(1)) # type: ignore # Nothing found, return first non-empty line for line in lines: @@ -9989,25 +10604,30 @@

    Args

    payloads = self.BANNER_PAYLOADS[0] for payload in payloads: + # Break the loop on terminate signal + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner._getbanner: %s-%d", addr, port + ) + return (False, None) try: if payload is not None: sock.send(self.__enc.encode(payload)) self.__log.debug("%s:%d - payload sent: %s", addr, port, repr(payload)) - sock.settimeout(0.1) + sock.settimeout(0.5) banner = sock.recv(self.__sock_opts.bufsize) version = self.__get_banner_version(self.__enc.decode(banner)) self.__log.debug("%s:%d - respone received: %s", addr, port, repr(banner)) return (True, version) except socket.timeout: - time.sleep(0.1) continue except (OSError, socket.error): return (False, None) return (True, None) def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Port scanner yielding open/closed string for given port. Args: @@ -10022,13 +10642,25 @@

    Args

    # Loop over adress families for family in self.__targets: + # [1/7] Check for termination request + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner.producer" + ) + return + addr = self.__targets[family] - # [1/5] Get socket - sock = self.__get_socket(family) + # [2/7] Get socket + try: + sock = self.__get_socket(family) + sock_type = sock.type + except (AttributeError, socket.error): + # Exception is triggered due to stop stignal and we + # will abort here in that case. + return - # [2/5] Connect scan - succ_conn = False + # [3/7] Connect scan try: laddr, lport = self.__sock.connect( sock, @@ -10042,45 +10674,47 @@

    Args

    0.1, ) # Append local binds (addr-port) to check against during port scan - self.__local_binds.append(str(laddr + "-" + str(lport))) - succ_conn = True + key = str(laddr + "-" + str(lport)) + self.__local_binds[key] = sock except socket.error: - succ_conn = False + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + continue + + # [4/7] False positives + # Connect was successful, but against a local bind of one of our + # port scanners, so this is a false positive. + if str(addr + "-" + str(port)) in self.__local_binds: + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + del self.__local_binds[key] + continue - # [3/5] Banner grabbing + # [5/7] Banner grabbing succ_banner = True banner = None if self.__banner: (succ_banner, banner) = self.__get_banner(sock, addr, port) - # [4/5] Evaluation - if banner is not None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({}): {}".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - banner, - ) - if banner is None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({})".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - ) + # [6/7] Evaluation + if banner is not None and succ_banner: + msg = "[+] {:>5}/{} open ({}): {}".format( + port, + self.__sock.get_type_name(sock_type), + self.__sock.get_family_name(family), + banner, + ) + yield self.__enc.encode(msg) + if banner is None and succ_banner: + msg = "[+] {:>5}/{} open ({})".format( + port, self.__sock.get_type_name(sock_type), self.__sock.get_family_name(family), + ) + yield self.__enc.encode(msg) - # [5/5] Cleanup - self.__sock.close(sock, addr + "-" + str(port)) - try: - self.__local_binds.remove(str(addr + "-" + str(port))) - except ValueError: - pass + # [7/7] Cleanup + self.__sock.close(sock, key) + del self.__local_binds[key] def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Print received data to stdout.""" # For issues with flush (when using tail -F or equal) see links below: # https://stackoverflow.com/questions/26692284 @@ -10098,8 +10732,10 @@

    Args

    self.__screen_lock.release() def interrupt(self): - # type: (str) -> None - """Not required."""
    + # type: () -> None + """Stop function that can be called externally to close this instance.""" + self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore + self.ssig.raise_sock_quit()

    Ancestors

      @@ -10133,7 +10769,7 @@

      Methods

      Expand source code
      def consumer(self, data):
      -    # type: (str) -> None
      +    # type: (bytes) -> None
           """Print received data to stdout."""
           # For issues with flush (when using tail -F or equal) see links below:
           # https://stackoverflow.com/questions/26692284
      @@ -10155,14 +10791,16 @@ 

      Methods

      def interrupt(self)
    -

    Not required.

    +

    Stop function that can be called externally to close this instance.

    Expand source code
    def interrupt(self):
    -    # type: (str) -> None
    -    """Not required."""
    + # type: () -> None + """Stop function that can be called externally to close this instance.""" + self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore + self.ssig.raise_sock_quit()
    @@ -10187,7 +10825,7 @@

    Yields

    Expand source code
    def producer(self, *args, **kwargs):
    -    # type: (Any, Any) -> Iterator[str]
    +    # type: (Any, Any) -> Iterator[bytes]
         """Port scanner yielding open/closed string for given port.
     
         Args:
    @@ -10202,13 +10840,25 @@ 

    Yields

    # Loop over adress families for family in self.__targets: + # [1/7] Check for termination request + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner.producer" + ) + return + addr = self.__targets[family] - # [1/5] Get socket - sock = self.__get_socket(family) + # [2/7] Get socket + try: + sock = self.__get_socket(family) + sock_type = sock.type + except (AttributeError, socket.error): + # Exception is triggered due to stop stignal and we + # will abort here in that case. + return - # [2/5] Connect scan - succ_conn = False + # [3/7] Connect scan try: laddr, lport = self.__sock.connect( sock, @@ -10222,42 +10872,44 @@

    Yields

    0.1, ) # Append local binds (addr-port) to check against during port scan - self.__local_binds.append(str(laddr + "-" + str(lport))) - succ_conn = True + key = str(laddr + "-" + str(lport)) + self.__local_binds[key] = sock except socket.error: - succ_conn = False + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + continue + + # [4/7] False positives + # Connect was successful, but against a local bind of one of our + # port scanners, so this is a false positive. + if str(addr + "-" + str(port)) in self.__local_binds: + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + del self.__local_binds[key] + continue - # [3/5] Banner grabbing + # [5/7] Banner grabbing succ_banner = True banner = None if self.__banner: (succ_banner, banner) = self.__get_banner(sock, addr, port) - # [4/5] Evaluation - if banner is not None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({}): {}".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - banner, - ) - if banner is None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({})".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - ) + # [6/7] Evaluation + if banner is not None and succ_banner: + msg = "[+] {:>5}/{} open ({}): {}".format( + port, + self.__sock.get_type_name(sock_type), + self.__sock.get_family_name(family), + banner, + ) + yield self.__enc.encode(msg) + if banner is None and succ_banner: + msg = "[+] {:>5}/{} open ({})".format( + port, self.__sock.get_type_name(sock_type), self.__sock.get_family_name(family), + ) + yield self.__enc.encode(msg) - # [5/5] Cleanup - self.__sock.close(sock, addr + "-" + str(port)) - try: - self.__local_binds.remove(str(addr + "-" + str(port))) - except ValueError: - pass
    + # [7/7] Cleanup + self.__sock.close(sock, key) + del self.__local_binds[key]
    @@ -10283,8 +10935,8 @@

    Inherited members

    Set specific options for this I/O module.

    Args

    -
    ssig : StopSignal
    -
    StopSignal instance.
    +
    ssig : InterruptHandler
    +
    InterruptHandler instance.
    opts : DsIOStdinStdout
    IO options.
    @@ -10304,63 +10956,111 @@

    Args

    # Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, ssig, opts): - # type: (StopSignal, DsIOStdinStdout) -> None + # type: (InterruptHandler, DsIOStdinStdout) -> None """Set specific options for this I/O module. Args: - ssig (StopSignal): StopSignal instance. + ssig (InterruptHandler): InterruptHandler instance. opts (DsIOStdinStdout): IO options. """ super(IOStdinStdout, self).__init__(ssig) self.__opts = opts self.__py3 = sys.version_info >= (3, 0) # type: bool +<<<<<<< HEAD self.__win = os.name != "posix" # posix or nt +======= + self.__abort = False +>>>>>>> Heavy refactoring # -------------------------------------------------------------------------- # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Constantly ask for user input. Yields: str: Data read from stdin. """ + # On --send-on-eof we will return all of its contents at once: + lines = [] + # https://stackoverflow.com/questions/1450393/#38670261 # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-1") # type: ignore + if self.__abort: + self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore + return + if self.ssig.has_stdin_quit(): + self.log.trace( # type: ignore + "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]" + ) return try: +<<<<<<< HEAD data = self.__read_stdin() +======= + # TODO: select() does not work for windows on stdin/stdout + if os.name != "nt": + self.__set_input_timeout() + if self.__py3: + line = sys.stdin.buffer.readline() + else: + if sys.platform == "win32": + # Python 2 on Windows opens sys.stdin in text mode, and + # binary data that read from it becomes corrupted on \r\n. + # Setting sys.stdin to binary mode fixes that. + if hasattr(os, "O_BINARY"): + msvcrt.setmode( + sys.stdin.fileno(), os.O_BINARY, # pylint: disable=no-member + ) + line = sys.stdin.readline() # type: ignore + +>>>>>>> Heavy refactoring except EOFError: # When using select() with timeout, we don't have any input # at this point and simply continue the loop or quit if # a terminate request has been made by other threads. - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-2") # type: ignore + if self.ssig.has_stdin_quit(): + self.log.trace( # type: ignore + "STDIN-QUIT signal ACK in IOStdinStdout.producer [2]" + ) return continue +<<<<<<< HEAD if data: self.log.debug("Received %d bytes from STDIN", len(data)) self.log.trace("Received: %s", repr(data)) # type: ignore yield data +======= + if line: + self.log.debug("Received %d bytes from STDIN", len(line)) + self.log.trace("Received: %s", repr(line)) # type: ignore + # [send-on-eof] Append data + if self.__opts.send_on_eof: + lines.append(line) + else: + yield line +>>>>>>> Heavy refactoring # EOF or <Ctrl>+<d> else: - # DO NOT RETURN HERE BLINDLY, THE UPSTREAM CONNECTION MUST GO FIRST! - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-3") # type: ignore - return + # [send-on-eof] Dump data before quitting + if lines and self.__opts.send_on_eof: + yield StringEncoder.encode("").join(lines) + self.ssig.raise_stdin_quit() def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Print received data to stdout.""" - # For issues with flush (when using tail -F or equal) see links below: - # https://stackoverflow.com/questions/26692284 - # https://docs.python.org/3/library/signal.html#note-on-sigpipe - print(data, end="") + if self.__py3: + sys.stdout.buffer.write(data) + else: + # For issues with flush (when using tail -F or equal) see links below: + # https://stackoverflow.com/questions/26692284 + # https://docs.python.org/3/library/signal.html#note-on-sigpipe + print(data, end="") + try: sys.stdout.flush() except (BrokenPipeError, IOError): @@ -10372,12 +11072,14 @@

    Args

    def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" + # TODO: Does not work on windows as it has blocking read of stdin + self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore + self.ssig.raise_stdin_quit() + self.log.trace( # type: ignore - "[IOStdinStdout] interrupt() invoked" + "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" ) - # Raise stop signal - # TODO: Check if this is required??? - self.ssig.raise_stop() + self.__abort = True # -------------------------------------------------------------------------- # Private Functions @@ -10458,12 +11160,16 @@

    Methods

    Expand source code
    def consumer(self, data):
    -    # type: (str) -> None
    +    # type: (bytes) -> None
         """Print received data to stdout."""
    -    # For issues with flush (when using tail -F or equal) see links below:
    -    # https://stackoverflow.com/questions/26692284
    -    # https://docs.python.org/3/library/signal.html#note-on-sigpipe
    -    print(data, end="")
    +    if self.__py3:
    +        sys.stdout.buffer.write(data)
    +    else:
    +        # For issues with flush (when using tail -F or equal) see links below:
    +        # https://stackoverflow.com/questions/26692284
    +        # https://docs.python.org/3/library/signal.html#note-on-sigpipe
    +        print(data, end="")
    +
         try:
             sys.stdout.flush()
         except (BrokenPipeError, IOError):
    @@ -10485,12 +11191,14 @@ 

    Methods

    def interrupt(self):
         # type: () -> None
         """Stop function that can be called externally to close this instance."""
    +    # TODO: Does not work on windows as it has blocking read of stdin
    +    self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt")  # type: ignore
    +    self.ssig.raise_stdin_quit()
    +
         self.log.trace(  # type: ignore
    -        "[IOStdinStdout] interrupt() invoked"
    +        "[IOStdinStdout] setting __abort to True was raised by interrupt() externally"
         )
    -    # Raise stop signal
    -    # TODO: Check if this is required???
    -    self.ssig.raise_stop()
    + self.__abort = True
    @@ -10508,39 +11216,79 @@

    Yields

    Expand source code
    def producer(self, *args, **kwargs):
    -    # type: (Any, Any) -> Iterator[str]
    +    # type: (Any, Any) -> Iterator[bytes]
         """Constantly ask for user input.
     
         Yields:
             str: Data read from stdin.
         """
    +    # On --send-on-eof we will return all of its contents at once:
    +    lines = []
    +
         # https://stackoverflow.com/questions/1450393/#38670261
         # while True: line = sys.stdin.readline() <- reads a whole line (faster)
         # for line in sys.stdin.readlin():        <- reads one byte at a time
         while True:
    -        if self.ssig.has_stop():
    -            self.log.trace("Stop signal acknowledged for reading STDIN-1")  # type: ignore
    +        if self.__abort:
    +            self.log.trace("External interrupt signal triggered. Aborting.")  # type: ignore
    +            return
    +        if self.ssig.has_stdin_quit():
    +            self.log.trace(  # type: ignore
    +                "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]"
    +            )
                 return
             try:
    +<<<<<<< HEAD
                 data = self.__read_stdin()
    +=======
    +            # TODO: select() does not work for windows on stdin/stdout
    +            if os.name != "nt":
    +                self.__set_input_timeout()
    +            if self.__py3:
    +                line = sys.stdin.buffer.readline()
    +            else:
    +                if sys.platform == "win32":
    +                    # Python 2 on Windows opens sys.stdin in text mode, and
    +                    # binary data that read from it becomes corrupted on \r\n.
    +                    # Setting sys.stdin to binary mode fixes that.
    +                    if hasattr(os, "O_BINARY"):
    +                        msvcrt.setmode(
    +                            sys.stdin.fileno(), os.O_BINARY,  # pylint: disable=no-member
    +                        )
    +                line = sys.stdin.readline()  # type: ignore
    +
    +>>>>>>> Heavy refactoring
             except EOFError:
                 # When using select() with timeout, we don't have any input
                 # at this point and simply continue the loop or quit if
                 # a terminate request has been made by other threads.
    -            if self.ssig.has_stop():
    -                self.log.trace("Stop signal acknowledged for reading STDIN-2")  # type: ignore
    +            if self.ssig.has_stdin_quit():
    +                self.log.trace(  # type: ignore
    +                    "STDIN-QUIT signal ACK in IOStdinStdout.producer [2]"
    +                )
                     return
                 continue
    +<<<<<<< HEAD
             if data:
                 self.log.debug("Received %d bytes from STDIN", len(data))
                 self.log.trace("Received: %s", repr(data))  # type: ignore
                 yield data
    +=======
    +        if line:
    +            self.log.debug("Received %d bytes from STDIN", len(line))
    +            self.log.trace("Received: %s", repr(line))  # type: ignore
    +            # [send-on-eof] Append data
    +            if self.__opts.send_on_eof:
    +                lines.append(line)
    +            else:
    +                yield line
    +>>>>>>> Heavy refactoring
             # EOF or <Ctrl>+<d>
             else:
    -            # DO NOT RETURN HERE BLINDLY, THE UPSTREAM CONNECTION MUST GO FIRST!
    -            if self.ssig.has_stop():
    -                self.log.trace("Stop signal acknowledged for reading STDIN-3")  # type: ignore
    -                return
    + # [send-on-eof] Dump data before quitting + if lines and self.__opts.send_on_eof: + yield StringEncoder.encode("").join(lines) + self.ssig.raise_stdin_quit()
    @@ -10554,6 +11302,256 @@

    Inherited members

+
+class InterruptHandler +(keep_open, no_shutdown) +
+
+

Pwncat interrupt handler.

+

It allows all threads to raise various signal on certain actions, +as well as to ask the Interrupt Handler what to do. +The Interrupt handler will internally decide (based on pwncat's +command line arguments) what to do.

+

Instantiate InterruptHandler.

+

Args

+
+
keep_open : bool
+
--keep-open command line argument.
+
no_shutdown : bool
+
--no-shutdown command line argument.
+
+
+ +Expand source code + +
class InterruptHandler(object):
+    """Pwncat interrupt handler.
+
+    It allows all threads to raise various signal on certain actions,
+    as well as to ask the Interrupt Handler what to do.
+    The Interrupt handler will internally decide (based on pwncat's
+    command line arguments) what to do.
+    """
+
+    # --------------------------------------------------------------------------
+    # Constructor
+    # --------------------------------------------------------------------------
+    def __init__(self, keep_open, no_shutdown):
+        # type: (bool, bool) -> None
+        """Instantiate InterruptHandler.
+
+        Args:
+            keep_open (bool): `--keep-open` command line argument.
+            no_shutdown (bool): `--no-shutdown` command line argument.
+        """
+        self.__log = logging.getLogger(__name__)  # type: logging.Logger
+        self.__keep_open = keep_open
+        self.__no_shutdown = no_shutdown
+
+        self.__terminate = False
+        self.__sock_quit = False
+        self.__stdin_quit = False
+        self.__command_quit = False
+
+        def handler(signum, frame):  # type: ignore  # pylint: disable=unused-argument
+            self.__log.trace("Ctrl+c caught.")  # type: ignore
+            self.raise_terminate()
+
+        # Handle Ctrl+C
+        signal.signal(signal.SIGINT, handler)
+
+    # --------------------------------------------------------------------------
+    # Ask for action
+    # --------------------------------------------------------------------------
+    def has_terminate(self):
+        # type: () -> bool
+        """`bool`: Switch to be checked if pwncat should be terminated."""
+        return self.__terminate
+
+    def has_sock_quit(self):
+        # type: () -> bool
+        """`bool`: Switch to be checked if the socket connection should be closed."""
+        return self.__sock_quit
+
+    def has_stdin_quit(self):
+        # type: () -> bool
+        """`bool`: Switch to be checked if the STDIN should be closed."""
+        return self.__stdin_quit
+
+    def has_command_quit(self):
+        # type: () -> bool
+        """`bool`: Switch to be checked if the command should be closed."""
+        return self.__command_quit
+
+    # --------------------------------------------------------------------------
+    # Raise signals
+    # --------------------------------------------------------------------------
+    def raise_terminate(self):
+        # type: () -> None
+        """Signal the application that Socket should be quit."""
+        self.__log.trace("SIGNAL TERMINATE raised")  # type: ignore
+        self.__terminate = True
+        self.__sock_quit = True
+        self.__stdin_quit = True
+        self.__command_quit = True
+
+    def raise_sock_quit(self):
+        # type: () -> None
+        """Signal the application that Socket should be quit."""
+        self.__log.trace("SIGNAL SOCK-QUIT raised")  # type: ignore
+        self.__sock_quit = True
+        self.raise_terminate()
+
+    def raise_stdin_quit(self):
+        # type: () -> None
+        """Signal the application that STDIN should be quit."""
+        if not (self.__no_shutdown or self.__keep_open):
+            self.__log.trace("SIGNAL STDIN-QUIT raised")  # type: ignore
+            self.__stdin_quit = True
+            self.raise_terminate()
+
+    def raise_command_quit(self):
+        # type: () -> None
+        """Signal the application that Command should be quit."""
+        self.__log.trace("SIGNAL CMD-QUIT raised")  # type: ignore
+        self.__command_quit = True
+        self.raise_terminate()
+
+

Methods

+
+
+def has_command_quit(self) +
+
+

bool: Switch to be checked if the command should be closed.

+
+ +Expand source code + +
def has_command_quit(self):
+    # type: () -> bool
+    """`bool`: Switch to be checked if the command should be closed."""
+    return self.__command_quit
+
+
+
+def has_sock_quit(self) +
+
+

bool: Switch to be checked if the socket connection should be closed.

+
+ +Expand source code + +
def has_sock_quit(self):
+    # type: () -> bool
+    """`bool`: Switch to be checked if the socket connection should be closed."""
+    return self.__sock_quit
+
+
+
+def has_stdin_quit(self) +
+
+

bool: Switch to be checked if the STDIN should be closed.

+
+ +Expand source code + +
def has_stdin_quit(self):
+    # type: () -> bool
+    """`bool`: Switch to be checked if the STDIN should be closed."""
+    return self.__stdin_quit
+
+
+
+def has_terminate(self) +
+
+

bool: Switch to be checked if pwncat should be terminated.

+
+ +Expand source code + +
def has_terminate(self):
+    # type: () -> bool
+    """`bool`: Switch to be checked if pwncat should be terminated."""
+    return self.__terminate
+
+
+
+def raise_command_quit(self) +
+
+

Signal the application that Command should be quit.

+
+ +Expand source code + +
def raise_command_quit(self):
+    # type: () -> None
+    """Signal the application that Command should be quit."""
+    self.__log.trace("SIGNAL CMD-QUIT raised")  # type: ignore
+    self.__command_quit = True
+    self.raise_terminate()
+
+
+
+def raise_sock_quit(self) +
+
+

Signal the application that Socket should be quit.

+
+ +Expand source code + +
def raise_sock_quit(self):
+    # type: () -> None
+    """Signal the application that Socket should be quit."""
+    self.__log.trace("SIGNAL SOCK-QUIT raised")  # type: ignore
+    self.__sock_quit = True
+    self.raise_terminate()
+
+
+
+def raise_stdin_quit(self) +
+
+

Signal the application that STDIN should be quit.

+
+ +Expand source code + +
def raise_stdin_quit(self):
+    # type: () -> None
+    """Signal the application that STDIN should be quit."""
+    if not (self.__no_shutdown or self.__keep_open):
+        self.__log.trace("SIGNAL STDIN-QUIT raised")  # type: ignore
+        self.__stdin_quit = True
+        self.raise_terminate()
+
+
+
+def raise_terminate(self) +
+
+

Signal the application that Socket should be quit.

+
+ +Expand source code + +
def raise_terminate(self):
+    # type: () -> None
+    """Signal the application that Socket should be quit."""
+    self.__log.trace("SIGNAL TERMINATE raised")  # type: ignore
+    self.__terminate = True
+    self.__sock_quit = True
+    self.__stdin_quit = True
+    self.__command_quit = True
+
+
+
+
class Net (encoder, ssig, options) @@ -10565,7 +11563,7 @@

Args

encoder : StringEncoder
Instance of StringEncoder (Python2/3 str/byte compat).
-
ssig : StopSignal
+
ssig : InterruptHandler
Used to stop blocking loops.
options : DsSock
Instance of DsSock.
@@ -10581,12 +11579,12 @@

Args

# Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, encoder, ssig, options): - # type: (StringEncoder, StopSignal, DsSock) -> None + # type: (StringEncoder, InterruptHandler, DsSock) -> None """Instantiate Sock class. Args: encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). - ssig (StopSignal): Used to stop blocking loops. + ssig (InterruptHandler): Used to stop blocking loops. options (DsSock): Instance of DsSock. """ self.__log = logging.getLogger(__name__) # type: logging.Logger @@ -10656,14 +11654,17 @@

Args

# Public Send / Receive Functions # -------------------------------------------------------------------------- def send(self, data): - # type: (str) -> int + # type: (bytes) -> int """Send data through a connected (TCP) or unconnected (UDP) socket. Args: - data (str): The data to send. + data (bytes): The data to send. Returns: int: Returns total bytes sent. + + Raises: + socket.error: Except here when unconnected or connection was forcibly closed. """ # UDP has some specialities as its socket is unconnected. # See also recv() for specialities on that side. @@ -10675,16 +11676,18 @@

Args

if not self.__active: self.__log.warning("UDP client has not yet connected. Queueing message") while not self.__active: + if self.__ssig.has_sock_quit(): + self.__log.trace( # type: ignore + "SOCK-QUIT signal ACK in Net.send (while waiting for UDP client)" + ) + return -1 time.sleep(0.01) curr = 0 # bytes send during one loop iteration send = 0 # total bytes send size = len(data) # bytes of data that needs to be send - byte = self.__enc.encode(data) - assert size == len(byte), "Encoding messed up string length, might need to do len() after." # Loop until all bytes have been send - # TODO: Does this make it impossible to send nullbytes (Ctrl+d) while send < size: self.__log.debug( "Trying to send %d bytes to %s:%d", @@ -10692,23 +11695,23 @@

Args

self.__active["remote_addr"], self.__active["remote_port"], ) - self.__log.trace("Trying to send: %s", repr(byte)) # type: ignore + self.__log.trace("Trying to send: %s", repr(data)) # type: ignore try: # Only UDP server has not made a connect() to the socket, all others # are already connected and need to use send() instead of sendto() if self.__udp_mode_server: curr = self.__active["conn"].sendto( - byte, (self.__active["remote_addr"], self.__active["remote_port"]) + data, (self.__active["remote_addr"], self.__active["remote_port"]) ) send += curr else: - curr = self.__active["conn"].send(byte) + curr = self.__active["conn"].send(data) send += curr if curr == 0: self.__log.error("No bytes send during loop round.") return 0 # Remove 'curr' many bytes from byte for the next round - byte = byte[curr:] + data = data[curr:] self.__log.debug( "Sent %d bytes to %s:%d (%d bytes remaining)", curr, @@ -10716,23 +11719,23 @@

Args

self.__active["remote_port"], size - send, ) - except (OSError, socket.error) as error: - self.__log.error("Socket OS Error: %s", error) - return send + except (BrokenPipeError, OSError, socket.error) as error: + msg = "Socket send Error: {}".format(error) + raise socket.error(msg) return send def receive(self): - # type: () -> str + # type: () -> bytes """Receive and return data from the connected (TCP) or unconnected (UDP) socket. Returns: - str: Returns received data from connected (TCP) or unconnected (UDP) socket. + bytes: Returns received data from connected (TCP) or unconnected (UDP) socket. Raises: socket.timeout: Except here to do an action when the socket is not busy. AttributeError: Except here when current instance has closed itself (Ctrl+c). socket.error: Except here when unconnected or connection was forcibly closed. - EOFError: Except here when upstream has closed the connection. + EOFError: Except here when upstream has closed the connection via EOF. """ # This is required for a UDP server that has no connected clients yet # and is waiting for data receival for the first time on either IPv4 or IPv6 @@ -10748,9 +11751,9 @@

Args

0 ] # type: List[socket.socket] # E.g.: ValueError: file descriptor cannot be a negative integer (-1) - except (ValueError, AttributeError): - msg = "Connection was closed by self." - self.__log.warning(msg) + except (ValueError, AttributeError) as error: + msg = "Connection was closed by self: [1]: {}".format(error) + self.__log.debug(msg) raise AttributeError(msg) if not conns: # This is raised for the calling function to determine what to do @@ -10762,12 +11765,12 @@

Args

conn = conns[0] # type: socket.socket try: # https://manpages.debian.org/buster/manpages-dev/recv.2.en.html - (byte, addr) = conn.recvfrom(self.__options.bufsize) + (data, addr) = conn.recvfrom(self.__options.bufsize) # [1/5] When closing itself (e.g.: via Ctrl+c and the socket_close() funcs are called) - except AttributeError: - msg = "Connection was closed by self." - self.__log.warning(msg) + except AttributeError as error: + msg = "Connection was closed by self: [2]: {}".format(error) + self.__log.debug(msg) raise AttributeError(msg) # [2/5] Connection was forcibly closed @@ -10775,14 +11778,14 @@

Args

# [Errno 10054] An existing connection was forcibly closed by the remote host # [WinError 10054] An existing connection was forcibly closed by the remote host except (OSError, socket.error) as error: - self.__log.warning("Connection error: %s", error) + self.__log.debug("Connection error: %s", error) raise socket.error(error) # [3/5] Upstream (server or client) is gone. # In TCP, there is no such thing as an empty message, so zero means a peer disconnect. # In UDP, there is no such thing as a peer disconnect, so zero means an empty datagram. - if not byte: - msg = "Upstream has closed the connection." + if not data: + msg = "EOF: Remote finished sending." self.__log.info(msg) raise EOFError(msg) @@ -10820,7 +11823,6 @@

Args

} # [5/5] We have data to process - data = self.__enc.decode(byte) self.__log.debug( "Received %d bytes from %s:%d", len(data), @@ -11057,24 +12059,27 @@

Args

return False # (2/3) Accept + remove = {} try: conn, client = self.__sock.accept( - [conns[family]["sock"] for family in conns], self.__ssig.has_stop + [conns[family]["sock"] for family in conns], self.__ssig.has_sock_quit ) conns[conn.family]["conn"] = conn conns[conn.family]["remote_addr"] = client[0] conns[conn.family]["remote_port"] = client[1] except socket.error as err: - # On error, remove all bind sockets - for family in conns: - self.__log.debug( - "Removing (family %d/%s) due to: %s", - family, - self.__sock.get_family_name(family), - err, - ) - self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) - del conns[family] + remove = {family: str(err) for family in conns} + # On error, remove all bind sockets + for family in remove: + self.__log.debug( + "Removing (family %d/%s) due to: %s", + family, + self.__sock.get_family_name(family), + remove[family], + ) + self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) + del conns[family] + if not conns: return False # (3/3) Store connections @@ -11107,7 +12112,7 @@

Args

# [2/3] Accept try: conn, client = self.__sock.accept( - [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_stop + [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_sock_quit ) except socket.error: return False @@ -11204,7 +12209,7 @@

Returns

# [2/3] Accept try: conn, client = self.__sock.accept( - [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_stop + [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_sock_quit ) except socket.error: return False @@ -11229,7 +12234,7 @@

Returns

Receive and return data from the connected (TCP) or unconnected (UDP) socket.

Returns

-
str
+
bytes
Returns received data from connected (TCP) or unconnected (UDP) socket.

Raises

@@ -11242,7 +12247,7 @@

Raises

Except here when unconnected or connection was forcibly closed.
EOFError
-

Except here when upstream has closed the connection.

+

Except here when upstream has closed the connection via EOF.

@@ -11250,17 +12255,17 @@

Raises

Expand source code
def receive(self):
-    # type: () -> str
+    # type: () -> bytes
     """Receive and return data from the connected (TCP) or unconnected (UDP) socket.
 
     Returns:
-        str: Returns received data from connected (TCP) or unconnected (UDP) socket.
+        bytes: Returns received data from connected (TCP) or unconnected (UDP) socket.
 
     Raises:
         socket.timeout: Except here to do an action when the socket is not busy.
         AttributeError: Except here when current instance has closed itself (Ctrl+c).
         socket.error:   Except here when unconnected or connection was forcibly closed.
-        EOFError:       Except here when upstream has closed the connection.
+        EOFError:       Except here when upstream has closed the connection via EOF.
     """
     # This is required for a UDP server that has no connected clients yet
     # and is waiting for data receival for the first time on either IPv4 or IPv6
@@ -11276,9 +12281,9 @@ 

Raises

0 ] # type: List[socket.socket] # E.g.: ValueError: file descriptor cannot be a negative integer (-1) - except (ValueError, AttributeError): - msg = "Connection was closed by self." - self.__log.warning(msg) + except (ValueError, AttributeError) as error: + msg = "Connection was closed by self: [1]: {}".format(error) + self.__log.debug(msg) raise AttributeError(msg) if not conns: # This is raised for the calling function to determine what to do @@ -11290,12 +12295,12 @@

Raises

conn = conns[0] # type: socket.socket try: # https://manpages.debian.org/buster/manpages-dev/recv.2.en.html - (byte, addr) = conn.recvfrom(self.__options.bufsize) + (data, addr) = conn.recvfrom(self.__options.bufsize) # [1/5] When closing itself (e.g.: via Ctrl+c and the socket_close() funcs are called) - except AttributeError: - msg = "Connection was closed by self." - self.__log.warning(msg) + except AttributeError as error: + msg = "Connection was closed by self: [2]: {}".format(error) + self.__log.debug(msg) raise AttributeError(msg) # [2/5] Connection was forcibly closed @@ -11303,14 +12308,14 @@

Raises

# [Errno 10054] An existing connection was forcibly closed by the remote host # [WinError 10054] An existing connection was forcibly closed by the remote host except (OSError, socket.error) as error: - self.__log.warning("Connection error: %s", error) + self.__log.debug("Connection error: %s", error) raise socket.error(error) # [3/5] Upstream (server or client) is gone. # In TCP, there is no such thing as an empty message, so zero means a peer disconnect. # In UDP, there is no such thing as a peer disconnect, so zero means an empty datagram. - if not byte: - msg = "Upstream has closed the connection." + if not data: + msg = "EOF: Remote finished sending." self.__log.info(msg) raise EOFError(msg) @@ -11348,7 +12353,6 @@

Raises

} # [5/5] We have data to process - data = self.__enc.decode(byte) self.__log.debug( "Received %d bytes from %s:%d", len(data), @@ -11626,24 +12630,27 @@

Returns

return False # (2/3) Accept + remove = {} try: conn, client = self.__sock.accept( - [conns[family]["sock"] for family in conns], self.__ssig.has_stop + [conns[family]["sock"] for family in conns], self.__ssig.has_sock_quit ) conns[conn.family]["conn"] = conn conns[conn.family]["remote_addr"] = client[0] conns[conn.family]["remote_port"] = client[1] except socket.error as err: - # On error, remove all bind sockets - for family in conns: - self.__log.debug( - "Removing (family %d/%s) due to: %s", - family, - self.__sock.get_family_name(family), - err, - ) - self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) - del conns[family] + remove = {family: str(err) for family in conns} + # On error, remove all bind sockets + for family in remove: + self.__log.debug( + "Removing (family %d/%s) due to: %s", + family, + self.__sock.get_family_name(family), + remove[family], + ) + self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) + del conns[family] + if not conns: return False # (3/3) Store connections @@ -11668,27 +12675,35 @@

Returns

Send data through a connected (TCP) or unconnected (UDP) socket.

Args

-
data : str
+
data : bytes
The data to send.

Returns

int
Returns total bytes sent.
+
+

Raises

+
+
socket.error
+
Except here when unconnected or connection was forcibly closed.
Expand source code
def send(self, data):
-    # type: (str) -> int
+    # type: (bytes) -> int
     """Send data through a connected (TCP) or unconnected (UDP) socket.
 
     Args:
-        data (str): The data to send.
+        data (bytes): The data to send.
 
     Returns:
         int: Returns total bytes sent.
+
+    Raises:
+        socket.error:   Except here when unconnected or connection was forcibly closed.
     """
     # UDP has some specialities as its socket is unconnected.
     # See also recv() for specialities on that side.
@@ -11700,16 +12715,18 @@ 

Returns

if not self.__active: self.__log.warning("UDP client has not yet connected. Queueing message") while not self.__active: + if self.__ssig.has_sock_quit(): + self.__log.trace( # type: ignore + "SOCK-QUIT signal ACK in Net.send (while waiting for UDP client)" + ) + return -1 time.sleep(0.01) curr = 0 # bytes send during one loop iteration send = 0 # total bytes send size = len(data) # bytes of data that needs to be send - byte = self.__enc.encode(data) - assert size == len(byte), "Encoding messed up string length, might need to do len() after." # Loop until all bytes have been send - # TODO: Does this make it impossible to send nullbytes (Ctrl+d) while send < size: self.__log.debug( "Trying to send %d bytes to %s:%d", @@ -11717,23 +12734,23 @@

Returns

self.__active["remote_addr"], self.__active["remote_port"], ) - self.__log.trace("Trying to send: %s", repr(byte)) # type: ignore + self.__log.trace("Trying to send: %s", repr(data)) # type: ignore try: # Only UDP server has not made a connect() to the socket, all others # are already connected and need to use send() instead of sendto() if self.__udp_mode_server: curr = self.__active["conn"].sendto( - byte, (self.__active["remote_addr"], self.__active["remote_port"]) + data, (self.__active["remote_addr"], self.__active["remote_port"]) ) send += curr else: - curr = self.__active["conn"].send(byte) + curr = self.__active["conn"].send(data) send += curr if curr == 0: self.__log.error("No bytes send during loop round.") return 0 # Remove 'curr' many bytes from byte for the next round - byte = byte[curr:] + data = data[curr:] self.__log.debug( "Sent %d bytes to %s:%d (%d bytes remaining)", curr, @@ -11741,9 +12758,9 @@

Returns

self.__active["remote_port"], size - send, ) - except (OSError, socket.error) as error: - self.__log.error("Socket OS Error: %s", error) - return send + except (BrokenPipeError, OSError, socket.error) as error: + msg = "Socket send Error: {}".format(error) + raise socket.error(msg) return send
@@ -11758,12 +12775,12 @@

Returns

The same instance of this class will be available to your send and receive scripts that allow you to exchange data or manipulate themselves. You even have access to the currently used instance of the networking class to manipulate the active socket. -As well as to the logger and StopSignal instances.

+As well as to the logger and InterruptHandler instances.

Instantiate the PSE class.

Args

-
ssig : StopSignal
-
Instance of the StopSignal class to force a shutdown.
+
ssig : InterruptHandler
+
Instance InterruptHandler.
net : IONetwork
Instance of the current network class to manipulate the socket.
@@ -11777,18 +12794,18 @@

Args

The same instance of this class will be available to your send and receive scripts that allow you to exchange data or manipulate themselves. You even have access to the currently used instance of the networking class to manipulate the active socket. - As well as to the logger and StopSignal instances. + As well as to the logger and InterruptHandler instances. """ @property def messages(self): - # type: () -> Dict[str, List[str]] - """`Dict[str, List[str]]`: Stores sent and received messages by its thread name.""" + # type: () -> Dict[str, List[bytes]] + """`Dict[str, List[bytes]]`: Stores sent and received messages by its thread name.""" return self.__messages @messages.setter def messages(self, value): - # type: (Dict[str, List[str]]) -> None + # type: (Dict[str, List[bytes]]) -> None self.__messages = value @property @@ -11804,8 +12821,8 @@

Args

@property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: Instance of Logging.logger class.""" + # type: () -> InterruptHandler + """`InterruptHandler`: Instance of InterruptHandler class.""" return self.__ssig @property @@ -11821,11 +12838,11 @@

Args

return self.__log def __init__(self, ssig, net): - # type: (StopSignal, List[IONetwork]) -> None + # type: (InterruptHandler, List[IONetwork]) -> None """Instantiate the PSE class. Args: - ssig (StopSignal): Instance of the StopSignal class to force a shutdown. + ssig (InterruptHandler): Instance InterruptHandler. net (IONetwork): Instance of the current network class to manipulate the socket. """ self.__messages = {} @@ -11852,15 +12869,15 @@

Instance variables

var messages
-

Dict[str, List[str]]: Stores sent and received messages by its thread name.

+

Dict[str, List[bytes]]: Stores sent and received messages by its thread name.

Expand source code
@property
 def messages(self):
-    # type: () -> Dict[str, List[str]]
-    """`Dict[str, List[str]]`: Stores sent and received messages by its thread name."""
+    # type: () -> Dict[str, List[bytes]]
+    """`Dict[str, List[bytes]]`: Stores sent and received messages by its thread name."""
     return self.__messages
@@ -11880,15 +12897,15 @@

Instance variables

var ssig
-

StopSignal: Instance of Logging.logger class.

+

InterruptHandler: Instance of InterruptHandler class.

Expand source code
@property
 def ssig(self):
-    # type: () -> StopSignal
-    """`StopSignal`: Instance of Logging.logger class."""
+    # type: () -> InterruptHandler
+    """`InterruptHandler`: Instance of InterruptHandler class."""
     return self.__ssig
@@ -11910,13 +12927,15 @@

Instance variables

class Runner -(pse) +(ssig, pse)

Runner class that takes care about putting everything into threads.

Create a new Runner object.

Args

+
ssig : InterruptHandler
+
Instance of InterruptHandler.
pse : PSEStore
Pwncat Scripting Engine store.
@@ -11930,11 +12949,12 @@

Args

# -------------------------------------------------------------------------- # Constructor / Destructor # -------------------------------------------------------------------------- - def __init__(self, pse): - # type: (PSEStore) -> None + def __init__(self, ssig, pse): + # type: (InterruptHandler, PSEStore) -> None """Create a new Runner object. Args: + ssig (InterruptHandler): Instance of InterruptHandler. pse (PSEStore): Pwncat Scripting Engine store. """ self.log = logging.getLogger(__name__) @@ -11956,6 +12976,7 @@

Args

# {"name": "<thread>"} self.__threads = {} # type: Dict[str, threading.Thread] + self.__ssig = ssig self.__pse = pse # -------------------------------------------------------------------------- @@ -11998,7 +13019,7 @@

Args

def run_action( name, # type: str producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] ): @@ -12048,22 +13069,24 @@

Args

self.log.trace("[%s] Producer Stop", name) # type: ignore def run_timer(name, action, intvl, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, InterruptHandler, Any, Any) -> None """Timer run function to be thrown into a thread (Execs periodic tasks). Args: name (str): Name for logging output action (function): Function to be called in a given intervall intvl (float): Intervall at which the action function will be called - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ self.log.trace("[%s] Timer Start (exec every %f sec)", name, intvl) # type: ignore time_last = int(time.time()) while True: - if ssig.has_stop(): - self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore + if ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for timer action [%s]", name + ) return time_now = int(time.time()) if time_now > time_last + intvl: @@ -12073,7 +13096,7 @@

Args

time.sleep(0.1) def run_repeater(name, action, repeat, pause, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, float, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, float, InterruptHandler, Any, Any) -> None """Repeater run function to be thrown into a thread (Execs periodic tasks). Args: @@ -12081,23 +13104,30 @@

Args

action (function): Function to be called repeat (int): Repeat the function so many times before quitting pause (float): Pause between repeated calls - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ cycles = 1 self.log.trace("Repeater Start (%d/%d)", cycles, repeat) # type: ignore while cycles <= repeat: - if ssig.has_stop(): - self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore + if ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for repeater action [%s]", name + ) return self.log.debug("Executing repeated function (%d/%d)", cycles, repeat) action(*args, **kwargs) cycles += 1 time.sleep(pause) - # Start available action in a thread + # [1/3] Start available action in a thread for key in self.__actions: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [1]: [%s]", key + ) + break # Create Thread object thread = threading.Thread( target=run_action, @@ -12110,16 +13140,27 @@

Args

self.__actions[key].code, ), ) - thread.daemon = False + # Daemon threads are easier to kill + thread.daemon = True + # Add delay if threads cannot be started + delay = 0.0 while True: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [2]: [%s]", key + ) + break try: + # Start and break the loop upon success to go to the next thread to start thread.start() break except (RuntimeError, Exception): # pylint: disable=broad-except - time.sleep(0.1) + delay += 0.1 + time.sleep(delay) # Give the system some time to release open fd's self.__threads[key] = thread - # Start available timers in a thread + + # [2/3] Start available timers in a thread for key in self.__timers: # Create Thread object thread = threading.Thread( @@ -12129,14 +13170,15 @@

Args

key, self.__timers[key].action, self.__timers[key].intvl, - self.__timers[key].signal, + self.__timers[key].ssig, self.__timers[key].args, ), kwargs=self.__timers[key].kwargs, ) thread.daemon = False thread.start() - # Start available repeaters in a thread + + # [3/3] Start available repeaters in a thread for key in self.__repeaters: # Create Thread object thread = threading.Thread( @@ -12147,7 +13189,7 @@

Args

self.__repeaters[key].action, self.__repeaters[key].repeat, self.__repeaters[key].pause, - self.__repeaters[key].signal, + self.__repeaters[key].ssig, self.__repeaters[key].args, ), kwargs=self.__repeaters[key].kwargs, @@ -12155,22 +13197,14 @@

Args

thread.daemon = False thread.start() - def check_stop(force): - # type: (int) -> bool + def check_stop(): + # type: () -> bool """Stop threads.""" - for key in self.__threads: - if not self.__threads[key].is_alive() or force: - # TODO: How are we gonna call the stop signal now? - # # [1/3] Inform all threads (inside) about a stop signal. - # # All threads with non-blocking funcs will be able to stop themselves - # self.log.trace( # type: ignore - # "Raise stop signal: StopSignal.stop() for thread [%s]", - # self.__threads[key].getName(), - # ) - # self.__actions[key].signal.raise_stop() - # [2/3] Call external interrupters - # These will shutdown all blocking functions inside a thread, - # so that they are actually able to join + # TODO: This is a workaround for using daemon threads. + # Python < 3.3 is unable to detect Ctrl+c signal during + # thread.join() operation in a fast loop (Port scan). + if self.__ssig.has_terminate(): + for key in self.__threads: for interrupt in self.__actions[key].interrupts: self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", @@ -12179,24 +13213,53 @@

Args

self.__threads[key].getName(), ) interrupt() - # [3/3] All blocking events inside the threads are gone, now join them - self.log.trace("Joining %s", self.__threads[key].getName()) # type: ignore - self.__threads[key].join(timeout=0.1) - # If all threads have died or force is requested, then exit - if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + return True + # If all threads are done, also stop + if not all([self.__threads[key].is_alive() for key in self.__threads]): return True return False + # NOTE: This was for previous non-daemon threads + # for key in self.__threads: + # if not self.__threads[key].is_alive() or force: + # # TODO: How are we gonna call the stop signal now? + # # # [1/3] Inform all threads (inside) about a stop signal. + # # # All threads with non-blocking funcs will be able to stop themselves + # # self.log.trace( # type: ignore + # # "Raise stop signal: StopSignal.stop() for thread [%s]", + # # self.__threads[key].getName(), + # # ) + # # self.__actions[key].signal.signal_quit() + # # [2/3] Call external interrupters + # # These will shutdown all blocking functions inside a thread, + # # so that they are actually able to join + # for interrupt in self.__actions[key].interrupts: + # self.log.trace( # type: ignore + # "Call INTERRUPT: %s.%s() for %s", + # getattr(interrupt, "__self__").__class__.__name__, + # interrupt.__name__, + # self.__threads[key].getName(), + # ) + # interrupt() + # # [3/3] All blocking events inside the threads are gone, now join them + # try: + # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore + # # NOTE: The thread.join() operating will also block the signal handler + # #self.__threads[key].join(timeout=0.1) + # self.__threads[key].join() + # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore + # except RuntimeError as err: + # print(err) + # #pass + # # If all threads have died or force is requested, then exit + # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + # return True + # return False - try: - while True: - if check_stop(False): - sys.exit(0) - # Need a timeout to not skyrocket the CPU - time.sleep(0.1) - except KeyboardInterrupt: - print() - check_stop(True) - sys.exit(1)
+ while True: + if check_stop(): + sys.exit(0) + # Need a timeout to not skyrocket the CPU + time.sleep(0.01)

Methods

@@ -12297,7 +13360,7 @@

Args

def run_action( name, # type: str producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] ): @@ -12347,22 +13410,24 @@

Args

self.log.trace("[%s] Producer Stop", name) # type: ignore def run_timer(name, action, intvl, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, InterruptHandler, Any, Any) -> None """Timer run function to be thrown into a thread (Execs periodic tasks). Args: name (str): Name for logging output action (function): Function to be called in a given intervall intvl (float): Intervall at which the action function will be called - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ self.log.trace("[%s] Timer Start (exec every %f sec)", name, intvl) # type: ignore time_last = int(time.time()) while True: - if ssig.has_stop(): - self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore + if ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for timer action [%s]", name + ) return time_now = int(time.time()) if time_now > time_last + intvl: @@ -12372,7 +13437,7 @@

Args

time.sleep(0.1) def run_repeater(name, action, repeat, pause, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, float, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, float, InterruptHandler, Any, Any) -> None """Repeater run function to be thrown into a thread (Execs periodic tasks). Args: @@ -12380,23 +13445,30 @@

Args

action (function): Function to be called repeat (int): Repeat the function so many times before quitting pause (float): Pause between repeated calls - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ cycles = 1 self.log.trace("Repeater Start (%d/%d)", cycles, repeat) # type: ignore while cycles <= repeat: - if ssig.has_stop(): - self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore + if ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for repeater action [%s]", name + ) return self.log.debug("Executing repeated function (%d/%d)", cycles, repeat) action(*args, **kwargs) cycles += 1 time.sleep(pause) - # Start available action in a thread + # [1/3] Start available action in a thread for key in self.__actions: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [1]: [%s]", key + ) + break # Create Thread object thread = threading.Thread( target=run_action, @@ -12409,16 +13481,27 @@

Args

self.__actions[key].code, ), ) - thread.daemon = False + # Daemon threads are easier to kill + thread.daemon = True + # Add delay if threads cannot be started + delay = 0.0 while True: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [2]: [%s]", key + ) + break try: + # Start and break the loop upon success to go to the next thread to start thread.start() break except (RuntimeError, Exception): # pylint: disable=broad-except - time.sleep(0.1) + delay += 0.1 + time.sleep(delay) # Give the system some time to release open fd's self.__threads[key] = thread - # Start available timers in a thread + + # [2/3] Start available timers in a thread for key in self.__timers: # Create Thread object thread = threading.Thread( @@ -12428,14 +13511,15 @@

Args

key, self.__timers[key].action, self.__timers[key].intvl, - self.__timers[key].signal, + self.__timers[key].ssig, self.__timers[key].args, ), kwargs=self.__timers[key].kwargs, ) thread.daemon = False thread.start() - # Start available repeaters in a thread + + # [3/3] Start available repeaters in a thread for key in self.__repeaters: # Create Thread object thread = threading.Thread( @@ -12446,7 +13530,7 @@

Args

self.__repeaters[key].action, self.__repeaters[key].repeat, self.__repeaters[key].pause, - self.__repeaters[key].signal, + self.__repeaters[key].ssig, self.__repeaters[key].args, ), kwargs=self.__repeaters[key].kwargs, @@ -12454,22 +13538,14 @@

Args

thread.daemon = False thread.start() - def check_stop(force): - # type: (int) -> bool + def check_stop(): + # type: () -> bool """Stop threads.""" - for key in self.__threads: - if not self.__threads[key].is_alive() or force: - # TODO: How are we gonna call the stop signal now? - # # [1/3] Inform all threads (inside) about a stop signal. - # # All threads with non-blocking funcs will be able to stop themselves - # self.log.trace( # type: ignore - # "Raise stop signal: StopSignal.stop() for thread [%s]", - # self.__threads[key].getName(), - # ) - # self.__actions[key].signal.raise_stop() - # [2/3] Call external interrupters - # These will shutdown all blocking functions inside a thread, - # so that they are actually able to join + # TODO: This is a workaround for using daemon threads. + # Python < 3.3 is unable to detect Ctrl+c signal during + # thread.join() operation in a fast loop (Port scan). + if self.__ssig.has_terminate(): + for key in self.__threads: for interrupt in self.__actions[key].interrupts: self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", @@ -12478,24 +13554,53 @@

Args

self.__threads[key].getName(), ) interrupt() - # [3/3] All blocking events inside the threads are gone, now join them - self.log.trace("Joining %s", self.__threads[key].getName()) # type: ignore - self.__threads[key].join(timeout=0.1) - # If all threads have died or force is requested, then exit - if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + return True + # If all threads are done, also stop + if not all([self.__threads[key].is_alive() for key in self.__threads]): return True return False + # NOTE: This was for previous non-daemon threads + # for key in self.__threads: + # if not self.__threads[key].is_alive() or force: + # # TODO: How are we gonna call the stop signal now? + # # # [1/3] Inform all threads (inside) about a stop signal. + # # # All threads with non-blocking funcs will be able to stop themselves + # # self.log.trace( # type: ignore + # # "Raise stop signal: StopSignal.stop() for thread [%s]", + # # self.__threads[key].getName(), + # # ) + # # self.__actions[key].signal.signal_quit() + # # [2/3] Call external interrupters + # # These will shutdown all blocking functions inside a thread, + # # so that they are actually able to join + # for interrupt in self.__actions[key].interrupts: + # self.log.trace( # type: ignore + # "Call INTERRUPT: %s.%s() for %s", + # getattr(interrupt, "__self__").__class__.__name__, + # interrupt.__name__, + # self.__threads[key].getName(), + # ) + # interrupt() + # # [3/3] All blocking events inside the threads are gone, now join them + # try: + # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore + # # NOTE: The thread.join() operating will also block the signal handler + # #self.__threads[key].join(timeout=0.1) + # self.__threads[key].join() + # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore + # except RuntimeError as err: + # print(err) + # #pass + # # If all threads have died or force is requested, then exit + # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + # return True + # return False - try: - while True: - if check_stop(False): - sys.exit(0) - # Need a timeout to not skyrocket the CPU - time.sleep(0.1) - except KeyboardInterrupt: - print() - check_stop(True) - sys.exit(1) + while True: + if check_stop(): + sys.exit(0) + # Need a timeout to not skyrocket the CPU + time.sleep(0.01)
@@ -12505,13 +13610,13 @@

Args

(*args, **kwargs)
-

Thread-safe singleton Socket helper to emulate a module within the same file.

+

Thread-safe singleton Socket wrapper to emulate a module within the same file.

Expand source code
class Sock(_Singleton("SingletonMeta", (object,), {})):  # type: ignore
-    """Thread-safe singleton Socket helper to emulate a module within the same file."""
+    """Thread-safe singleton Socket wrapper to emulate a module within the same file."""
 
     def __init__(self):
         # type: () -> None
@@ -12971,27 +14076,35 @@ 

Args

self.__log.error(msg) raise socket.error(msg) - def accept(self, sockets, fstop): - # type: (List[socket.socket], Callable[[], bool]) -> Tuple[socket.socket, Tuple[str, int]] + def accept( + self, + sockets, # type: List[socket.socket] + has_quit, # type: Callable[[], bool] + select_timeout=0.01, # type: float + ): + # type: (...) -> Tuple[socket.socket, Tuple[str, int]] """Accept a single connection from given list of sockets. Given sockets must be bound to an addr and listening for connections. Args: sock ([socket.socket]): List of sockets IPv4 and/or IPv6 to accept on. - fstop (Callable[[], bool]): A function that returns True if abort is requested. + has_quit (Callable[[], bool]): A function that returns True if abort is requested. + select_timeout (float): Timeout to poll sockets for connected clients. Returns: - socket.socket: Returns the connection socket (whatever protocol was faster). + (socket.socket, str, int): Returns tuple of socket, address and port of client. Raises: socket.error: Raised if server cannot accept connection or stop signal is requested. """ self.__log.debug("Waiting for TCP client") while True: - ssockets = select.select(sockets, [], [], 0.01)[0] # type: List[socket.socket] - if fstop(): - raise socket.error("StopSignal acknknowledged") + ssockets = select.select(sockets, [], [], select_timeout)[ + 0 + ] # type: List[socket.socket] + if has_quit(): + raise socket.error("SOCK-QUIT signal ACK for accept(): raised socket.error()") for sock in ssockets: try: conn, addr = sock.accept() @@ -13029,13 +14142,18 @@

Args

port (int): Port of server to connect to. Returns: - Tuple[str,int]: Adress/port tuple of local bin of the client. + Tuple[str,int]: Adress/port tuple of local bind of the client. Raises: socker.error: If client cannot connect to remote peer or custom bind did not succeed. """ - sock_family_name = self.get_family_name(sock.family) - sock_type_name = self.get_type_name(sock.type) + try: + # If the socket was already closed elsewhere, it won't have family or type anymore + sock_family_name = self.get_family_name(sock.family) + sock_type_name = self.get_type_name(sock.type) + except AttributeError as error: + raise socket.error(error) + # Bind to a custom addr/port if src_addr is not None and src_port is not None: try: @@ -13243,7 +14361,7 @@

Static methods

Methods

-def accept(self, sockets, fstop) +def accept(self, sockets, has_quit, select_timeout=0.01)

Accept a single connection from given list of sockets.

@@ -13252,14 +14370,13 @@

Args

sock : [socket.socket]
List of sockets IPv4 and/or IPv6 to accept on.
-
fstop : Callable[[], bool]
+
has_quit : Callable[[], bool]
A function that returns True if abort is requested.
+
select_timeout : float
+
Timeout to poll sockets for connected clients.

Returns

-
-
socket.socket
-
Returns the connection socket (whatever protocol was faster).
-
+

(socket.socket, str, int): Returns tuple of socket, address and port of client.

Raises

socket.error
@@ -13269,27 +14386,35 @@

Raises

Expand source code -
def accept(self, sockets, fstop):
-    # type: (List[socket.socket], Callable[[], bool]) -> Tuple[socket.socket, Tuple[str, int]]
+
def accept(
+    self,
+    sockets,  # type: List[socket.socket]
+    has_quit,  # type: Callable[[], bool]
+    select_timeout=0.01,  # type: float
+):
+    # type: (...) -> Tuple[socket.socket, Tuple[str, int]]
     """Accept a single connection from given list of sockets.
 
     Given sockets must be bound to an addr and listening for connections.
 
     Args:
         sock ([socket.socket]): List of sockets IPv4 and/or IPv6 to accept on.
-        fstop (Callable[[], bool]): A function that returns True if abort is requested.
+        has_quit (Callable[[], bool]): A function that returns True if abort is requested.
+        select_timeout (float): Timeout to poll sockets for connected clients.
 
     Returns:
-        socket.socket: Returns the connection socket (whatever protocol was faster).
+        (socket.socket, str, int): Returns tuple of socket, address and port of client.
 
     Raises:
         socket.error: Raised if server cannot accept connection or stop signal is requested.
     """
     self.__log.debug("Waiting for TCP client")
     while True:
-        ssockets = select.select(sockets, [], [], 0.01)[0]  # type: List[socket.socket]
-        if fstop():
-            raise socket.error("StopSignal acknknowledged")
+        ssockets = select.select(sockets, [], [], select_timeout)[
+            0
+        ]  # type: List[socket.socket]
+        if has_quit():
+            raise socket.error("SOCK-QUIT signal ACK for accept(): raised socket.error()")
         for sock in ssockets:
             try:
                 conn, addr = sock.accept()
@@ -13416,7 +14541,7 @@ 

Args

Returns

Tuple[str,int]
-
Adress/port tuple of local bin of the client.
+
Adress/port tuple of local bind of the client.

Raises

@@ -13448,13 +14573,18 @@

Raises

port (int): Port of server to connect to. Returns: - Tuple[str,int]: Adress/port tuple of local bin of the client. + Tuple[str,int]: Adress/port tuple of local bind of the client. Raises: socker.error: If client cannot connect to remote peer or custom bind did not succeed. """ - sock_family_name = self.get_family_name(sock.family) - sock_type_name = self.get_type_name(sock.type) + try: + # If the socket was already closed elsewhere, it won't have family or type anymore + sock_family_name = self.get_family_name(sock.family) + sock_type_name = self.get_type_name(sock.type) + except AttributeError as error: + raise socket.error(error) + # Bind to a custom addr/port if src_addr is not None and src_port is not None: try: @@ -13850,82 +14980,13 @@

Raises

-
-class StopSignal -
-
-

Provide a simple boolean switch.

-

Create a StopSignal instance.

-
- -Expand source code - -
class StopSignal(object):
-    """Provide a simple boolean switch."""
-
-    # --------------------------------------------------------------------------
-    # Constructor
-    # --------------------------------------------------------------------------
-    def __init__(self):
-        # type: () -> None
-        """Create a StopSignal instance."""
-        self.__stop = False
-
-    # --------------------------------------------------------------------------
-    # Public Functions
-    # --------------------------------------------------------------------------
-    def has_stop(self):
-        # type: () -> bool
-        """Check if a stop signal has been raised."""
-        return self.__stop
-
-    def raise_stop(self):
-        # type: () -> None
-        """Raise a stop signal."""
-        self.__stop = True
-
-

Methods

-
-
-def has_stop(self) -
-
-

Check if a stop signal has been raised.

-
- -Expand source code - -
def has_stop(self):
-    # type: () -> bool
-    """Check if a stop signal has been raised."""
-    return self.__stop
-
-
-
-def raise_stop(self) -
-
-

Raise a stop signal.

-
- -Expand source code - -
def raise_stop(self):
-    # type: () -> None
-    """Raise a stop signal."""
-    self.__stop = True
-
-
-
-
class StringEncoder

Takes care about Python 2/3 string encoding/decoding.

This allows to parse all string/byte values internally between all -classes or functions as strings to keep full Python 2/3 compat.

-

Create a StringEncoder instance which converts str/bytes according to Python version.

+classes or functions as strings to keep full Python 2/3 compat.

Expand source code @@ -13937,63 +14998,84 @@

Methods

classes or functions as strings to keep full Python 2/3 compat. """ - # -------------------------------------------------------------------------- - # Constructor - # -------------------------------------------------------------------------- - def __init__(self): - # type: () -> None - """Create a StringEncoder instance which converts str/bytes according to Python version.""" - self.__py3 = sys.version_info >= (3, 0) # type: bool - - # https://stackoverflow.com/questions/606191/27527728#27527728 - self.__codec = "cp437" - self.__fallback = "latin-1" + CODECS = [ + "utf-8", + "cp437", + "latin-1", + ] # -------------------------------------------------------------------------- - # Public Functions - # -------------------------------------------------------------------------- - def encode(self, data): + # Class methods + # -------------------------------------------------------------------------- + @classmethod + def rstrip(cls, data, search=None): + # type: (Union[bytes, str], Optional[str]) -> Union[bytes, str] + """Implementation of rstring which works on bytes or strings.""" + # We have a bytes object in Python3 + if sys.version_info >= (3, 0) and type(data) is not str: + # Strip whitespace + if search is None: + while True: + new = data + new = cls.rstrip(new, " ") + new = cls.rstrip(new, "\n") + new = cls.rstrip(new, "\r") + new = cls.rstrip(new, "\t") + # Loop until no more changes occur + if new == data: + return new + else: + bsearch = StringEncoder.encode(search) + while data[-1:] == bsearch: + data = data[:-1] + return data + + # Use native function + if search is None: + return data.rstrip() + return data.rstrip(search) # type: ignore + + @classmethod + def encode(cls, data): # type: (str) -> bytes """Convert string into a byte type for Python3.""" - if self.__py3: - try: - return data.encode(self.__codec) - except UnicodeEncodeError: - # TODO: Add logging - return data.encode(self.__fallback) + if sys.version_info >= (3, 0): + for codec in cls.CODECS: + # On the last codec, do not catch the exception and let it trigger if it fails + if codec == cls.CODECS[-1]: + return data.encode(codec) + try: + return data.encode(codec) + except UnicodeEncodeError: + pass return data # type: ignore - def decode(self, data): + @classmethod + def decode(cls, data): # type: (bytes) -> str """Convert bytes into a string type for Python3.""" - if self.__py3: - return data.decode(self.__codec) - return data # type: ignore - - def base64_encode(self, data): - # type: (str) -> str - """Convert string into a base64 encoded string.""" - return self.decode(base64.b64encode(self.encode(data)))
+ if sys.version_info >= (3, 0): + for codec in cls.CODECS: + # On the last codec, do not catch the exception and let it trigger if it fails + if codec == cls.CODECS[-1]: + return data.decode(codec) + try: + return data.decode(codec) + except UnicodeDecodeError: + pass + return data # type: ignore
-

Methods

+

Class variables

-
-def base64_encode(self, data) -
+
var CODECS
-

Convert string into a base64 encoded string.

-
- -Expand source code - -
def base64_encode(self, data):
-    # type: (str) -> str
-    """Convert string into a base64 encoded string."""
-    return self.decode(base64.b64encode(self.encode(data)))
-
+
+
+

Static methods

+
-def decode(self, data) +def decode(data)

Convert bytes into a string type for Python3.

@@ -14001,16 +15083,24 @@

Methods

Expand source code -
def decode(self, data):
+
@classmethod
+def decode(cls, data):
     # type: (bytes) -> str
     """Convert bytes into a string type for Python3."""
-    if self.__py3:
-        return data.decode(self.__codec)
+    if sys.version_info >= (3, 0):
+        for codec in cls.CODECS:
+            # On the last codec, do not catch the exception and let it trigger if it fails
+            if codec == cls.CODECS[-1]:
+                return data.decode(codec)
+            try:
+                return data.decode(codec)
+            except UnicodeDecodeError:
+                pass
     return data  # type: ignore
-def encode(self, data) +def encode(data)

Convert string into a byte type for Python3.

@@ -14018,18 +15108,60 @@

Methods

Expand source code -
def encode(self, data):
+
@classmethod
+def encode(cls, data):
     # type: (str) -> bytes
     """Convert string into a byte type for Python3."""
-    if self.__py3:
-        try:
-            return data.encode(self.__codec)
-        except UnicodeEncodeError:
-            # TODO: Add logging
-            return data.encode(self.__fallback)
+    if sys.version_info >= (3, 0):
+        for codec in cls.CODECS:
+            # On the last codec, do not catch the exception and let it trigger if it fails
+            if codec == cls.CODECS[-1]:
+                return data.encode(codec)
+            try:
+                return data.encode(codec)
+            except UnicodeEncodeError:
+                pass
     return data  # type: ignore
+
+def rstrip(data, search=None) +
+
+

Implementation of rstring which works on bytes or strings.

+
+ +Expand source code + +
@classmethod
+def rstrip(cls, data, search=None):
+    # type: (Union[bytes, str], Optional[str]) -> Union[bytes, str]
+    """Implementation of rstring which works on bytes or strings."""
+    # We have a bytes object in Python3
+    if sys.version_info >= (3, 0) and type(data) is not str:
+        # Strip whitespace
+        if search is None:
+            while True:
+                new = data
+                new = cls.rstrip(new, " ")
+                new = cls.rstrip(new, "\n")
+                new = cls.rstrip(new, "\r")
+                new = cls.rstrip(new, "\t")
+                # Loop until no more changes occur
+                if new == data:
+                    return new
+        else:
+            bsearch = StringEncoder.encode(search)
+            while data[-1:] == bsearch:
+                data = data[:-1]
+            return data
+
+    # Use native function
+    if search is None:
+        return data.rstrip()
+    return data.rstrip(search)  # type: ignore
+
+
@@ -14179,11 +15311,14 @@

Args

# -------------------------------------------------------------------------- @abstractmethod def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Implement a transformer function which transforms a string.. + Args: + data (bytes): data to be transformed. + Returns: - str: The transformed string. + bytes: The transformed string. """

Ancestors

@@ -14192,6 +15327,8 @@

Ancestors

Subclasses

@@ -14219,9 +15356,14 @@

Methods

Implement a transformer function which transforms a string..

+

Args

+
+
data : bytes
+
data to be transformed.
+

Returns

-
str
+
bytes
The transformed string.
@@ -14230,16 +15372,312 @@

Returns

@abstractmethod
 def transform(self, data):
-    # type: (str) -> str
+    # type: (bytes) -> bytes
     """Implement a transformer function which transforms a string..
 
+    Args:
+        data (bytes): data to be transformed.
+
     Returns:
-        str: The transformed string.
+        bytes: The transformed string.
     """
+
+class TransformHttpPack +(opts) +
+
+

Implement a transformation to pack data into HTTP packets.

+

Set specific options for this transformer.

+

Args

+
+
opts : DsTransformLinefeed
+
Transformer options.
+
+
+ +Expand source code + +
class TransformHttpPack(Transform):
+    """Implement a transformation to pack data into HTTP packets."""
+
+    # --------------------------------------------------------------------------
+    # Constructor / Destructor
+    # --------------------------------------------------------------------------
+    def __init__(self, opts):
+        # type: (Dict[str, str]) -> None
+        """Set specific options for this transformer.
+
+        Args:
+            opts (DsTransformLinefeed): Transformer options.
+
+        """
+        super(TransformHttpPack, self).__init__()
+        self.__opts = opts
+        self.__log = logging.getLogger(__name__)
+
+        assert "reply" in opts
+        assert opts["reply"] in ["request", "response"]
+
+        # Initial default header
+        self.__headers = [
+            "Accept-Charset: utf-8",
+        ]
+
+        self.__response_headers_sent = False
+
+    # --------------------------------------------------------------------------
+    # Public Functions
+    # --------------------------------------------------------------------------
+    def transform(self, data):
+        # type: (bytes) -> bytes
+        """Wrap data into a HTTP packet.
+
+        Returns:
+            bytes: The wrapped string.
+        """
+        request_header = [
+            "POST / HTTP/1.1",
+            "Host: {}".format(self.__opts["host"]),
+            "User-Agent: pwncat",
+            "Accept: */*",
+            "Conent-Length: {}".format(len(data)),
+            "Content-Type: text/plain; charset=UTF-8",
+        ]
+        response_header = [
+            "HTTP/1.1 200 OK",
+            "Date: {}".format(self.__get_date()),
+            "Server: pwncat",
+            "Conent-Length: {}".format(len(data)),
+            "Connection: close",
+        ]
+
+        self.__response_headers_sent = True
+
+        if self.__opts["reply"] == "request":
+            header = StringEncoder.encode(
+                "\n".join(request_header) + "\n" + "\n".join(self.__headers) + "\n\n"
+            )
+        else:
+            header = StringEncoder.encode(
+                "\n".join(response_header) + "\n" + "\n".join(self.__headers) + "\n\n"
+            )
+        return header + data
+
+    # --------------------------------------------------------------------------
+    # Private Functions
+    # --------------------------------------------------------------------------
+    def __get_date(self):  # pylint: disable=no-self-use
+        # type: () -> str
+        now = datetime.utcnow()
+        weekday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][now.weekday()]
+        month = [
+            "Jan",
+            "Feb",
+            "Mar",
+            "Apr",
+            "May",
+            "Jun",
+            "Jul",
+            "Aug",
+            "Sep",
+            "Oct",
+            "Nov",
+            "Dec",
+        ][now.month - 1]
+        return "%s, %02d %s %04d %02d:%02d:%02d GMT" % (
+            weekday,
+            now.day,
+            month,
+            now.year,
+            now.hour,
+            now.minute,
+            now.second,
+        )
+
+

Ancestors

+ +

Methods

+
+
+def transform(self, data) +
+
+

Wrap data into a HTTP packet.

+

Returns

+
+
bytes
+
The wrapped string.
+
+
+ +Expand source code + +
def transform(self, data):
+    # type: (bytes) -> bytes
+    """Wrap data into a HTTP packet.
+
+    Returns:
+        bytes: The wrapped string.
+    """
+    request_header = [
+        "POST / HTTP/1.1",
+        "Host: {}".format(self.__opts["host"]),
+        "User-Agent: pwncat",
+        "Accept: */*",
+        "Conent-Length: {}".format(len(data)),
+        "Content-Type: text/plain; charset=UTF-8",
+    ]
+    response_header = [
+        "HTTP/1.1 200 OK",
+        "Date: {}".format(self.__get_date()),
+        "Server: pwncat",
+        "Conent-Length: {}".format(len(data)),
+        "Connection: close",
+    ]
+
+    self.__response_headers_sent = True
+
+    if self.__opts["reply"] == "request":
+        header = StringEncoder.encode(
+            "\n".join(request_header) + "\n" + "\n".join(self.__headers) + "\n\n"
+        )
+    else:
+        header = StringEncoder.encode(
+            "\n".join(response_header) + "\n" + "\n".join(self.__headers) + "\n\n"
+        )
+    return header + data
+
+
+
+

Inherited members

+ +
+
+class TransformHttpUnpack +(opts) +
+
+

Implement a transformation to unpack data from HTTP packets.

+

Set specific options for this transformer.

+

Args

+
+
opts : DsTransformLinefeed
+
Transformer options.
+
+
+ +Expand source code + +
class TransformHttpUnpack(Transform):
+    """Implement a transformation to unpack data from HTTP packets."""
+
+    # --------------------------------------------------------------------------
+    # Constructor / Destructor
+    # --------------------------------------------------------------------------
+    def __init__(self, opts):
+        # type: (Dict[str, str]) -> None
+        """Set specific options for this transformer.
+
+        Args:
+            opts (DsTransformLinefeed): Transformer options.
+
+        """
+        super(TransformHttpUnpack, self).__init__()
+        self.__opts = opts
+        self.__log = logging.getLogger(__name__)
+
+    # --------------------------------------------------------------------------
+    # Public Functions
+    # --------------------------------------------------------------------------
+    def transform(self, data):
+        # type: (bytes) -> bytes
+        """Unwrap data from a HTTP packet.
+
+        Returns:
+            str: The wrapped string.
+        """
+        request = StringEncoder.encode(r"^(GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH)")
+        response = StringEncoder.encode(r"^HTTP/[.0-9]+")
+
+        # Did not receive a valid HTTP request, so we return the original untransformed message
+        if not (re.match(request, data) or re.match(response, data)):
+            return data
+
+        body = StringEncoder.encode(r"(\r\n\r\n|\n\n)(.*)")
+        match = re.search(body, data)
+
+        # Check if we can separate headers and body
+        if match is None or len(match.group()) < 2:
+            return data
+        return match.group(2)
+
+

Ancestors

+ +

Methods

+
+
+def transform(self, data) +
+
+

Unwrap data from a HTTP packet.

+

Returns

+
+
str
+
The wrapped string.
+
+
+ +Expand source code + +
def transform(self, data):
+    # type: (bytes) -> bytes
+    """Unwrap data from a HTTP packet.
+
+    Returns:
+        str: The wrapped string.
+    """
+    request = StringEncoder.encode(r"^(GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH)")
+    response = StringEncoder.encode(r"^HTTP/[.0-9]+")
+
+    # Did not receive a valid HTTP request, so we return the original untransformed message
+    if not (re.match(request, data) or re.match(response, data)):
+        return data
+
+    body = StringEncoder.encode(r"(\r\n\r\n|\n\n)(.*)")
+    match = re.search(body, data)
+
+    # Check if we can separate headers and body
+    if match is None or len(match.group()) < 2:
+        return data
+    return match.group(2)
+
+
+
+

Inherited members

+ +
class TransformLinefeed (opts) @@ -14277,7 +15715,7 @@

Args

# Public Functions # -------------------------------------------------------------------------- def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Transform linefeeds to CRLF, LF or CR if requested. Returns: @@ -14289,39 +15727,39 @@

Args

# ? -> No line feeds if self.__opts.crlf == "no": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Removing CRLF") return data[:-2] - if data.endswith("\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Removing LF") return data[:-1] - if data.endswith("\r"): + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Removing CR") return data[:-1] # ? -> CRLF - if self.__opts.crlf == "crlf" and not data.endswith("\r\n"): - if data.endswith("\n"): + if self.__opts.crlf == "crlf" and data[-2:] != StringEncoder.encode("\r\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CRLF") - return data[:-1] + "\r\n" - if data.endswith("\r"): + return data[:-1] + StringEncoder.encode("\r\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with CRLF") - return data[:-1] + "\r\n" + return data[:-1] + StringEncoder.encode("\r\n") # ? -> LF if self.__opts.crlf == "lf": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with LF") - return data[:-2] + "\n" - if data.endswith("\r"): + return data[:-2] + StringEncoder.encode("\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with LF") - return data[:-1] + "\n" + return data[:-1] + StringEncoder.encode("\n") # ? -> CR if self.__opts.crlf == "cr": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with CR") - return data[:-2] + "\r" - if data.endswith("\n"): + return data[:-2] + StringEncoder.encode("\r") + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CR") - return data[:-1] + "\r" + return data[:-1] + StringEncoder.encode("\r") # Otherwise just return it as it is return data
@@ -14348,7 +15786,7 @@

Returns

Expand source code
def transform(self, data):
-    # type: (str) -> str
+    # type: (bytes) -> bytes
     """Transform linefeeds to CRLF, LF or CR if requested.
 
     Returns:
@@ -14360,39 +15798,39 @@ 

Returns

# ? -> No line feeds if self.__opts.crlf == "no": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Removing CRLF") return data[:-2] - if data.endswith("\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Removing LF") return data[:-1] - if data.endswith("\r"): + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Removing CR") return data[:-1] # ? -> CRLF - if self.__opts.crlf == "crlf" and not data.endswith("\r\n"): - if data.endswith("\n"): + if self.__opts.crlf == "crlf" and data[-2:] != StringEncoder.encode("\r\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CRLF") - return data[:-1] + "\r\n" - if data.endswith("\r"): + return data[:-1] + StringEncoder.encode("\r\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with CRLF") - return data[:-1] + "\r\n" + return data[:-1] + StringEncoder.encode("\r\n") # ? -> LF if self.__opts.crlf == "lf": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with LF") - return data[:-2] + "\n" - if data.endswith("\r"): + return data[:-2] + StringEncoder.encode("\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with LF") - return data[:-1] + "\n" + return data[:-1] + StringEncoder.encode("\n") # ? -> CR if self.__opts.crlf == "cr": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with CR") - return data[:-2] + "\r" - if data.endswith("\n"): + return data[:-2] + StringEncoder.encode("\r") + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CR") - return data[:-1] + "\r" + return data[:-1] + StringEncoder.encode("\r") # Otherwise just return it as it is return data
@@ -14446,15 +15884,15 @@

Args

# Public Functions # -------------------------------------------------------------------------- def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Raise a stop signal upon receiving the safeword. Returns: str: The string as it is without changes """ - if self.__opts.safeword in data: - self.__log.info("Received safeword: raising stop signal.") - self.__opts.ssig.raise_stop() + if StringEncoder.encode(self.__opts.safeword) in data: + self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore + self.__opts.ssig.raise_terminate() return data

Ancestors

@@ -14479,15 +15917,15 @@

Returns

Expand source code
def transform(self, data):
-    # type: (str) -> str
+    # type: (bytes) -> bytes
     """Raise a stop signal upon receiving the safeword.
 
     Returns:
         str: The string as it is without changes
     """
-    if self.__opts.safeword in data:
-        self.__log.info("Received safeword: raising stop signal.")
-        self.__opts.ssig.raise_stop()
+    if StringEncoder.encode(self.__opts.safeword) in data:
+        self.log.trace("TERMINATE signal REQ in TransformSafeword.transform")  # type: ignore
+        self.__opts.ssig.raise_terminate()
     return data
@@ -14604,6 +16042,7 @@

DsIOS
  • @@ -14624,7 +16063,7 @@

    DsR
  • kwargs
  • pause
  • repeat
  • -
  • signal
  • +
  • ssig
  • @@ -14634,7 +16073,7 @@

    DsRunnerT
  • args
  • intvl
  • kwargs
  • -
  • signal
  • +
  • ssig
  • @@ -14714,6 +16153,19 @@

    IOStdinSt

  • +

    InterruptHandler

    + +
  • +
  • Net

  • -

    StopSignal

    - -
  • -
  • StringEncoder

  • @@ -14793,6 +16239,18 @@

    Transform

  • +

    TransformHttpPack

    + +
  • +
  • +

    TransformHttpUnpack

    + +
  • +
  • TransformLinefeed

    • transform
    • diff --git a/docs/pwncat.man.html b/docs/pwncat.man.html index 350452f8..99b0dbc2 100644 --- a/docs/pwncat.man.html +++ b/docs/pwncat.man.html @@ -155,6 +155,21 @@

      DESCRIPTION

      Do not resolve DNS.

      + +

      −−send−on−eof

      + +

      Buffer data received on stdin +until EOF and send everything in one chunk.

      + + +

      −−no−shutdown

      + +

      Do not shutdown into +half−duplex mode. If this option is passed, pwncat +won’t invoke shutdown on a socket after seeing EOF on +stdin. This is provided for backward−compatibility +with OpenBSD netcat, which exhibits this behavior.

      +

      −v, −−verbose

      diff --git a/docs/pwncat.type.html b/docs/pwncat.type.html index 9cbc8889..3396a6b8 100644 --- a/docs/pwncat.type.html +++ b/docs/pwncat.type.html @@ -15,12 +15,20 @@

      Mypy Type Check Coverage Summary

      Total 6.44% imprecise +<<<<<<< HEAD 5283 LOC +======= +5687 LOC +>>>>>>> Heavy refactoring bin/pwncat 6.44% imprecise +<<<<<<< HEAD 5283 LOC +======= +5687 LOC +>>>>>>> Heavy refactoring @@ -5318,6 +5326,413 @@

      pwncat

      5281 5282 5283 +<<<<<<< HEAD +======= +5284 +5285 +5286 +5287 +5288 +5289 +5290 +5291 +5292 +5293 +5294 +5295 +5296 +5297 +5298 +5299 +5300 +5301 +5302 +5303 +5304 +5305 +5306 +5307 +5308 +5309 +5310 +5311 +5312 +5313 +5314 +5315 +5316 +5317 +5318 +5319 +5320 +5321 +5322 +5323 +5324 +5325 +5326 +5327 +5328 +5329 +5330 +5331 +5332 +5333 +5334 +5335 +5336 +5337 +5338 +5339 +5340 +5341 +5342 +5343 +5344 +5345 +5346 +5347 +5348 +5349 +5350 +5351 +5352 +5353 +5354 +5355 +5356 +5357 +5358 +5359 +5360 +5361 +5362 +5363 +5364 +5365 +5366 +5367 +5368 +5369 +5370 +5371 +5372 +5373 +5374 +5375 +5376 +5377 +5378 +5379 +5380 +5381 +5382 +5383 +5384 +5385 +5386 +5387 +5388 +5389 +5390 +5391 +5392 +5393 +5394 +5395 +5396 +5397 +5398 +5399 +5400 +5401 +5402 +5403 +5404 +5405 +5406 +5407 +5408 +5409 +5410 +5411 +5412 +5413 +5414 +5415 +5416 +5417 +5418 +5419 +5420 +5421 +5422 +5423 +5424 +5425 +5426 +5427 +5428 +5429 +5430 +5431 +5432 +5433 +5434 +5435 +5436 +5437 +5438 +5439 +5440 +5441 +5442 +5443 +5444 +5445 +5446 +5447 +5448 +5449 +5450 +5451 +5452 +5453 +5454 +5455 +5456 +5457 +5458 +5459 +5460 +5461 +5462 +5463 +5464 +5465 +5466 +5467 +5468 +5469 +5470 +5471 +5472 +5473 +5474 +5475 +5476 +5477 +5478 +5479 +5480 +5481 +5482 +5483 +5484 +5485 +5486 +5487 +5488 +5489 +5490 +5491 +5492 +5493 +5494 +5495 +5496 +5497 +5498 +5499 +5500 +5501 +5502 +5503 +5504 +5505 +5506 +5507 +5508 +5509 +5510 +5511 +5512 +5513 +5514 +5515 +5516 +5517 +5518 +5519 +5520 +5521 +5522 +5523 +5524 +5525 +5526 +5527 +5528 +5529 +5530 +5531 +5532 +5533 +5534 +5535 +5536 +5537 +5538 +5539 +5540 +5541 +5542 +5543 +5544 +5545 +5546 +5547 +5548 +5549 +5550 +5551 +5552 +5553 +5554 +5555 +5556 +5557 +5558 +5559 +5560 +5561 +5562 +5563 +5564 +5565 +5566 +5567 +5568 +5569 +5570 +5571 +5572 +5573 +5574 +5575 +5576 +5577 +5578 +5579 +5580 +5581 +5582 +5583 +5584 +5585 +5586 +5587 +5588 +5589 +5590 +5591 +5592 +5593 +5594 +5595 +5596 +5597 +5598 +5599 +5600 +5601 +5602 +5603 +5604 +5605 +5606 +5607 +5608 +5609 +5610 +5611 +5612 +5613 +5614 +5615 +5616 +5617 +5618 +5619 +5620 +5621 +5622 +5623 +5624 +5625 +5626 +5627 +5628 +5629 +5630 +5631 +5632 +5633 +5634 +5635 +5636 +5637 +5638 +5639 +5640 +5641 +5642 +5643 +5644 +5645 +5646 +5647 +5648 +5649 +5650 +5651 +5652 +5653 +5654 +5655 +5656 +5657 +5658 +5659 +5660 +5661 +5662 +5663 +5664 +5665 +5666 +5667 +5668 +5669 +5670 +5671 +5672 +5673 +5674 +5675 +5676 +5677 +5678 +5679 +5680 +5681 +5682 +5683 +5684 +5685 +5686 +5687 +>>>>>>> Heavy refactoring
      #!/usr/bin/env python3
       """pwncat."""
      @@ -5330,7 +5745,7 @@ 

      pwncat

      # 4. Transformer # 5. IO modules # 6. PSE Store -# 7. IO Runner +# 7. IO Runner / InterruptHandler # 8. Command & Control # 9. Command line arguments # 10. Main entrypoint @@ -5370,7 +5785,7 @@

      pwncat

      # # 4. Signaling / Interrupts # ------------------------------------ -# The StopSignal instance is distributed across all Threads and and the Runner instance and +# The InterruptHandler instance is distributed across all Threads and and the Runner instance and # is a way to let other Threads know that a stop signal has been requested. # Producer/Consumer can implement their own interrupt function so they can be stopped from # inside (if they do non-blocking stuff) or from outside (if they do blocking stuff). @@ -5379,17 +5794,18 @@

      pwncat

      from abc import abstractmethod from abc import ABCMeta +from datetime import datetime from subprocess import PIPE from subprocess import Popen from subprocess import STDOUT import argparse -import atexit import base64 import logging import os import re import select +import signal import socket import sys import threading @@ -5400,12 +5816,15 @@

      pwncat

      import ipaddress except ImportError: pass +<<<<<<< HEAD # Posix terminal try: import tty import termios except ImportError: pass +======= +>>>>>>> Heavy refactoring # Windows try: import msvcrt @@ -5448,12 +5867,16 @@

      pwncat

      APPNAME = "pwncat" APPREPO = "https://github.com/cytopia/pwncat" +<<<<<<< HEAD VERSION = "0.0.23-alpha" +======= +VERSION = "0.1.0" +>>>>>>> Heavy refactoring # Default timeout for timeout-based sys.stdin and socket.recv -TIMEOUT_READ_STDIN = 0.1 -TIMEOUT_RECV_SOCKET = 0.1 -TIMEOUT_RECV_SOCKET_RETRY = 2 +TIMEOUT_READ_STDIN = 0.05 +TIMEOUT_RECV_SOCKET = 0.05 +TIMEOUT_RECV_SOCKET_RETRY = 1 # https://docs.python.org/3/library/subprocess.html#popen-constructor # * 0 means unbuffered (read and write are one system call and can return short) @@ -5539,7 +5962,7 @@

      pwncat

      @property def function(self): - # type: () -> Callable[..., Iterator[str]] + # type: () -> Callable[..., Iterator[bytes]] """`IO.producer`: Callable funtcion function.""" return self.__function @@ -5565,7 +5988,7 @@

      pwncat

      # -------------------------------------------------------------------------- def __init__(self, function, *args, **kwargs): - # type: (Callable[..., Iterator[str]], Any, Any) -> None + # type: (Callable[..., Iterator[bytes]], Any, Any) -> None self.__function = function @property def consumer(self): - # type: () -> Callable[[str], None] + # type: () -> Callable[[bytes], None] """`IO.consumer`: Data consumer function.""" return self.__consumer @@ -5619,7 +6042,7 @@

      pwncat

      def __init__( self, producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] interrupts, # type: List[Callable[[], None]] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] @@ -5672,10 +6095,10 @@

      pwncat

      Explicit (x1)"> return self.__kwargs @property - def signal(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance.""" - return self.__signal + def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig # -------------------------------------------------------------------------- # Constructor @@ -5684,7 +6107,7 @@

      pwncat

      Explicit (x4)"> def __init__( self, action, # type: Callable[..., None] - signal, # type: StopSignal + ssig, # type: InterruptHandler intvl, # type: int *args, # type: Tuple[Any, ...] **kwargs # type: Dict[str, Any] @@ -5696,7 +6119,7 @@

      pwncat

      Explicit (x6)"> assert type(kwargs) is dict, type(kwargs) self.__action = action - self.__signal = signal + self.__ssig = ssig self.__intvl = intvl self.__args = args @@ -5750,10 +6173,10 @@

      pwncat

      Explicit (x1)"> return self.__kwargs @property - def signal(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance.""" - return self.__signal + def ssig(self): + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" + return self.__ssig # -------------------------------------------------------------------------- # Constructor @@ -5762,7 +6185,7 @@

      pwncat

      Explicit (x4)"> def __init__( self, action, # type: Callable[..., None] - signal, # type: StopSignal + ssig, # type: InterruptHandler repeat, # type: int pause, # type: float *args, # type: Tuple[Any, ...] @@ -5777,7 +6200,7 @@

      pwncat

      Explicit (x6)"> assert type(kwargs) is dict, type(kwargs) self.__action = action - self.__signal = signal + self.__ssig = ssig self.__repeat = repeat self.__pause = pause # -------------------------------------------------------------------------- @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: StopSignal instance to trigger a shutdown signal.""" + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance to trigger a shutdown signal.""" return self.__ssig @property @@ -6161,7 +6584,7 @@

      pwncat

      # Constructor # -------------------------------------------------------------------------- def __init__(self, ssig, safeword): - # type: (StopSignal, str) -> None + # type: (InterruptHandler, str) -> None super(DsTransformSafeword, self).__init__() self.__ssig = ssig self.__safeword = safeword @@ -6188,14 +6611,21 @@

      pwncat

      """`float`: Input timeout in seconds for non-blocking read or `None` for blocking.""" return self.__input_timeout + @property + def send_on_eof(self): + # type: () -> bool + """`float`: Determines if we buffer STDIN until EOF before sending.""" + return self.__send_on_eof + # -------------------------------------------------------------------------- # Constructor # -------------------------------------------------------------------------- - def __init__(self, encoder, input_timeout): - # type: (StringEncoder, Optional[float]) -> None + def __init__(self, encoder, input_timeout, send_on_eof): + # type: (StringEncoder, Optional[float], bool) -> None super(DsIOStdinStdout, self).__init__() self.__enc = encoder self.__input_timeout = input_timeout + self.__send_on_eof = send_on_eof # ------------------------------------------------------------------------------------------------- @@ -6251,7 +6681,7 @@

      pwncat

      # ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (1/4) TraceLogger +# [3/11 LIBRARY CLASSES]: (1/3) TraceLogger # ------------------------------------------------------------------------------------------------- class TraceLogger(logging.getLoggerClass()): # type: ignore """Extend Python's default logger class with TRACE level logging.""" @@ -6293,7 +6723,7 @@

      pwncat

      # ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (2/4) ColoredLogFormatter +# [3/11 LIBRARY CLASSES]: (2/3) ColoredLogFormatter # ------------------------------------------------------------------------------------------------- class ColoredLogFormatter(logging.Formatter): """Custom log formatter which adds different details and color support.""" @@ -6366,7 +6796,7 @@

      pwncat

      # ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (3/4) StringEncoder +# [3/11 LIBRARY CLASSES]: (3/3) StringEncoder # ------------------------------------------------------------------------------------------------- class StringEncoder(object): """Takes care about Python 2/3 string encoding/decoding. @@ -6375,72 +6805,74 @@

      pwncat

      classes or functions as strings to keep full Python 2/3 compat. """ - # -------------------------------------------------------------------------- - # Constructor - # -------------------------------------------------------------------------- - def __init__(self): - # type: () -> None - """Create a StringEncoder instance which converts str/bytes according to Python version.""" - self.__py3 = sys.version_info >= (3, 0) # type: bool - - # https://stackoverflow.com/questions/606191/27527728#27527728 - self.__codec = "cp437" - self.__fallback = "latin-1" + CODECS = [ + "utf-8", + "cp437", + "latin-1", + ] # -------------------------------------------------------------------------- - # Public Functions + # Class methods # -------------------------------------------------------------------------- - def encode(self, data): + @classmethod + def rstrip(cls, data, search=None): + # type: (Union[bytes, str], Optional[str]) -> Union[bytes, str] + """Implementation of rstring which works on bytes or strings.""" + # We have a bytes object in Python3 + if sys.version_info >= (3, 0) and type(data) is not str: + # Strip whitespace + if search is None: + while True: + new = data + new = cls.rstrip(new, " ") + new = cls.rstrip(new, "\n") + new = cls.rstrip(new, "\r") + new = cls.rstrip(new, "\t") + # Loop until no more changes occur + if new == data: + return new + else: + bsearch = StringEncoder.encode(search) + while data[-1:] == bsearch: + data = data[:-1] + return data + + # Use native function + if search is None: + return data.rstrip() + return data.rstrip(search) # type: ignore + + @classmethod + def encode(cls, data): # type: (str) -> bytes """Convert string into a byte type for Python3.""" - if self.__py3: - try: - return data.encode(self.__codec) - except UnicodeEncodeError: - # TODO: Add logging - return data.encode(self.__fallback) + if sys.version_info >= (3, 0): + for codec in cls.CODECS: + # On the last codec, do not catch the exception and let it trigger if it fails + if codec == cls.CODECS[-1]: + return data.encode(codec) + try: + return data.encode(codec) + except UnicodeEncodeError: + pass return data # type: ignore - def decode(self, data): + @classmethod + def decode(cls, data): # type: (bytes) -> str """Convert bytes into a string type for Python3.""" - if self.__py3: - return data.decode(self.__codec) + if sys.version_info >= (3, 0): + for codec in cls.CODECS: + # On the last codec, do not catch the exception and let it trigger if it fails + if codec == cls.CODECS[-1]: + return data.decode(codec) + try: + return data.decode(codec) + except UnicodeDecodeError: + pass return data # type: ignore - def base64_encode(self, data): - # type: (str) -> str - """Convert string into a base64 encoded string.""" - return self.decode(base64.b64encode(self.encode(data))) - - -# ------------------------------------------------------------------------------------------------- -# [3/11 LIBRARY CLASSES]: (4/4): StopSignal -# ------------------------------------------------------------------------------------------------- -class StopSignal(object): - """Provide a simple boolean switch.""" - - # -------------------------------------------------------------------------- - # Constructor - # -------------------------------------------------------------------------- - def __init__(self): - # type: () -> None - """Create a StopSignal instance.""" - self.__stop = False - - # -------------------------------------------------------------------------- - # Public Functions - # -------------------------------------------------------------------------- - def has_stop(self): - # type: () -> bool - """Check if a stop signal has been raised.""" - return self.__stop - - def raise_stop(self): - # type: () -> None - """Raise a stop signal.""" - self.__stop = True - # ################################################################################################# # ################################################################################################# @@ -6454,7 +6886,7 @@

      pwncat

      # [4/11 NETWORK]: (1/1) Sock # ------------------------------------------------------------------------------------------------- class Sock(_Singleton("SingletonMeta", (object,), {})): # type: ignore - """Thread-safe singleton Socket helper to emulate a module within the same file.""" + """Thread-safe singleton Socket wrapper to emulate a module within the same file.""" def __init__(self): # type: () -> None @@ -6947,18 +7379,24 @@

      pwncat

      Explicit (x4)"> self.__log.error(msg) raise socket.error(msg) - def accept(self, sockets, fstop): - # type: (List[socket.socket], Callable[[], bool]) -> Tuple[socket.socket, Tuple[str, int]] + def accept( + self, + sockets, # type: List[socket.socket] + has_quit, # type: Callable[[], bool] + select_timeout=0.01, # type: float + ): + # type: (...) -> Tuple[socket.socket, Tuple[str, int]] """Accept a single connection from given list of sockets. Given sockets must be bound to an addr and listening for connections. Args: sock ([socket.socket]): List of sockets IPv4 and/or IPv6 to accept on. - fstop (Callable[[], bool]): A function that returns True if abort is requested. + has_quit (Callable[[], bool]): A function that returns True if abort is requested. + select_timeout (float): Timeout to poll sockets for connected clients. Returns: - socket.socket: Returns the connection socket (whatever protocol was faster). + (socket.socket, str, int): Returns tuple of socket, address and port of client. Raises: socket.error: Raised if server cannot accept connection or stop signal is requested. @@ -6967,9 +7405,11 @@

      pwncat

      Explicit (x4)"> self.__log.debug("Waiting for TCP client") while True: ssockets = select.select(sockets, [], [], 0.01)[0] # type: List[socket.socket] - if fstop(): - raise socket.error("StopSignal acknknowledged") +Explicit (x10)"> ssockets = select.select(sockets, [], [], select_timeout)[ + 0 + ] # type: List[socket.socket] + if has_quit(): + raise socket.error("SOCK-QUIT signal ACK for accept(): raised socket.error()") for sock in ssockets: try: conn, addr = sock.accept() @@ -7009,13 +7449,18 @@

      pwncat

      port (int): Port of server to connect to. Returns: - Tuple[str,int]: Adress/port tuple of local bin of the client. + Tuple[str,int]: Adress/port tuple of local bind of the client. Raises: socker.error: If client cannot connect to remote peer or custom bind did not succeed. """ - sock_family_name = self.get_family_name(sock.family) - sock_type_name = self.get_type_name(sock.type) + try: + # If the socket was already closed elsewhere, it won't have family or type anymore + sock_family_name = self.get_family_name(sock.family) + sock_type_name = self.get_type_name(sock.type) + except AttributeError as error: + raise socket.error(error) + # Bind to a custom addr/port if src_addr is not None and src_port is not None: try: @@ -7129,12 +7574,12 @@

      pwncat

      # Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, encoder, ssig, options): - # type: (StringEncoder, StopSignal, DsSock) -> None + # type: (StringEncoder, InterruptHandler, DsSock) -> None """Instantiate Sock class. Args: encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). - ssig (StopSignal): Used to stop blocking loops. + ssig (InterruptHandler): Used to stop blocking loops. options (DsSock): Instance of DsSock. """ self.__log = logging.getLogger(__name__) # type: logging.Logger @@ -7204,14 +7649,17 @@

      pwncat

      # Public Send / Receive Functions # -------------------------------------------------------------------------- def send(self, data): - # type: (str) -> int + # type: (bytes) -> int """Send data through a connected (TCP) or unconnected (UDP) socket. Args: - data (str): The data to send. + data (bytes): The data to send. Returns: int: Returns total bytes sent. + + Raises: + socket.error: Except here when unconnected or connection was forcibly closed. """ # UDP has some specialities as its socket is unconnected. # See also recv() for specialities on that side. @@ -7224,16 +7672,19 @@

      pwncat

      self.__log.warning("UDP client has not yet connected. Queueing message") while not self.__active: + if self.__ssig.has_sock_quit(): + self.__log.trace( # type: ignore + "SOCK-QUIT signal ACK in Net.send (while waiting for UDP client)" + ) + return -1 time.sleep(0.01) curr = 0 # bytes send during one loop iteration send = 0 # total bytes send size = len(data) # bytes of data that needs to be send - byte = self.__enc.encode(data) - assert size == len(byte), "Encoding messed up string length, might need to do len() after." # Loop until all bytes have been send - # TODO: Does this make it impossible to send nullbytes (Ctrl+d) while send < size: self.__log.debug( @@ -7243,25 +7694,25 @@

      pwncat

      self.__active["remote_port"], ) self.__log.trace("Trying to send: %s", repr(byte)) # type: ignore +Error (x2)"> self.__log.trace("Trying to send: %s", repr(data)) # type: ignore try: # Only UDP server has not made a connect() to the socket, all others # are already connected and need to use send() instead of sendto() if self.__udp_mode_server: curr = self.__active["conn"].sendto( - byte, (self.__active["remote_addr"], self.__active["remote_port"]) + data, (self.__active["remote_addr"], self.__active["remote_port"]) ) send += curr else: - curr = self.__active["conn"].send(byte) + curr = self.__active["conn"].send(data) send += curr if curr == 0: self.__log.error("No bytes send during loop round.") return 0 # Remove 'curr' many bytes from byte for the next round - byte = byte[curr:] + data = data[curr:] self.__log.debug( "Sent %d bytes to %s:%d (%d bytes remaining)", @@ -7270,24 +7721,23 @@

      pwncat

      self.__active["remote_port"], size - send, ) - except (OSError, socket.error) as error: - self.__log.error("Socket OS Error: %s", error) - return send + except (BrokenPipeError, OSError, socket.error) as error: + msg = "Socket send Error: {}".format(error) + raise socket.error(msg) return send def receive(self): - # type: () -> str + # type: () -> bytes """Receive and return data from the connected (TCP) or unconnected (UDP) socket. Returns: - str: Returns received data from connected (TCP) or unconnected (UDP) socket. + bytes: Returns received data from connected (TCP) or unconnected (UDP) socket. Raises: socket.timeout: Except here to do an action when the socket is not busy. AttributeError: Except here when current instance has closed itself (Ctrl+c). socket.error: Except here when unconnected or connection was forcibly closed. - EOFError: Except here when upstream has closed the connection. + EOFError: Except here when upstream has closed the connection via EOF. """ # This is required for a UDP server that has no connected clients yet # and is waiting for data receival for the first time on either IPv4 or IPv6 @@ -7304,10 +7754,10 @@

      pwncat

      0 ] # type: List[socket.socket] # E.g.: ValueError: file descriptor cannot be a negative integer (-1) - except (ValueError, AttributeError): - msg = "Connection was closed by self." + except (ValueError, AttributeError) as error: + msg = "Connection was closed by self: [1]: {}".format(error) self.__log.warning(msg) +Explicit (x4)"> self.__log.debug(msg) raise AttributeError(msg) if not conns: # This is raised for the calling function to determine what to do @@ -7319,13 +7769,13 @@

      pwncat

      conn = conns[0] # type: socket.socket try: # https://manpages.debian.org/buster/manpages-dev/recv.2.en.html - (byte, addr) = conn.recvfrom(self.__options.bufsize) + (data, addr) = conn.recvfrom(self.__options.bufsize) # [1/5] When closing itself (e.g.: via Ctrl+c and the socket_close() funcs are called) - except AttributeError: - msg = "Connection was closed by self." + except AttributeError as error: + msg = "Connection was closed by self: [2]: {}".format(error) self.__log.warning(msg) +Explicit (x4)"> self.__log.debug(msg) raise AttributeError(msg) # [2/5] Connection was forcibly closed @@ -7334,14 +7784,14 @@

      pwncat

      # [WinError 10054] An existing connection was forcibly closed by the remote host except (OSError, socket.error) as error: self.__log.warning("Connection error: %s", error) +Explicit (x4)"> self.__log.debug("Connection error: %s", error) raise socket.error(error) # [3/5] Upstream (server or client) is gone. # In TCP, there is no such thing as an empty message, so zero means a peer disconnect. # In UDP, there is no such thing as a peer disconnect, so zero means an empty datagram. - if not byte: - msg = "Upstream has closed the connection." + if not data: + msg = "EOF: Remote finished sending." self.__log.info(msg) raise EOFError(msg) @@ -7382,7 +7832,6 @@

      pwncat

      } # [5/5] We have data to process - data = self.__enc.decode(byte) self.__log.debug( "Received %d bytes from %s:%d", @@ -7634,25 +8083,28 @@

      pwncat

      return False # (2/3) Accept + remove = {} try: conn, client = self.__sock.accept( - [conns[family]["sock"] for family in conns], self.__ssig.has_stop + [conns[family]["sock"] for family in conns], self.__ssig.has_sock_quit ) conns[conn.family]["conn"] = conn conns[conn.family]["remote_addr"] = client[0] conns[conn.family]["remote_port"] = client[1] except socket.error as err: - # On error, remove all bind sockets - for family in conns: + remove = {family: str(err) for family in conns} + # On error, remove all bind sockets + for family in remove: self.__log.debug( - "Removing (family %d/%s) due to: %s", - family, - self.__sock.get_family_name(family), - err, - ) - self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) - del conns[family] +Explicit (x4)"> self.__log.debug( + "Removing (family %d/%s) due to: %s", + family, + self.__sock.get_family_name(family), + remove[family], + ) + self.__sock.close(conns[family]["sock"], self.__sock.get_family_name(family)) + del conns[family] + if not conns: return False # (3/3) Store connections @@ -7686,7 +8138,7 @@

      pwncat

      # [2/3] Accept try: conn, client = self.__sock.accept( - [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_stop + [self.__conns[family]["sock"] for family in self.__conns], self.__ssig.has_sock_quit ) except socket.error: return False @@ -7727,7 +8179,7 @@

      pwncat

      # ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (1/3): Transform +# [5/11 TRANSFORM]: (1/5): Transform # ------------------------------------------------------------------------------------------------- class Transform(ABC): # type: ignore """Abstract class to for pwncat I/O transformers. @@ -7759,16 +8211,19 @@

      pwncat

      # -------------------------------------------------------------------------- @abstractmethod def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Implement a transformer function which transforms a string.. + Args: + data (bytes): data to be transformed. + Returns: - str: The transformed string. + bytes: The transformed string. """ # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (2/3) TransformLinefeed +# [5/11 TRANSFORM]: (2/5) TransformLinefeed # ------------------------------------------------------------------------------------------------- class TransformLinefeed(Transform): """Implement basic linefeed replacement.""" @@ -7791,7 +8246,7 @@

      pwncat

      # Public Functions # -------------------------------------------------------------------------- def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Transform linefeeds to CRLF, LF or CR if requested. Returns: @@ -7803,55 +8258,55 @@

      pwncat

      # ? -> No line feeds if self.__opts.crlf == "no": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Removing CRLF") return data[:-2] - if data.endswith("\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Removing LF") return data[:-1] - if data.endswith("\r"): + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Removing CR") return data[:-1] # ? -> CRLF - if self.__opts.crlf == "crlf" and not data.endswith("\r\n"): - if data.endswith("\n"): + if self.__opts.crlf == "crlf" and data[-2:] != StringEncoder.encode("\r\n"): + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CRLF") - return data[:-1] + "\r\n" - if data.endswith("\r"): + return data[:-1] + StringEncoder.encode("\r\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with CRLF") - return data[:-1] + "\r\n" + return data[:-1] + StringEncoder.encode("\r\n") # ? -> LF if self.__opts.crlf == "lf": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with LF") - return data[:-2] + "\n" - if data.endswith("\r"): + return data[:-2] + StringEncoder.encode("\n") + if data[-1:] == StringEncoder.encode("\r"): self.log.debug("Replacing CR with LF") - return data[:-1] + "\n" + return data[:-1] + StringEncoder.encode("\n") # ? -> CR if self.__opts.crlf == "cr": - if data.endswith("\r\n"): + if data[-2:] == StringEncoder.encode("\r\n"): self.log.debug("Replacing CRLF with CR") - return data[:-2] + "\r" - if data.endswith("\n"): + return data[:-2] + StringEncoder.encode("\r") + if data[-1:] == StringEncoder.encode("\n"): self.log.debug("Replacing LF with CR") - return data[:-1] + "\r" + return data[:-1] + StringEncoder.encode("\r") # Otherwise just return it as it is return data # ------------------------------------------------------------------------------------------------- -# [5/11 TRANSFORM]: (3/3) TransformSafeword +# [5/11 TRANSFORM]: (3/5) TransformSafeword # ------------------------------------------------------------------------------------------------- class TransformSafeword(Transform): """Implement a trigger to emergency shutdown upon receival of a specific safeword.""" @@ -7875,19 +8330,167 @@

      pwncat

      # Public Functions # -------------------------------------------------------------------------- def transform(self, data): - # type: (str) -> str + # type: (bytes) -> bytes """Raise a stop signal upon receiving the safeword. Returns: str: The string as it is without changes """ - if self.__opts.safeword in data: + if StringEncoder.encode(self.__opts.safeword) in data: self.__log.info("Received safeword: raising stop signal.") - self.__opts.ssig.raise_stop() +Error (x2)"> self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore + self.__opts.ssig.raise_terminate() return data +# ------------------------------------------------------------------------------------------------- +# [5/11 TRANSFORM]: (4/5) TransformHttpPack +# ------------------------------------------------------------------------------------------------- +class TransformHttpPack(Transform): + """Implement a transformation to pack data into HTTP packets.""" + + # -------------------------------------------------------------------------- + # Constructor / Destructor + # -------------------------------------------------------------------------- + def __init__(self, opts): + # type: (Dict[str, str]) -> None + """Set specific options for this transformer. + + Args: + opts (DsTransformLinefeed): Transformer options. + + """ + super(TransformHttpPack, self).__init__() + self.__opts = opts + self.__log = logging.getLogger(__name__) + + assert "reply" in opts + assert opts["reply"] in ["request", "response"] + + # Initial default header + self.__headers = [ + "Accept-Charset: utf-8", + ] + + self.__response_headers_sent = False + + # -------------------------------------------------------------------------- + # Public Functions + # -------------------------------------------------------------------------- + def transform(self, data): + # type: (bytes) -> bytes + """Wrap data into a HTTP packet. + + Returns: + bytes: The wrapped string. + """ + request_header = [ + "POST / HTTP/1.1", + "Host: {}".format(self.__opts["host"]), + "User-Agent: pwncat", + "Accept: */*", + "Conent-Length: {}".format(len(data)), + "Content-Type: text/plain; charset=UTF-8", + ] + response_header = [ + "HTTP/1.1 200 OK", + "Date: {}".format(self.__get_date()), + "Server: pwncat", + "Conent-Length: {}".format(len(data)), + "Connection: close", + ] + + self.__response_headers_sent = True + + if self.__opts["reply"] == "request": + header = StringEncoder.encode( + "\n".join(request_header) + "\n" + "\n".join(self.__headers) + "\n\n" + ) + else: + header = StringEncoder.encode( + "\n".join(response_header) + "\n" + "\n".join(self.__headers) + "\n\n" + ) + return header + data + + # -------------------------------------------------------------------------- + # Private Functions + # -------------------------------------------------------------------------- + def __get_date(self): # pylint: disable=no-self-use + # type: () -> str + now = datetime.utcnow() + weekday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][now.weekday()] + month = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ][now.month - 1] + return "%s, %02d %s %04d %02d:%02d:%02d GMT" % ( + weekday, + now.day, + month, + now.year, + now.hour, + now.minute, + now.second, + ) + + +# ------------------------------------------------------------------------------------------------- +# [5/11 TRANSFORM]: (5/5) TransformHttpUnpack +# ------------------------------------------------------------------------------------------------- +class TransformHttpUnpack(Transform): + """Implement a transformation to unpack data from HTTP packets.""" + + # -------------------------------------------------------------------------- + # Constructor / Destructor + # -------------------------------------------------------------------------- + def __init__(self, opts): + # type: (Dict[str, str]) -> None + """Set specific options for this transformer. + + Args: + opts (DsTransformLinefeed): Transformer options. + + """ + super(TransformHttpUnpack, self).__init__() + self.__opts = opts + self.__log = logging.getLogger(__name__) + + # -------------------------------------------------------------------------- + # Public Functions + # -------------------------------------------------------------------------- + def transform(self, data): + # type: (bytes) -> bytes + """Unwrap data from a HTTP packet. + + Returns: + str: The wrapped string. + """ + request = StringEncoder.encode(r"^(GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH)") + response = StringEncoder.encode(r"^HTTP/[.0-9]+") + + # Did not receive a valid HTTP request, so we return the original untransformed message + if not (re.match(request, data) or re.match(response, data)): + return data + + body = StringEncoder.encode(r"(\r\n\r\n|\n\n)(.*)") + match = re.search(body, data) + + # Check if we can separate headers and body + if match is None or len(match.group()) < 2: + return data + return match.group(2) + + # ################################################################################################# # ################################################################################################# # ### @@ -7920,8 +8523,8 @@

      pwncat

      # -------------------------------------------------------------------------- @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: Read only property to provide a StopSignal instance to IO.""" + # type: () -> InterruptHandler + """`InterruptHandler`: InterruptHandler instance.""" return self.__ssig @property @@ -7935,11 +8538,11 @@

      pwncat

      # -------------------------------------------------------------------------- @abstractmethod def __init__(self, ssig): - # type: (StopSignal) -> None + # type: (InterruptHandler) -> None """Set specific options for this IO module. Args: - ssig (StopSignal): StopSignal instance used by the interrupter. + ssig (InterruptHandler): InterruptHandler instance used by the interrupter. """ super(IO, self).__init__() self.__ssig = ssig @@ -7951,7 +8554,7 @@

      pwncat

      @abstractmethod def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Implement a generator function which constantly yields data. The data could be from various sources such as: received from a socket, @@ -7963,7 +8566,7 @@

      pwncat

      @abstractmethod def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Define a consumer callback which will apply an action on the producer output. Args: @@ -7978,8 +8581,6 @@

      pwncat

      Various producer might call blocking functions and they won't be able to stop themself as they hang on that blocking function. NOTE: This method is triggered from outside and is supposed to stop/shutdown the producer. - - You should at least implement it with "self.ssig.raise_stop()" """ @@ -7994,7 +8595,7 @@

      pwncat

      # -------------------------------------------------------------------------- def __init__( self, - ssig, # type: StopSignal + ssig, # type: InterruptHandler encoder, # type: StringEncoder host, # type: str ports, # type: List[int] @@ -8007,7 +8608,7 @@

      pwncat

      """Create a Pwncat instance of either a server or a client. Args: - ssig (StopSignal): Stop signal instance + ssig (InterruptHandler): Instance of InterruptHandler. encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). host (str): The hostname to resolve. ports ([int]): List of ports to connect to or listen on. @@ -8025,6 +8626,9 @@

      pwncat

      self.__srv_opts = srv_opts self.__cli_opts = cli_opts + # Did we already run cleanup + self.__cleaned_up = False + # Internally store addresses for reconn or rebind functions self.__host = host self.__ports = ports @@ -8044,7 +8648,7 @@

      pwncat

      # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Network receive generator which hooks into the receive function and adds features. Yields: @@ -8060,9 +8664,9 @@

      pwncat

      try: yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action - except socket.timeout: + except socket.timeout as err: # Let's ask the interrupter() function if we should terminate? - if not self.ssig.has_stop(): + if not self.ssig.has_sock_quit(): continue # Stop signal is raied when my own side of the network was closed. # Happened most likely that the user pressed Ctrl+c @@ -8078,12 +8682,21 @@

      pwncat

      curr_recv_timeout_retry += 1 continue # We ware all done reading, shut down - self.ssig.raise_stop() + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [1]: %s", err + ) + self.__cleanup() return - # [3/3] Upstream is gone - except (EOFError, AttributeError, socket.error): + # [3/3] Upstream is gone (in one way or another) + except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.producer [2]: %s", err + ) + self.__cleanup() return # Do we re-accept new clients? if self.__sock_opts.udp: @@ -8093,28 +8706,42 @@

      pwncat

      continue if self.__role == "client" and self.__client_reconnect_to_server(): continue + # Inform everybody that we are quitting + self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() return def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Send data to a socket.""" - self.__net.send(data) + try: + self.__net.send(data) + except socket.error: + pass def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" self.log.trace( # type: ignore - "[IONetwork] socket.close was raised by calling interrupt() externally." - ) - self.__net.close_conn_sock() - self.__net.close_bind_sock() - # Raise stop signal - self.ssig.raise_stop() +Error (x2)"> self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore + self.ssig.raise_sock_quit() + self.__cleanup() # -------------------------------------------------------------------------- # Private Functions # -------------------------------------------------------------------------- + def __cleanup(self): + # type: () -> None + """Cleanup function.""" + if not self.__cleaned_up: + self.log.trace("SOCK-QUIT-CLEANUP: Closing sockets") # type: ignore + self.__net.close_conn_sock() + self.__net.close_bind_sock() + self.__cleaned_up = True + def __client_reconnect_to_server(self): # type: () -> bool """Ensure the client re-connects to the remote server, if the remote server hang up. @@ -8127,13 +8754,15 @@

      pwncat

      # reconn < 0 (endlessly) # reconn > 0 (reconnect until counter reaches zero) while self.__cli_opts.reconn != 0: - # [1/6] Let's ask the interrupter() function if we should terminate? # We need a little wait here in order for the stop signal to propagate. # Don't know how fast the other threads are. - # time.sleep(0.1) - # if self.ssig.has_stop(): - # return False + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" + ) + return False # [2/6] Wait time.sleep(self.__cli_opts.reconn_wait) @@ -8141,7 +8770,11 @@

      pwncat

      # [3/6] Let's ask the interrupter() function if we should terminate? # In case the other threads were slower as the sleep time in [1/5] # we will check again here. - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" + ) return False # [4/6] Increment the port numer (if --reconn-robin has multiple) @@ -8188,7 +8821,11 @@

      pwncat

      while self.__srv_opts.rebind != 0: # [1/7] Let's ask the interrupter() function if we should terminate? - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_rebind [1]" + ) return False # [2/7] Increment the port numer (if --reconn-robin has multiple) @@ -8223,7 +8860,11 @@

      pwncat

      # [6/7] Let's ask the interrupter() function if we should terminate? # In case the other threads were slower as the sleep time in [1/7] # we will check again here. - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_rebind [2]" + ) return False # [6/7] Recurse until True or reconnect count is used up @@ -8254,9 +8895,13 @@

      pwncat

      # [MAYBE] Check stop signal and otherwise try until success. while True: - time.sleep(0.1) + time.sleep(0.01) # [NO] We have a stop signal - if self.ssig.has_stop(): + if self.ssig.has_sock_quit(): + self.log.trace( # type: ignore + "SOCK-QUIT signal ACK in IONetwork.__server_reaccept_from_client" + ) return False # [YES] Re-accept indefinitely # -------------------------------------------------------------------------- def __init__( self, - ssig, # type: StopSignal + ssig, # type: InterruptHandler encoder, # type: StringEncoder host, # type: str banner, # type: bool @@ -8309,7 +8954,7 @@

      pwncat

      """Create a Pwncat Network Scanner instance. Args: - ssig (StopSignal): Stop signal instance + ssig (InterruptHandler): Instance of InterruptHandler. encoder (StringEncoder): Instance of StringEncoder (Python2/3 str/byte compat). host (str): The hostname to resolve. banner (bool): Determines if we do banner grabbing as well. @@ -8318,19 +8963,19 @@

      pwncat

      """ super(IONetworkScanner, self).__init__(ssig) + self.__ssig = ssig self.__enc = encoder self.__cli_opts = cli_opts self.__sock_opts = sock_opts self.__banner = banner self.__log = logging.getLogger(__name__) - self.__net = Net(encoder, ssig, sock_opts) self.__sock = Sock() self.__screen_lock = threading.Semaphore() # Keep track of local binds (addr-port) of the threaded scanner # clients as we do not want to treat them as open ports (false posistives) - self.__local_binds = [] # type: List[str] + self.__local_binds = {} # type: Dict[str, socket.socket] # Compile our regexes if using banner detection if banner: @@ -8348,13 +8993,13 @@

      pwncat

      int(socket.AF_INET), ] self.__targets = {} - try: - for family in families: + for family in families: + try: self.__targets[family] = self.__sock.gethostbyname( host, family, not self.__sock_opts.nodns ) - except socket.gaierror: - pass + except socket.gaierror: + pass # -------------------------------------------------------------------------- # Public Functions @@ -8362,18 +9007,25 @@

      pwncat

      def __get_socket(self, family): # type: (Union[socket.AddressFamily, int]) -> socket.socket """Create socket for specific address family endlessly until resources are available.""" - # The scanner is starting many threads, each creating a single socket - # and we might hit the max allowed open files limit, so we will - # endlessly ask the system for a new socket until success. - # Also adding a delay, which will give other threads the time to - # release their sockets. + # The scanner starts one thread for each port to scan. Each thread will also create + # one socket and we might hit the max_allowed_files limit (ulimit). + # That's why we loop through creating sockets until we hit a success + # as in the meantime, other threads might have already released sockets/fd's. while True: + delay = 0.0 + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner._getsocket" + ) + raise socket.error("quit") try: if self.__sock_opts.udp: return self.__sock.create_socket(family, socket.SOCK_DGRAM) return self.__sock.create_socket(family, socket.SOCK_STREAM) except socket.error: - time.sleep(0.1) + delay += 0.1 + time.sleep(delay) # This can be bigger to give the system some time to release fd's def __get_banner_version(self, banner): # type: (str) -> Optional[str] @@ -8390,7 +9042,7 @@

      pwncat

      for reg in self.BANNER_REG_COMP: match = re.search(reg, banner) if match: - return match.group(1).rstrip() + return StringEncoder.rstrip(match.group(1)) # type: ignore # Nothing found, return first non-empty line for line in lines: @@ -8409,20 +9061,26 @@

      pwncat

      payloads = self.BANNER_PAYLOADS[0] for payload in payloads: + # Break the loop on terminate signal + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner._getbanner: %s-%d", addr, port + ) + return (False, None) try: if payload is not None: sock.send(self.__enc.encode(payload)) self.__log.debug("%s:%d - payload sent: %s", addr, port, repr(payload)) - sock.settimeout(0.1) + sock.settimeout(0.5) banner = sock.recv(self.__sock_opts.bufsize) version = self.__get_banner_version(self.__enc.decode(banner)) self.__log.debug("%s:%d - respone received: %s", addr, port, repr(banner)) return (True, version) except socket.timeout: - time.sleep(0.1) continue except (OSError, socket.error): return (False, None) @@ -8430,7 +9088,7 @@

      pwncat

      def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Port scanner yielding open/closed string for given port. Args: @@ -8446,13 +9104,26 @@

      pwncat

      # Loop over adress families for family in self.__targets: + # [1/7] Check for termination request + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for IONetworkScanner.producer" + ) + return + addr = self.__targets[family] - # [1/5] Get socket - sock = self.__get_socket(family) + # [2/7] Get socket + try: + sock = self.__get_socket(family) + sock_type = sock.type + except (AttributeError, socket.error): + # Exception is triggered due to stop stignal and we + # will abort here in that case. + return - # [2/5] Connect scan - succ_conn = False + # [3/7] Connect scan try: laddr, lport = self.__sock.connect( sock, @@ -8467,52 +9138,53 @@

      pwncat

      0.1, ) # Append local binds (addr-port) to check against during port scan - self.__local_binds.append(str(laddr + "-" + str(lport))) - succ_conn = True + key = str(laddr + "-" + str(lport)) + self.__local_binds[key] = sock except socket.error: - succ_conn = False + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + continue + + # [4/7] False positives + # Connect was successful, but against a local bind of one of our + # port scanners, so this is a false positive. + if str(addr + "-" + str(port)) in self.__local_binds: + self.__sock.close(sock, "[-] closed: {}:{}".format(addr, port)) + del self.__local_binds[key] + continue - # [3/5] Banner grabbing + # [5/7] Banner grabbing succ_banner = True banner = None if self.__banner: (succ_banner, banner) = self.__get_banner(sock, addr, port) - # [4/5] Evaluation - if banner is not None and (succ_conn and succ_banner): + # [6/7] Evaluation + if banner is not None and succ_banner: + msg = "[+] {:>5}/{} open ({}): {}".format( if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({}): {}".format( - port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - banner, - ) - if banner is None and (succ_conn and succ_banner): - if str(addr + "-" + str(port)) not in self.__local_binds: - sock_type = sock.type - yield "[+] {:>5}/{} open ({})".format( +Explicit (x1)"> port, + self.__sock.get_type_name(sock_type), + self.__sock.get_family_name(family), + banner, + ) + yield self.__enc.encode(msg) + if banner is None and succ_banner: + msg = "[+] {:>5}/{} open ({})".format( port, - self.__sock.get_type_name(sock_type), - self.__sock.get_family_name(family), - ) +Explicit (x1)"> port, self.__sock.get_type_name(sock_type), self.__sock.get_family_name(family), + ) + yield self.__enc.encode(msg) - # [5/5] Cleanup - self.__sock.close(sock, addr + "-" + str(port)) - try: - self.__local_binds.remove(str(addr + "-" + str(port))) - except ValueError: - pass + # [7/7] Cleanup + self.__sock.close(sock, key) + del self.__local_binds[key] def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Print received data to stdout.""" # For issues with flush (when using tail -F or equal) see links below: # https://stackoverflow.com/questions/26692284 @@ -8531,8 +9203,21 @@

      pwncat

      self.__screen_lock.release() def interrupt(self): - # type: (str) -> None - """Not required.""" + # type: () -> None + """Stop function that can be called externally to close this instance.""" + self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore + self.ssig.raise_sock_quit() + + # NOTE: Closing up to 65535 sockets (single thread) takes very very long + # Se we leave this up to Python itself, once the program exits. + # self.log.trace("SOCK-QUIT-CLEANUP: Closing sockets") # type: ignore + # # Double loop to prevent: Dictionary size changed during iteration + # remove = {} + # for key in self.__local_binds: + # remove[key] = self.__local_binds[key] + # for key in remove: + # self.__sock.close(remove[key], key) # ------------------------------------------------------------------------------------------------- @@ -8550,69 +9235,115 @@

      pwncat

      # Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, ssig, opts): - # type: (StopSignal, DsIOStdinStdout) -> None + # type: (InterruptHandler, DsIOStdinStdout) -> None """Set specific options for this I/O module. Args: - ssig (StopSignal): StopSignal instance. + ssig (InterruptHandler): InterruptHandler instance. opts (DsIOStdinStdout): IO options. """ super(IOStdinStdout, self).__init__(ssig) self.__opts = opts self.__py3 = sys.version_info >= (3, 0) # type: bool +<<<<<<< HEAD self.__win = os.name != "posix" # posix or nt +======= + self.__abort = False +>>>>>>> Heavy refactoring # -------------------------------------------------------------------------- # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Constantly ask for user input. Yields: str: Data read from stdin. """ + # On --send-on-eof we will return all of its contents at once: + lines = [] + # https://stackoverflow.com/questions/1450393/#38670261 # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.ssig.has_stop(): + if self.__abort: self.log.trace("Stop signal acknowledged for reading STDIN-1") # type: ignore +Error (x2)"> self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore + return + if self.ssig.has_stdin_quit(): + self.log.trace( # type: ignore + "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]" + ) return try: +<<<<<<< HEAD data = self.__read_stdin() +======= + # TODO: select() does not work for windows on stdin/stdout + if os.name != "nt": + self.__set_input_timeout() + if self.__py3: + line = sys.stdin.buffer.readline() + else: + if sys.platform == "win32": + # Python 2 on Windows opens sys.stdin in text mode, and + # binary data that read from it becomes corrupted on \r\n. + # Setting sys.stdin to binary mode fixes that. + if hasattr(os, "O_BINARY"): + msvcrt.setmode( + sys.stdin.fileno(), os.O_BINARY, # pylint: disable=no-member + ) + line = sys.stdin.readline() # type: ignore + +>>>>>>> Heavy refactoring except EOFError: # When using select() with timeout, we don't have any input # at this point and simply continue the loop or quit if # a terminate request has been made by other threads. - if self.ssig.has_stop(): + if self.ssig.has_stdin_quit(): self.log.trace("Stop signal acknowledged for reading STDIN-2") # type: ignore +Error (x2)"> self.log.trace( # type: ignore + "STDIN-QUIT signal ACK in IOStdinStdout.producer [2]" + ) return continue if data: self.log.debug("Received %d bytes from STDIN", len(data)) self.log.trace("Received: %s", repr(data)) # type: ignore yield data +======= +Error (x2)"> self.log.trace("Received: %s", repr(line)) # type: ignore + # [send-on-eof] Append data + if self.__opts.send_on_eof: + lines.append(line) + else: + yield line +>>>>>>> Heavy refactoring # EOF or <Ctrl>+<d> else: - # DO NOT RETURN HERE BLINDLY, THE UPSTREAM CONNECTION MUST GO FIRST! - if self.ssig.has_stop(): - self.log.trace("Stop signal acknowledged for reading STDIN-3") # type: ignore - return + # [send-on-eof] Dump data before quitting + if lines and self.__opts.send_on_eof: + yield StringEncoder.encode("").join(lines) + self.ssig.raise_stdin_quit() def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Print received data to stdout.""" - # For issues with flush (when using tail -F or equal) see links below: - # https://stackoverflow.com/questions/26692284 - # https://docs.python.org/3/library/signal.html#note-on-sigpipe - print(data, end="") + if self.__py3: + sys.stdout.buffer.write(data) + else: + # For issues with flush (when using tail -F or equal) see links below: + # https://stackoverflow.com/questions/26692284 + # https://docs.python.org/3/library/signal.html#note-on-sigpipe + print(data, end="") + try: sys.stdout.flush() except (BrokenPipeError, IOError): @@ -8625,13 +9356,16 @@

      pwncat

      def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" + # TODO: Does not work on windows as it has blocking read of stdin + self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore + self.ssig.raise_stdin_quit() + self.log.trace( # type: ignore - "[IOStdinStdout] interrupt() invoked" + "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" ) - # Raise stop signal - # TODO: Check if this is required??? - self.ssig.raise_stop() + self.__abort = True # -------------------------------------------------------------------------- # Private Functions @@ -8717,11 +9451,11 @@

      pwncat

      # Constructor / Destructor # -------------------------------------------------------------------------- def __init__(self, ssig, opts): - # type: (StopSignal, DsIOCommand) -> None + # type: (InterruptHandler, DsIOCommand) -> None """Set specific options for this I/O module. Args: - ssig (StopSignal): Instance of StopSignal. + ssig (InterruptHandler): Instance of InterruptHandler. opts (DsIOCommand): Custom module options. """ super(IOCommand, self).__init__(ssig) @@ -8729,9 +9463,8 @@

      pwncat

      self.log.debug("Setting '%s' as executable", self.__opts.executable) - # Define destructor - atexit.register(self.__destruct__) + # Did we already run cleanup + self.__cleaned_up = False # Open executable to wait for commands env = os.environ.copy() @@ -8757,21 +9490,12 @@

      pwncat

      Explicit (x4)"> self.log.error("Specified executable '%s' not found", self.__opts.executable) sys.exit(1) - def __destruct__(self): - # type: () -> None - """Destructor.""" - self.log.trace( # type: ignore - "Killing executable: %s with pid %d", self.__opts.executable, self.proc.pid - ) - self.proc.kill() - # -------------------------------------------------------------------------- # Public Functions # -------------------------------------------------------------------------- def producer(self, *args, **kwargs): - # type: (Any, Any) -> Iterator[str] + # type: (Any, Any) -> Iterator[bytes] """Constantly ask for input. Yields: @@ -8779,49 +9503,66 @@

      pwncat

      """ assert self.proc.stdout is not None while True: - if self.ssig.has_stop(): + if self.ssig.has_command_quit(): self.log.trace("Stop signal acknowledged in Command") # type: ignore +Error (x2)"> self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.__cleanup() return self.log.trace("Reading command output") # type: ignore +<<<<<<< HEAD # Byte-wise reading is required to make it work for remote ends being in raw mode # However, the performance of self.proc.stdout.readline() is way faster. # To improve performance we will get rid of all other logging calls here. data = self.proc.stdout.read(1) +======= + # Much better performance than self.proc.read(1) + # TODO: check if self.proc.read(1) might be better in raw mode + data = self.proc.stdout.readline() +>>>>>>> Heavy refactoring self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: self.log.trace("Command output was empty. Exiting loop.") # type: ignore - break - yield self.__opts.enc.decode(data) +Error (x2)"> self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + return + yield data def consumer(self, data): - # type: (str) -> None + # type: (bytes) -> None """Send data received to stdin (command input). Args: data (str): Command to execute. """ assert self.proc.stdin is not None - byte = self.__opts.enc.encode(data) self.log.trace("Appending to stdin: %s", repr(byte)) # type: ignore - self.proc.stdin.write(byte) +Error (x2)"> self.log.trace("Appending to stdin: %s", repr(data)) # type: ignore + self.proc.stdin.write(data) self.proc.stdin.flush() def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" self.log.trace( # type: ignore - "[IOCommand] subprocess.kill() was raised by input_unterrupter()" - ) - self.proc.kill() - # Raise stop signal - # TODO: Check if this is required??? - self.ssig.raise_stop() +Error (x2)"> self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore + self.ssig.raise_command_quit() + self.__cleanup() + + def __cleanup(self): + # type: () -> None + """Cleanup function.""" + if not self.__cleaned_up: + self.log.trace( # type: ignore + "CMD-QUIT-CLEANUP: killing executable: %s with pid %d", + self.__opts.executable, + self.proc.pid, + ) + self.proc.kill() + self.__cleaned_up = True # ################################################################################################# @@ -8841,18 +9582,18 @@

      pwncat

      The same instance of this class will be available to your send and receive scripts that allow you to exchange data or manipulate themselves. You even have access to the currently used instance of the networking class to manipulate the active socket. - As well as to the logger and StopSignal instances. + As well as to the logger and InterruptHandler instances. """ @property def messages(self): - # type: () -> Dict[str, List[str]] - """`Dict[str, List[str]]`: Stores sent and received messages by its thread name.""" + # type: () -> Dict[str, List[bytes]] + """`Dict[str, List[bytes]]`: Stores sent and received messages by its thread name.""" return self.__messages @messages.setter def messages(self, value): - # type: (Dict[str, List[str]]) -> None + # type: (Dict[str, List[bytes]]) -> None self.__messages = value @property @@ -8872,8 +9613,8 @@

      pwncat

      @property def ssig(self): - # type: () -> StopSignal - """`StopSignal`: Instance of Logging.logger class.""" + # type: () -> InterruptHandler + """`InterruptHandler`: Instance of InterruptHandler class.""" return self.__ssig @property @@ -8889,11 +9630,11 @@

      pwncat

      return self.__log def __init__(self, ssig, net): - # type: (StopSignal, List[IONetwork]) -> None + # type: (InterruptHandler, List[IONetwork]) -> None """Instantiate the PSE class. Args: - ssig (StopSignal): Instance of the StopSignal class to force a shutdown. + ssig (InterruptHandler): Instance InterruptHandler. net (IONetwork): Instance of the current network class to manipulate the socket. """ self.__messages = {} @@ -8913,7 +9654,110 @@

      pwncat

      # ################################################################################################# # ------------------------------------------------------------------------------------------------- -# [8/11 IO RUNNER]: (1/1) Runner +# [8/11 IO RUNNER]: (1/2) InterruptHandler +# ------------------------------------------------------------------------------------------------- +class InterruptHandler(object): + """Pwncat interrupt handler. + + It allows all threads to raise various signal on certain actions, + as well as to ask the Interrupt Handler what to do. + The Interrupt handler will internally decide (based on pwncat's + command line arguments) what to do. + """ + + # -------------------------------------------------------------------------- + # Constructor + # -------------------------------------------------------------------------- + def __init__(self, keep_open, no_shutdown): + # type: (bool, bool) -> None + """Instantiate InterruptHandler. + + Args: + keep_open (bool): `--keep-open` command line argument. + no_shutdown (bool): `--no-shutdown` command line argument. + """ + self.__log = logging.getLogger(__name__) # type: logging.Logger + self.__keep_open = keep_open + self.__no_shutdown = no_shutdown + + self.__terminate = False + self.__sock_quit = False + self.__stdin_quit = False + self.__command_quit = False + + def handler(signum, frame): # type: ignore # pylint: disable=unused-argument + self.__log.trace("Ctrl+c caught.") # type: ignore + self.raise_terminate() + + # Handle Ctrl+C + signal.signal(signal.SIGINT, handler) + + # -------------------------------------------------------------------------- + # Ask for action + # -------------------------------------------------------------------------- + def has_terminate(self): + # type: () -> bool + """`bool`: Switch to be checked if pwncat should be terminated.""" + return self.__terminate + + def has_sock_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the socket connection should be closed.""" + return self.__sock_quit + + def has_stdin_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the STDIN should be closed.""" + return self.__stdin_quit + + def has_command_quit(self): + # type: () -> bool + """`bool`: Switch to be checked if the command should be closed.""" + return self.__command_quit + + # -------------------------------------------------------------------------- + # Raise signals + # -------------------------------------------------------------------------- + def raise_terminate(self): + # type: () -> None + """Signal the application that Socket should be quit.""" + self.__log.trace("SIGNAL TERMINATE raised") # type: ignore + self.__terminate = True + self.__sock_quit = True + self.__stdin_quit = True + self.__command_quit = True + + def raise_sock_quit(self): + # type: () -> None + """Signal the application that Socket should be quit.""" + self.__log.trace("SIGNAL SOCK-QUIT raised") # type: ignore + self.__sock_quit = True + self.raise_terminate() + + def raise_stdin_quit(self): + # type: () -> None + """Signal the application that STDIN should be quit.""" + if not (self.__no_shutdown or self.__keep_open): + self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore + self.__stdin_quit = True + self.raise_terminate() + + def raise_command_quit(self): + # type: () -> None + """Signal the application that Command should be quit.""" + self.__log.trace("SIGNAL CMD-QUIT raised") # type: ignore + self.__command_quit = True + self.raise_terminate() + + +# ------------------------------------------------------------------------------------------------- +# [8/11 IO RUNNER]: (2/2) Runner # ------------------------------------------------------------------------------------------------- class Runner(object): """Runner class that takes care about putting everything into threads.""" @@ -8921,11 +9765,12 @@

      pwncat

      # -------------------------------------------------------------------------- # Constructor / Destructor # -------------------------------------------------------------------------- - def __init__(self, pse): - # type: (PSEStore) -> None + def __init__(self, ssig, pse): + # type: (InterruptHandler, PSEStore) -> None """Create a new Runner object. Args: + ssig (InterruptHandler): Instance of InterruptHandler. pse (PSEStore): Pwncat Scripting Engine store. """ self.log = logging.getLogger(__name__) @@ -8947,6 +9792,7 @@

      pwncat

      # {"name": "<thread>"} self.__threads = {} # type: Dict[str, threading.Thread] + self.__ssig = ssig self.__pse = pse # -------------------------------------------------------------------------- @@ -8989,7 +9835,7 @@

      pwncat

      def run_action( name, # type: str producer, # type: DsCallableProducer - consumer, # type: Callable[[str], None] + consumer, # type: Callable[[bytes], None] transformers, # type: List[Transform] code, # type: Optional[Union[str, bytes, CodeType]] ): @@ -9049,14 +9895,14 @@

      pwncat

      def run_timer(name, action, intvl, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, InterruptHandler, Any, Any) -> None """Timer run function to be thrown into a thread (Execs periodic tasks). Args: name (str): Name for logging output action (function): Function to be called in a given intervall intvl (float): Intervall at which the action function will be called - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ @@ -9064,9 +9910,11 @@

      pwncat

      Error (x2)"> self.log.trace("[%s] Timer Start (exec every %f sec)", name, intvl) # type: ignore time_last = int(time.time()) while True: - if ssig.has_stop(): + if ssig.has_terminate(): self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore +Error (x2)"> self.log.trace( # type: ignore + "TERMINATE signal ACK for timer action [%s]", name + ) return time_now = int(time.time()) if time_now > time_last + intvl: @@ -9079,7 +9927,7 @@

      pwncat

      def run_repeater(name, action, repeat, pause, ssig, args, **kwargs): - # type: (str, Callable[..., None], int, float, StopSignal, Any, Any) -> None + # type: (str, Callable[..., None], int, float, InterruptHandler, Any, Any) -> None """Repeater run function to be thrown into a thread (Execs periodic tasks). Args: @@ -9087,7 +9935,7 @@

      pwncat

      action (function): Function to be called repeat (int): Repeat the function so many times before quitting pause (float): Pause between repeated calls - ssig (StopSignal): Providing has_stop() and raise_stop() + ssig (InterruptHandler): Instance of InterruptHandler args (*args): *args for action func kwargs (**kwargs): **kwargs for action func """ @@ -9095,9 +9943,11 @@

      pwncat

      self.log.trace("Repeater Start (%d/%d)", cycles, repeat) # type: ignore while cycles <= repeat: - if ssig.has_stop(): + if ssig.has_terminate(): self.log.trace("Stop signal acknowledged for timer %s", name) # type: ignore +Error (x2)"> self.log.trace( # type: ignore + "TERMINATE signal ACK for repeater action [%s]", name + ) return self.log.debug("Executing repeated function (%d/%d)", cycles, repeat) @@ -9106,8 +9956,14 @@

      pwncat

      cycles += 1 time.sleep(pause) - # Start available action in a thread + # [1/3] Start available action in a thread for key in self.__actions: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [1]: [%s]", key + ) + break # Create Thread object thread = threading.Thread( @@ -9121,16 +9977,28 @@

      pwncat

      self.__actions[key].code, ), ) - thread.daemon = False + # Daemon threads are easier to kill + thread.daemon = True + # Add delay if threads cannot be started + delay = 0.0 while True: + if self.__ssig.has_terminate(): + self.log.trace( # type: ignore + "TERMINATE signal ACK for Runner.run [2]: [%s]", key + ) + break try: + # Start and break the loop upon success to go to the next thread to start thread.start() break except (RuntimeError, Exception): # pylint: disable=broad-except - time.sleep(0.1) + delay += 0.1 + time.sleep(delay) # Give the system some time to release open fd's self.__threads[key] = thread - # Start available timers in a thread + + # [2/3] Start available timers in a thread for key in self.__timers: # Create Thread object self.__timers[key].action, self.__timers[key].intvl, - self.__timers[key].signal, + self.__timers[key].ssig, self.__timers[key].args, ), @@ -9152,7 +10020,8 @@

      pwncat

      ) thread.daemon = False thread.start() - # Start available repeaters in a thread + + # [3/3] Start available repeaters in a thread for key in self.__repeaters: # Create Thread object self.__repeaters[key].action, self.__repeaters[key].repeat, self.__repeaters[key].pause, - self.__repeaters[key].signal, + self.__repeaters[key].ssig, self.__repeaters[key].args, ), @@ -9176,22 +10045,14 @@

      pwncat

      thread.daemon = False thread.start() - def check_stop(force): - # type: (int) -> bool + def check_stop(): + # type: () -> bool """Stop threads.""" - for key in self.__threads: - if not self.__threads[key].is_alive() or force: - # TODO: How are we gonna call the stop signal now? - # # [1/3] Inform all threads (inside) about a stop signal. - # # All threads with non-blocking funcs will be able to stop themselves - # self.log.trace( # type: ignore - # "Raise stop signal: StopSignal.stop() for thread [%s]", - # self.__threads[key].getName(), - # ) - # self.__actions[key].signal.raise_stop() - # [2/3] Call external interrupters - # These will shutdown all blocking functions inside a thread, - # so that they are actually able to join + # TODO: This is a workaround for using daemon threads. + # Python < 3.3 is unable to detect Ctrl+c signal during + # thread.join() operation in a fast loop (Port scan). + if self.__ssig.has_terminate(): + for key in self.__threads: for interrupt in self.__actions[key].interrupts: self.log.trace( # type: ignore @@ -9202,25 +10063,53 @@

      pwncat

      self.__threads[key].getName(), ) interrupt() - # [3/3] All blocking events inside the threads are gone, now join them - self.log.trace("Joining %s", self.__threads[key].getName()) # type: ignore - self.__threads[key].join(timeout=0.1) - # If all threads have died or force is requested, then exit - if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + return True + # If all threads are done, also stop + if not all([self.__threads[key].is_alive() for key in self.__threads]): return True return False + # NOTE: This was for previous non-daemon threads + # for key in self.__threads: + # if not self.__threads[key].is_alive() or force: + # # TODO: How are we gonna call the stop signal now? + # # # [1/3] Inform all threads (inside) about a stop signal. + # # # All threads with non-blocking funcs will be able to stop themselves + # # self.log.trace( # type: ignore + # # "Raise stop signal: StopSignal.stop() for thread [%s]", + # # self.__threads[key].getName(), + # # ) + # # self.__actions[key].signal.signal_quit() + # # [2/3] Call external interrupters + # # These will shutdown all blocking functions inside a thread, + # # so that they are actually able to join + # for interrupt in self.__actions[key].interrupts: + # self.log.trace( # type: ignore + # "Call INTERRUPT: %s.%s() for %s", + # getattr(interrupt, "__self__").__class__.__name__, + # interrupt.__name__, + # self.__threads[key].getName(), + # ) + # interrupt() + # # [3/3] All blocking events inside the threads are gone, now join them + # try: + # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore + # # NOTE: The thread.join() operating will also block the signal handler + # #self.__threads[key].join(timeout=0.1) + # self.__threads[key].join() + # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore + # except RuntimeError as err: + # print(err) + # #pass + # # If all threads have died or force is requested, then exit + # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: + # return True + # return False - try: - while True: - if check_stop(False): - sys.exit(0) - # Need a timeout to not skyrocket the CPU - time.sleep(0.1) - except KeyboardInterrupt: - print() - check_stop(True) - sys.exit(1) + while True: + if check_stop(): + sys.exit(0) + # Need a timeout to not skyrocket the CPU + time.sleep(0.01) # ################################################################################################# @@ -9260,7 +10149,7 @@

      pwncat

      "/opt/python3.8/bin", ] - __PYTHON_VERSIONS = [ + __PYTHON_NAMES = [ "python", "python2", "python2.7", @@ -9291,8 +10180,9 @@

      pwncat

      # -------------------------------------------------------------------------- # Constructor # -------------------------------------------------------------------------- - def __init__(self, enc, fsend, frecv): - # type: (StringEncoder, Callable[[str], None], Callable[[], Iterator[str]]) -> None + def __init__(self, enc, fsend, frecv): + # type: (StringEncoder, Callable[[bytes], None], Callable[..., Iterator[bytes]]) -> None """Instantiate Command and Control class. Args: @@ -9305,7 +10195,8 @@

      pwncat

      """ self.__enc = enc self.__fsend = fsend - self.__frecv = frecv + self.__frecv = frecv if not self.__set_remote_python_path(): self.print_info("No Python has been found. Aborting and handing over to current shell.") @@ -9344,7 +10235,8 @@

      pwncat

      command (str): The command to execute on the remote end. """ # TODO: determine remote host line feeds and set accordingly. - self.__fsend(command + "\n") + # TODO: handle exception + self.__fsend(StringEncoder.encode(command + "\n")) def create_remote_tmpfile(self): # type: () -> Optional[str] @@ -9365,9 +10257,10 @@

      pwncat

      self.remote_command("".join(command)) self.print_info("Creating tmpfile:", False, True) - for response in self.__frecv(): + for response in self.__frecv(): if response: - tmpfile = response.rstrip() + tmpfile = StringEncoder.decode(response).rstrip() self.print_info("Creating tmpfile: {}".format(tmpfile), True, True) return tmpfile @@ -9409,13 +10302,18 @@

      pwncat

      """ # TODO: Make windows compatible for path in self.__PYTHON_PATHS: - for version in self.__PYTHON_VERSIONS: - python = path + "/" + version + for name in self.__PYTHON_NAMES: + + python = path + "/" + name self.print_info("Probing for: {}".format(python)) self.remote_command("test -f {p} && echo {p} || echo;".format(p=python)) - for response in self.__frecv(): - reg = re.search(r"^([.0-9]+)", response) - if response.rstrip() == python.rstrip(): + + for byte in self.__frecv(): + + response = StringEncoder.decode(byte) + match = re.search(r"^([.0-9]+)", response) + if StringEncoder.rstrip(response) == StringEncoder.rstrip(python): self.print_info("Potential path: {}".format(python)) command = [] command.append("{} -c '".format(python)) @@ -9426,18 +10324,18 @@

      pwncat

      data = "".join(command) self.remote_command(data) continue - if reg: - match = reg.group(1) - if match[0] == "2": + if match: + version = match.group(1) + if version[0] == "2": self.__py3 = False - elif match[0] == "3": + elif version[0] == "3": self.__py3 = True else: - self.print_info( - "Could not determine major version: {}".format(reg.group(1)) - ) + self.print_info("Could not determine major version: {}".format(version)) return False - self.print_info("Found valid Python{} version: {}".format(match[0], match)) + self.print_info( + "Found valid Python{} version: {}".format(version[0], version) + ) self.__python = python return True # Nothing matched, break the innter loop @@ -9465,7 +10363,7 @@

      pwncat

      self.print_info( "Uploading: {} -> {} ({}/{})".format(lpath, rpath, curr, count), False, True ) - b64 = self.__enc.base64_encode(line) + b64 = StringEncoder.decode(base64.b64encode(StringEncoder.encode(line))) if first: self.remote_command('echo "{}" > {}'.format(b64, rpath)) first = False @@ -9512,15 +10410,15 @@

      pwncat

      def __init__( self, enc, # type: StringEncoder - send, # type: Callable[[str], None] - recv, # type: Callable[[], Iterator[str]] + send, # type: Callable[[bytes], None] + recv, # type: Callable[[], Iterator[bytes]] cmd, # type: str host, # type: str ports, # type: List[int] ): # type: (...) -> None try: - super(CNCAutoDeploy, self).__init__(enc, send, recv) + super(CNCAutoDeploy, self).__init__(enc, send, recv) except FileNotFoundError: return @@ -10108,6 +11006,29 @@

      pwncat

      ) optional.add_argument( + "--send-on-eof", + action="store_true", + default=False, + help="""Buffer data received on stdin until EOF and send +everything in one chunk. + +""", + ) + optional.add_argument( + "--no-shutdown", + action="store_true", + default=False, + help="""Do not shutdown into half-duplex mode. +If this option is passed, pwncat won't invoke shutdown +on a socket after seeing EOF on stdin. This is provided +for backward-compatibility with OpenBSD netcat, which +exhibits this behavior. + +""", + ) + optional.add_argument( "-v", "--verbose", action="count", @@ -10622,7 +11543,7 @@

      pwncat

      # Deny unimplemented modes if args.http or args.https: +Explicit (x1)"> if args.https: print("Unimplemented options", file=sys.stderr) sys.exit(1) @@ -10751,8 +11672,9 @@

      pwncat

      # Initialize encoder enc = StringEncoder() - # Initialize StopSignal - ssig = StopSignal() + # Initialize interrupt handler + ssig = InterruptHandler(args.keep_open, args.no_shutdown) # Initialize transformers transformers = [] @@ -10784,7 +11706,8 @@

      pwncat

      Explicit (x1)"> mod = IOCommand(ssig, DsIOCommand(enc, args.cmd, POPEN_BUFSIZE)) # Use output module else: - mod = IOStdinStdout(ssig, DsIOStdinStdout(enc, TIMEOUT_READ_STDIN)) + mod = IOStdinStdout(ssig, DsIOStdinStdout(enc, TIMEOUT_READ_STDIN, args.send_on_eof)) # Run local port-forward # -> listen locally and forward traffic to remote (connect) @@ -10804,7 +11727,7 @@

      pwncat

      net_cli = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(PSEStore(ssig, [net_srv, net_cli])) + run = Runner(ssig, PSEStore(ssig, [net_srv, net_cli])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -10845,7 +11768,7 @@

      pwncat

      net_cli_r = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(PSEStore(ssig, [net_cli_l, net_cli_r])) + run = Runner(ssig, PSEStore(ssig, [net_cli_l, net_cli_r])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -10876,7 +11799,7 @@

      pwncat

      Explicit (x1)"> print("Scanning {} ports".format(len(ports))) net = IONetworkScanner(ssig, enc, host, args.banner, cli_opts, sock_opts) - run = Runner(PSEStore(ssig, [net])) + run = Runner(ssig, PSEStore(ssig, [net])) for port in ports: run.add_action( @@ -10886,8 +11809,8 @@

      pwncat

      DsCallableProducer(net.producer, port), # Send port scans net.consumer, # Output results + [net.interrupt], [], - transformers, None, ), ) @@ -10909,7 +11832,17 @@

      pwncat

      Explicit (x1)"> cnc_ports = ArgValidator.get_port_list_from_string(cnc_port) CNCAutoDeploy(enc, net.consumer, net.producer, cnc_cmd, cnc_host, cnc_ports) - run = Runner(PSEStore(ssig, [net])) + + if args.http: + trans_recv = [TransformHttpUnpack({})] + transformers + trans_send = [TransformHttpPack({"host": host, "reply": "response"})] + transformers + else: + trans_recv = transformers + trans_send = transformers + + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( @@ -10917,7 +11850,7 @@

      pwncat

      Explicit (x6)"> DsCallableProducer(net.producer), # receive data mod.consumer, [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err - transformers, + trans_recv, code_recv, ), @@ -10929,7 +11862,7 @@

      pwncat

      Explicit (x6)"> DsCallableProducer(mod.producer), net.consumer, # send data [mod.interrupt], # Externally stop the produer itself - transformers, + trans_send, code_send, ), @@ -10942,7 +11875,17 @@

      pwncat

      ssig, enc, host, ports + args.reconn_robin, "client", srv_opts, cli_opts, sock_opts ) - run = Runner(PSEStore(ssig, [net])) + + if args.http: + trans_recv = [TransformHttpUnpack({})] + transformers + trans_send = [TransformHttpPack({"host": host, "reply": "response"})] + transformers + else: + trans_recv = transformers + trans_send = transformers + + run = Runner(ssig, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( @@ -10950,7 +11893,7 @@

      pwncat

      Explicit (x6)"> DsCallableProducer(net.producer), # receive data mod.consumer, [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err - transformers, + trans_recv, code_recv, ), @@ -10962,7 +11905,7 @@

      pwncat

      Explicit (x6)"> DsCallableProducer(mod.producer), net.consumer, # send data [net.interrupt, mod.interrupt], # Externally stop the produer itself - transformers, + trans_send, code_send, ), @@ -10988,12 +11931,7 @@

      pwncat

      # [11/11 MAIN ENTRYPOINT]: (2/2) start # ------------------------------------------------------------------------------------------------- if __name__ == "pwncat": - # Catch Ctrl+c and exit without error message - try: - main() - except KeyboardInterrupt: - print() - sys.exit(1) + main()
      diff --git a/man/pwncat.1 b/man/pwncat.1 index f4651f93..45d93ee0 100644 --- a/man/pwncat.1 +++ b/man/pwncat.1 @@ -1,4 +1,8 @@ +<<<<<<< HEAD .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.15. +======= +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.11. +>>>>>>> Heavy refactoring .TH PWNCAT: "1" "June 2020" "https://github.com/cytopia/pwncat" "User Commands" .SH NAME pwncat: \- pwncat @@ -84,6 +88,17 @@ CR on MacOS). \fB\-n\fR, \fB\-\-nodns\fR Do not resolve DNS. .TP +\fB\-\-send\-on\-eof\fR +Buffer data received on stdin until EOF and send +everything in one chunk. +.TP +\fB\-\-no\-shutdown\fR +Do not shutdown into half\-duplex mode. +If this option is passed, pwncat won't invoke shutdown +on a socket after seeing EOF on stdin. This is provided +for backward\-compatibility with OpenBSD netcat, which +exhibits this behavior. +.TP \fB\-v\fR, \fB\-\-verbose\fR Be verbose and print info to stderr. Use \fB\-v\fR, \fB\-vv\fR, \fB\-vvv\fR or \fB\-vvvv\fR for more verbosity. The server performance will diff --git a/setup.cfg b/setup.cfg index a81081ef..77171068 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,11 +26,11 @@ max-line-length = 100 # bad-continuation: let Python Black take care of this # unidiomatic-typecheck: Need to check if int or bool and this doesnt work with isinstance() disable = useless-object-inheritance, bad-continuation, unidiomatic-typecheck -max-branches = 24 -max-statements = 107 +max-branches = 28 +max-statements = 119 max-args = 15 max-attributes = 13 -max-locals = 34 +max-locals = 36 max-module-lines = 6000 max-bool-expr = 6 max-returns = 11 diff --git a/tests/integration/01-behaviour-quit--client/000---tcp---client_quits---when_server_is_killed---client_default---before_send.sh b/tests/integration/01-behaviour-quit--client/000---tcp---client_quits---when_server_is_killed---client_default---before_send.sh index 9da4bf68..fdf66d81 100755 --- a/tests/integration/01-behaviour-quit--client/000---tcp---client_quits---when_server_is_killed---client_default---before_send.sh +++ b/tests/integration/01-behaviour-quit--client/000---tcp---client_quits---when_server_is_killed---client_default---before_send.sh @@ -137,24 +137,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/001---tcp---client_quits---when_server_is_killed---client_default---after_client_sent_data.sh b/tests/integration/01-behaviour-quit--client/001---tcp---client_quits---when_server_is_killed---client_default---after_client_sent_data.sh index 0576a3ed..831c7a0a 100755 --- a/tests/integration/01-behaviour-quit--client/001---tcp---client_quits---when_server_is_killed---client_default---after_client_sent_data.sh +++ b/tests/integration/01-behaviour-quit--client/001---tcp---client_quits---when_server_is_killed---client_default---after_client_sent_data.sh @@ -145,24 +145,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/002---tcp---client_quits---when_server_is_killed---client_default---after_server_sent_data.sh b/tests/integration/01-behaviour-quit--client/002---tcp---client_quits---when_server_is_killed---client_default---after_server_sent_data.sh index c9f79603..4efde1e4 100755 --- a/tests/integration/01-behaviour-quit--client/002---tcp---client_quits---when_server_is_killed---client_default---after_server_sent_data.sh +++ b/tests/integration/01-behaviour-quit--client/002---tcp---client_quits---when_server_is_killed---client_default---after_server_sent_data.sh @@ -145,24 +145,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/003---tcp---client_quits---when_server_is_killed---client_command---before_send.sh b/tests/integration/01-behaviour-quit--client/003---tcp---client_quits---when_server_is_killed---client_command---before_send.sh index 4b3613d9..0687baaf 100755 --- a/tests/integration/01-behaviour-quit--client/003---tcp---client_quits---when_server_is_killed---client_command---before_send.sh +++ b/tests/integration/01-behaviour-quit--client/003---tcp---client_quits---when_server_is_killed---client_command---before_send.sh @@ -136,24 +136,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/004---tcp---client_quits---when_server_is_killed---client_command---after_server_sent_command.sh b/tests/integration/01-behaviour-quit--client/004---tcp---client_quits---when_server_is_killed---client_command---after_server_sent_command.sh index 829dab0f..74f5c167 100755 --- a/tests/integration/01-behaviour-quit--client/004---tcp---client_quits---when_server_is_killed---client_command---after_server_sent_command.sh +++ b/tests/integration/01-behaviour-quit--client/004---tcp---client_quits---when_server_is_killed---client_command---after_server_sent_command.sh @@ -145,24 +145,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -e /bin/sh -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/100---udp---client_stays---when_server_is_killed---client_default---before_send.sh b/tests/integration/01-behaviour-quit--client/100---udp---client_stays---when_server_is_killed---client_default---before_send.sh index 036377a7..9035949a 100755 --- a/tests/integration/01-behaviour-quit--client/100---udp---client_stays---when_server_is_killed---client_default---before_send.sh +++ b/tests/integration/01-behaviour-quit--client/100---udp---client_stays---when_server_is_killed---client_default---before_send.sh @@ -149,24 +149,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/101---udp---client_stays---when_server_is_killed---client_default---after_client_sent_data.sh b/tests/integration/01-behaviour-quit--client/101---udp---client_stays---when_server_is_killed---client_default---after_client_sent_data.sh index 42dc3fa8..b92f1708 100755 --- a/tests/integration/01-behaviour-quit--client/101---udp---client_stays---when_server_is_killed---client_default---after_client_sent_data.sh +++ b/tests/integration/01-behaviour-quit--client/101---udp---client_stays---when_server_is_killed---client_default---after_client_sent_data.sh @@ -158,24 +158,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/102---udp---client_stays---when_server_is_killed---client_default---after_server_sent_data.sh b/tests/integration/01-behaviour-quit--client/102---udp---client_stays---when_server_is_killed---client_default---after_server_sent_data.sh index 4134a7a9..5bb46c52 100755 --- a/tests/integration/01-behaviour-quit--client/102---udp---client_stays---when_server_is_killed---client_default---after_server_sent_data.sh +++ b/tests/integration/01-behaviour-quit--client/102---udp---client_stays---when_server_is_killed---client_default---after_server_sent_data.sh @@ -159,24 +159,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/103---udp---client_stays---when_server_is_killed---client_command---before_send.sh b/tests/integration/01-behaviour-quit--client/103---udp---client_stays---when_server_is_killed---client_command---before_send.sh index 1373158d..b777bc2f 100755 --- a/tests/integration/01-behaviour-quit--client/103---udp---client_stays---when_server_is_killed---client_command---before_send.sh +++ b/tests/integration/01-behaviour-quit--client/103---udp---client_stays---when_server_is_killed---client_command---before_send.sh @@ -149,24 +149,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -e /bin/sh -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -e /bin/sh -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/200---tcp---client_stays---when_valid_http_request.sh b/tests/integration/01-behaviour-quit--client/200---tcp---client_stays---when_valid_http_request.sh index 8ed2cdba..db7a498f 100755 --- a/tests/integration/01-behaviour-quit--client/200---tcp---client_stays---when_valid_http_request.sh +++ b/tests/integration/01-behaviour-quit--client/200---tcp---client_stays---when_valid_http_request.sh @@ -102,9 +102,9 @@ run_test() { # ------------------------------------------------------------------------------------------------- for curr_round in $(seq "${RUNS}"); do - run_test "${RHOST} ${RPORT} -vvvv" "1" "5" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -vvv " "2" "5" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -vv " "3" "5" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -v " "4" "5" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} " "5" "5" "${curr_round}" "${RUNS}" + run_test "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "5" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -vvv " "2" "5" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -vv " "3" "5" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -v " "4" "5" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown " "5" "5" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/01-behaviour-quit--client/201---tcp---client_quites---when_invalid_http_request.sh b/tests/integration/01-behaviour-quit--client/201---tcp---client_quites---when_invalid_http_request.sh index 00eb5f43..71ade6b7 100755 --- a/tests/integration/01-behaviour-quit--client/201---tcp---client_quites---when_invalid_http_request.sh +++ b/tests/integration/01-behaviour-quit--client/201---tcp---client_quites---when_invalid_http_request.sh @@ -89,9 +89,9 @@ run_test() { # ------------------------------------------------------------------------------------------------- for curr_round in $(seq "${RUNS}"); do - run_test "${RHOST} ${RPORT} -vvvv" "1" "5" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -vvv " "2" "5" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -vv " "3" "5" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -v " "4" "5" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} " "5" "5" "${curr_round}" "${RUNS}" + run_test "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "5" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -vvv " "2" "5" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -vv " "3" "5" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -v " "4" "5" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown " "5" "5" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/000---tcp---server_quits---when_client_is_killed---server_default---before_send.sh b/tests/integration/02-behaviour-quit--server/000---tcp---server_quits---when_client_is_killed---server_default---before_send.sh index fa8e2385..50d60bae 100755 --- a/tests/integration/02-behaviour-quit--server/000---tcp---server_quits---when_client_is_killed---server_default---before_send.sh +++ b/tests/integration/02-behaviour-quit--server/000---tcp---server_quits---when_client_is_killed---server_default---before_send.sh @@ -136,24 +136,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/001---tcp---server_quits---when_client_is_killed---server_default---after_client_sent_data.sh b/tests/integration/02-behaviour-quit--server/001---tcp---server_quits---when_client_is_killed---server_default---after_client_sent_data.sh index 57b740bc..4a0750e6 100755 --- a/tests/integration/02-behaviour-quit--server/001---tcp---server_quits---when_client_is_killed---server_default---after_client_sent_data.sh +++ b/tests/integration/02-behaviour-quit--server/001---tcp---server_quits---when_client_is_killed---server_default---after_client_sent_data.sh @@ -145,24 +145,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/002---tcp---server_quits---when_client_is_killed---server_default---after_server_sent_data.sh b/tests/integration/02-behaviour-quit--server/002---tcp---server_quits---when_client_is_killed---server_default---after_server_sent_data.sh index c24c533d..44375d77 100755 --- a/tests/integration/02-behaviour-quit--server/002---tcp---server_quits---when_client_is_killed---server_default---after_server_sent_data.sh +++ b/tests/integration/02-behaviour-quit--server/002---tcp---server_quits---when_client_is_killed---server_default---after_server_sent_data.sh @@ -145,24 +145,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/003---tcp---server_quits---when_client_is_killed---server_command---before_send.sh b/tests/integration/02-behaviour-quit--server/003---tcp---server_quits---when_client_is_killed---server_command---before_send.sh index 7eeccc5e..53b7e66a 100755 --- a/tests/integration/02-behaviour-quit--server/003---tcp---server_quits---when_client_is_killed---server_command---before_send.sh +++ b/tests/integration/02-behaviour-quit--server/003---tcp---server_quits---when_client_is_killed---server_command---before_send.sh @@ -136,24 +136,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/004---tcp---server_quits---when_client_is_killed---server_command---after_client_sent_command.sh b/tests/integration/02-behaviour-quit--server/004---tcp---server_quits---when_client_is_killed---server_command---after_client_sent_command.sh index eb050b42..c6325870 100755 --- a/tests/integration/02-behaviour-quit--server/004---tcp---server_quits---when_client_is_killed---server_command---after_client_sent_command.sh +++ b/tests/integration/02-behaviour-quit--server/004---tcp---server_quits---when_client_is_killed---server_command---after_client_sent_command.sh @@ -145,24 +145,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/100---udp---server_stays---when_client_is_killed---server_default---before_send.sh b/tests/integration/02-behaviour-quit--server/100---udp---server_stays---when_client_is_killed---server_default---before_send.sh index 110b9ef7..147b5500 100755 --- a/tests/integration/02-behaviour-quit--server/100---udp---server_stays---when_client_is_killed---server_default---before_send.sh +++ b/tests/integration/02-behaviour-quit--server/100---udp---server_stays---when_client_is_killed---server_default---before_send.sh @@ -149,24 +149,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/101---udp---server_stays---when_client_is_killed---server_default---after_client_sent_data.sh b/tests/integration/02-behaviour-quit--server/101---udp---server_stays---when_client_is_killed---server_default---after_client_sent_data.sh index f903eb9e..9127cc57 100755 --- a/tests/integration/02-behaviour-quit--server/101---udp---server_stays---when_client_is_killed---server_default---after_client_sent_data.sh +++ b/tests/integration/02-behaviour-quit--server/101---udp---server_stays---when_client_is_killed---server_default---after_client_sent_data.sh @@ -158,24 +158,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/103---udp---server_stays---when_client_is_killed---server_command---before_send.sh b/tests/integration/02-behaviour-quit--server/103---udp---server_stays---when_client_is_killed---server_command---before_send.sh index 586c4416..d28e976e 100755 --- a/tests/integration/02-behaviour-quit--server/103---udp---server_stays---when_client_is_killed---server_command---before_send.sh +++ b/tests/integration/02-behaviour-quit--server/103---udp---server_stays---when_client_is_killed---server_command---before_send.sh @@ -149,24 +149,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/104---udp---server_stays---when_client_is_killed---server_command---after_client_sends_command.sh b/tests/integration/02-behaviour-quit--server/104---udp---server_stays---when_client_is_killed---server_command---after_client_sends_command.sh index 30965653..c648c4b4 100755 --- a/tests/integration/02-behaviour-quit--server/104---udp---server_stays---when_client_is_killed---server_command---after_client_sends_command.sh +++ b/tests/integration/02-behaviour-quit--server/104---udp---server_stays---when_client_is_killed---server_command---after_client_sends_command.sh @@ -158,24 +158,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/200---udp---server_reacc---when_client_is_killed---server_default---after_client_sent_data.sh b/tests/integration/02-behaviour-quit--server/200---udp---server_reacc---when_client_is_killed---server_default---after_client_sent_data.sh index 17ecc816..df0e7949 100755 --- a/tests/integration/02-behaviour-quit--server/200---udp---server_reacc---when_client_is_killed---server_default---after_client_sent_data.sh +++ b/tests/integration/02-behaviour-quit--server/200---udp---server_reacc---when_client_is_killed---server_default---after_client_sent_data.sh @@ -220,24 +220,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/02-behaviour-quit--server/201---udp---server_reacc---when_client_is_killed---server_command---after_client_sent_command.sh b/tests/integration/02-behaviour-quit--server/201---udp---server_reacc---when_client_is_killed---server_command---after_client_sent_command.sh index 72288a27..1673e79a 100755 --- a/tests/integration/02-behaviour-quit--server/201---udp---server_reacc---when_client_is_killed---server_command---after_client_sent_command.sh +++ b/tests/integration/02-behaviour-quit--server/201---udp---server_reacc---when_client_is_killed---server_command---after_client_sent_command.sh @@ -220,24 +220,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv --udp-sconnect --udp-sconnect-word" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv --udp-sconnect --udp-sconnect-word" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -u -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -u -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh -u -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -u -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/10-mode---local_forward/000---tcp---www-forward.sh b/tests/integration/10-mode---local_forward/000---tcp---www-forward.sh index f792d71e..c1fcb622 100755 --- a/tests/integration/10-mode---local_forward/000---tcp---www-forward.sh +++ b/tests/integration/10-mode---local_forward/000---tcp---www-forward.sh @@ -153,19 +153,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts - run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" "-vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvv " "-vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vv " "-vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -v " "-vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} " "-vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" "-vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" "-vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" "-v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" " " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvv " "-vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -vv " "-vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} -v " "-v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "--local ${RHOST}:${RPORT} ${THOST} ${TPORT} " " " "13" "13" "${curr_round}" "${RUNS}" + run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" "-vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvv " "-vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vv " "-vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -v " "-vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} " "-vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" "-vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" "-vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" "-v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" " " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvv " "-vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vv " "-vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -v " "-v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "--local ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} " " " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/11-mode---remote_forward/000---tcp---www-forward.sh b/tests/integration/11-mode---remote_forward/000---tcp---www-forward.sh index c2212ca6..dc29cb02 100755 --- a/tests/integration/11-mode---remote_forward/000---tcp---www-forward.sh +++ b/tests/integration/11-mode---remote_forward/000---tcp---www-forward.sh @@ -155,19 +155,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts - run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" "-vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvv " "-vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vv " "-vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -v " "-vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} " "-vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" "-vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" "-vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" "-v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvvv" " " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vvv " "-vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -vv " "-vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} -v " "-v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "--remote ${RHOST}:${RPORT} ${THOST} ${TPORT} " " " "13" "13" "${curr_round}" "${RUNS}" + run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" "-vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvv " "-vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vv " "-vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -v " "-vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} " "-vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" "-vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" "-vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" "-v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvvv" " " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vvv " "-vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -vv " "-vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} -v " "-v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "--remote ${RHOST}:${RPORT} --no-shutdown ${THOST} ${TPORT} " " " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/20-options---nodns/000---tcp---client_nodns.sh b/tests/integration/20-options---nodns/000---tcp---client_nodns.sh index 41f92f51..17d8a7e1 100755 --- a/tests/integration/20-options---nodns/000---tcp---client_nodns.sh +++ b/tests/integration/20-options---nodns/000---tcp---client_nodns.sh @@ -87,15 +87,15 @@ run_test() { # ------------------------------------------------------------------------------------------------- for curr_round in $(seq "${RUNS}"); do - run_test "${RHOST} ${RPORT} -n -vvvv " "1" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -n -vvv " "2" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -n -vv " "3" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -n -v " "4" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -n " "5" "10" "${curr_round}" "${RUNS}" - - #run_test "${RHOST} ${RPORT} --nodns -vvvv" "6" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} --nodns -vvv " "7" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} --nodns -vv " "8" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} --nodns -v " " 9" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} --nodns " "10" "10" "${curr_round}" "${RUNS}" + run_test "${RHOST} ${RPORT} --no-shutdown -n -vvvv " "1" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -n -vvv " "2" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -n -vv " "3" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -n -v " "4" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -n " "5" "10" "${curr_round}" "${RUNS}" + + #run_test "${RHOST} ${RPORT} --no-shutdown --nodns -vvvv" "6" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown --nodns -vvv " "7" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown --nodns -vv " "8" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown --nodns -v " " 9" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown --nodns " "10" "10" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/20-options---nodns/001---udp---client_nodns.sh b/tests/integration/20-options---nodns/001---udp---client_nodns.sh index f1388507..af32a682 100755 --- a/tests/integration/20-options---nodns/001---udp---client_nodns.sh +++ b/tests/integration/20-options---nodns/001---udp---client_nodns.sh @@ -87,15 +87,15 @@ run_test() { # ------------------------------------------------------------------------------------------------- for curr_round in $(seq "${RUNS}"); do - run_test "${RHOST} ${RPORT} -u -n -vvvv " "1" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -u -n -vvv " "2" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -u -n -vv " "3" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -u -n -v " "4" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -u -n " "5" "10" "${curr_round}" "${RUNS}" - - #run_test "${RHOST} ${RPORT} -u --nodns -vvvv" "6" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -u --nodns -vvv " "7" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -u --nodns -vv " "8" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -u --nodns -v " " 9" "10" "${curr_round}" "${RUNS}" - #run_test "${RHOST} ${RPORT} -u --nodns " "10" "10" "${curr_round}" "${RUNS}" + run_test "${RHOST} ${RPORT} --no-shutdown -u -n -vvvv " "1" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -u -n -vvv " "2" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -u -n -vv " "3" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -u -n -v " "4" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -u -n " "5" "10" "${curr_round}" "${RUNS}" + + #run_test "${RHOST} ${RPORT} --no-shutdown -u --nodns -vvvv" "6" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -u --nodns -vvv " "7" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -u --nodns -vv " "8" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -u --nodns -v " " 9" "10" "${curr_round}" "${RUNS}" + #run_test "${RHOST} ${RPORT} --no-shutdown -u --nodns " "10" "10" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/20-options---nodns/100---tcp---server_nodns.sh b/tests/integration/20-options---nodns/100---tcp---server_nodns.sh index 65ba1915..9909e3b4 100755 --- a/tests/integration/20-options---nodns/100---tcp---server_nodns.sh +++ b/tests/integration/20-options---nodns/100---tcp---server_nodns.sh @@ -87,15 +87,15 @@ run_test() { # ------------------------------------------------------------------------------------------------- for curr_round in $(seq "${RUNS}"); do - run_test "-l ${RHOST} ${RPORT} -n -vvvv " "1" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -n -vvv " "2" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -n -vv " "3" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -n -v " "4" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -n " "5" "10" "${curr_round}" "${RUNS}" - - #run_test "-l ${RHOST} ${RPORT} --nodns -vvvv" "6" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} --nodns -vvv " "7" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} --nodns -vv " "8" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} --nodns -v " " 9" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} --nodns " "10" "10" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -n -vvvv " "1" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -n -vvv " "2" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -n -vv " "3" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -n -v " "4" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -n " "5" "10" "${curr_round}" "${RUNS}" + + #run_test "-l ${RHOST} ${RPORT} --no-shutdown --nodns -vvvv" "6" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown --nodns -vvv " "7" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown --nodns -vv " "8" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown --nodns -v " " 9" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown --nodns " "10" "10" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/20-options---nodns/101---udp---server_nodns.sh b/tests/integration/20-options---nodns/101---udp---server_nodns.sh index 59d5ce58..3987674b 100755 --- a/tests/integration/20-options---nodns/101---udp---server_nodns.sh +++ b/tests/integration/20-options---nodns/101---udp---server_nodns.sh @@ -87,15 +87,15 @@ run_test() { # ------------------------------------------------------------------------------------------------- for curr_round in $(seq "${RUNS}"); do - run_test "-l ${RHOST} ${RPORT} -u -n -vvvv " "1" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -u -n -vvv " "2" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -u -n -vv " "3" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -u -n -v " "4" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -u -n " "5" "10" "${curr_round}" "${RUNS}" - - #run_test "-l ${RHOST} ${RPORT} -u --nodns -vvvv" "6" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -u --nodns -vvv " "7" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -u --nodns -vv " "8" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -u --nodns -v " " 9" "10" "${curr_round}" "${RUNS}" - #run_test "-l ${RHOST} ${RPORT} -u --nodns " "10" "10" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -n -vvvv " "1" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -n -vvv " "2" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -n -vv " "3" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -n -v " "4" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u -n " "5" "10" "${curr_round}" "${RUNS}" + + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u --nodns -vvvv" "6" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u --nodns -vvv " "7" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u --nodns -vv " "8" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u --nodns -v " " 9" "10" "${curr_round}" "${RUNS}" + #run_test "-l ${RHOST} ${RPORT} --no-shutdown -u --nodns " "10" "10" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/000---tcp---client_crlf_crlf---server_sends_lf.sh b/tests/integration/21-options---crlf/000---tcp---client_crlf_crlf---server_sends_lf.sh index 98432be3..4c98e47f 100755 --- a/tests/integration/21-options---crlf/000---tcp---client_crlf_crlf---server_sends_lf.sh +++ b/tests/integration/21-options---crlf/000---tcp---client_crlf_crlf---server_sends_lf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/001---tcp---client_crlf_crlf---server_sends_cr.sh b/tests/integration/21-options---crlf/001---tcp---client_crlf_crlf---server_sends_cr.sh index 87f1dd0c..a65d4176 100755 --- a/tests/integration/21-options---crlf/001---tcp---client_crlf_crlf---server_sends_cr.sh +++ b/tests/integration/21-options---crlf/001---tcp---client_crlf_crlf---server_sends_cr.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/002---tcp---client_crlf_crlf---server_sends_crlf.sh b/tests/integration/21-options---crlf/002---tcp---client_crlf_crlf---server_sends_crlf.sh index dc7825a5..b6924bda 100755 --- a/tests/integration/21-options---crlf/002---tcp---client_crlf_crlf---server_sends_crlf.sh +++ b/tests/integration/21-options---crlf/002---tcp---client_crlf_crlf---server_sends_crlf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/100---tcp---server_crlf_crlf---client_sends_lf.sh b/tests/integration/21-options---crlf/100---tcp---server_crlf_crlf---client_sends_lf.sh index 5eccb166..ca0ef3ec 100755 --- a/tests/integration/21-options---crlf/100---tcp---server_crlf_crlf---client_sends_lf.sh +++ b/tests/integration/21-options---crlf/100---tcp---server_crlf_crlf---client_sends_lf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/101---tcp---server_crlf_crlf---client_sends_cr.sh b/tests/integration/21-options---crlf/101---tcp---server_crlf_crlf---client_sends_cr.sh index a2e9dd32..a37b7f54 100755 --- a/tests/integration/21-options---crlf/101---tcp---server_crlf_crlf---client_sends_cr.sh +++ b/tests/integration/21-options---crlf/101---tcp---server_crlf_crlf---client_sends_cr.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/102---tcp---server_crlf_crlf---client_sends_crlf.sh b/tests/integration/21-options---crlf/102---tcp---server_crlf_crlf---client_sends_crlf.sh index 10f6de29..e734ca93 100755 --- a/tests/integration/21-options---crlf/102---tcp---server_crlf_crlf---client_sends_crlf.sh +++ b/tests/integration/21-options---crlf/102---tcp---server_crlf_crlf---client_sends_crlf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vvvv" "${RHOST} ${RPORT} --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf crlf -vvv " "${RHOST} ${RPORT} --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -vv " "${RHOST} ${RPORT} --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf -v " "${RHOST} ${RPORT} --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf crlf " "${RHOST} ${RPORT} --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf -v " "${RHOST} ${RPORT} --no-shutdown --crlf crlf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf crlf " "${RHOST} ${RPORT} --no-shutdown --crlf crlf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/200---tcp---client_crlf_lf---server_sends_lf.sh b/tests/integration/21-options---crlf/200---tcp---client_crlf_lf---server_sends_lf.sh index 670e541a..5b6eb6f8 100755 --- a/tests/integration/21-options---crlf/200---tcp---client_crlf_lf---server_sends_lf.sh +++ b/tests/integration/21-options---crlf/200---tcp---client_crlf_lf---server_sends_lf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/201---tcp---client_crlf_lf---server_sends_cr.sh b/tests/integration/21-options---crlf/201---tcp---client_crlf_lf---server_sends_cr.sh index c781f07b..873a1106 100755 --- a/tests/integration/21-options---crlf/201---tcp---client_crlf_lf---server_sends_cr.sh +++ b/tests/integration/21-options---crlf/201---tcp---client_crlf_lf---server_sends_cr.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/202---tcp---client_crlf_lf---server_sends_crlf.sh b/tests/integration/21-options---crlf/202---tcp---client_crlf_lf---server_sends_crlf.sh index 6d4d99d4..c8ac6eab 100755 --- a/tests/integration/21-options---crlf/202---tcp---client_crlf_lf---server_sends_crlf.sh +++ b/tests/integration/21-options---crlf/202---tcp---client_crlf_lf---server_sends_crlf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/300---tcp---server_crlf_lf---client_sends_lf.sh b/tests/integration/21-options---crlf/300---tcp---server_crlf_lf---client_sends_lf.sh index 1534fc31..0967ca18 100755 --- a/tests/integration/21-options---crlf/300---tcp---server_crlf_lf---client_sends_lf.sh +++ b/tests/integration/21-options---crlf/300---tcp---server_crlf_lf---client_sends_lf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/301---tcp---server_crlf_lf---client_sends_cr.sh b/tests/integration/21-options---crlf/301---tcp---server_crlf_lf---client_sends_cr.sh index 1b0fa107..034d32c1 100755 --- a/tests/integration/21-options---crlf/301---tcp---server_crlf_lf---client_sends_cr.sh +++ b/tests/integration/21-options---crlf/301---tcp---server_crlf_lf---client_sends_cr.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/302---tcp---server_crlf_lf---client_sends_crlf.sh b/tests/integration/21-options---crlf/302---tcp---server_crlf_lf---client_sends_crlf.sh index bc3243a2..f96f4ad8 100755 --- a/tests/integration/21-options---crlf/302---tcp---server_crlf_lf---client_sends_crlf.sh +++ b/tests/integration/21-options---crlf/302---tcp---server_crlf_lf---client_sends_crlf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vvvv" "${RHOST} ${RPORT} --crlf lf " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf lf -vvv " "${RHOST} ${RPORT} --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -vv " "${RHOST} ${RPORT} --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf -v " "${RHOST} ${RPORT} --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf lf " "${RHOST} ${RPORT} --crlf lf " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf lf " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -vv " "${RHOST} ${RPORT} --no-shutdown --crlf lf -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf -v " "${RHOST} ${RPORT} --no-shutdown --crlf lf -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf lf " "${RHOST} ${RPORT} --no-shutdown --crlf lf " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/400---tcp---client_crlf_cr---server_sends_lf.sh b/tests/integration/21-options---crlf/400---tcp---client_crlf_cr---server_sends_lf.sh index 8aad6b21..6752c110 100755 --- a/tests/integration/21-options---crlf/400---tcp---client_crlf_cr---server_sends_lf.sh +++ b/tests/integration/21-options---crlf/400---tcp---client_crlf_cr---server_sends_lf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/401---tcp---client_crlf_cr---server_sends_cr.sh b/tests/integration/21-options---crlf/401---tcp---client_crlf_cr---server_sends_cr.sh index f6be7e38..7a14badc 100755 --- a/tests/integration/21-options---crlf/401---tcp---client_crlf_cr---server_sends_cr.sh +++ b/tests/integration/21-options---crlf/401---tcp---client_crlf_cr---server_sends_cr.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/402---tcp---client_crlf_cr---server_sends_crlf.sh b/tests/integration/21-options---crlf/402---tcp---client_crlf_cr---server_sends_crlf.sh index ee336ebf..272b2276 100755 --- a/tests/integration/21-options---crlf/402---tcp---client_crlf_cr---server_sends_crlf.sh +++ b/tests/integration/21-options---crlf/402---tcp---client_crlf_cr---server_sends_crlf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/500---tcp---server_crlf_cr---client_sends_lf.sh b/tests/integration/21-options---crlf/500---tcp---server_crlf_cr---client_sends_lf.sh index ec28f872..0184aa4d 100755 --- a/tests/integration/21-options---crlf/500---tcp---server_crlf_cr---client_sends_lf.sh +++ b/tests/integration/21-options---crlf/500---tcp---server_crlf_cr---client_sends_lf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/501---tcp---server_crlf_cr---client_sends_cr.sh b/tests/integration/21-options---crlf/501---tcp---server_crlf_cr---client_sends_cr.sh index d2eaeb69..6dcfd5fe 100755 --- a/tests/integration/21-options---crlf/501---tcp---server_crlf_cr---client_sends_cr.sh +++ b/tests/integration/21-options---crlf/501---tcp---server_crlf_cr---client_sends_cr.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/502---tcp---server_crlf_cr---client_sends_crlf.sh b/tests/integration/21-options---crlf/502---tcp---server_crlf_cr---client_sends_crlf.sh index eac2cdf9..72f1d1aa 100755 --- a/tests/integration/21-options---crlf/502---tcp---server_crlf_cr---client_sends_crlf.sh +++ b/tests/integration/21-options---crlf/502---tcp---server_crlf_cr---client_sends_crlf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vvvv" "${RHOST} ${RPORT} --crlf cr " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf cr -vvv " "${RHOST} ${RPORT} --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -vv " "${RHOST} ${RPORT} --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr -v " "${RHOST} ${RPORT} --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf cr " "${RHOST} ${RPORT} --crlf cr " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf cr " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -vv " "${RHOST} ${RPORT} --no-shutdown --crlf cr -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr -v " "${RHOST} ${RPORT} --no-shutdown --crlf cr -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf cr " "${RHOST} ${RPORT} --no-shutdown --crlf cr " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/600---tcp---client_crlf_no---server_sends_lf.sh b/tests/integration/21-options---crlf/600---tcp---client_crlf_no---server_sends_lf.sh index 9069e94d..ee61b7a1 100755 --- a/tests/integration/21-options---crlf/600---tcp---client_crlf_no---server_sends_lf.sh +++ b/tests/integration/21-options---crlf/600---tcp---client_crlf_no---server_sends_lf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/601---tcp---client_crlf_no---server_sends_cr.sh b/tests/integration/21-options---crlf/601---tcp---client_crlf_no---server_sends_cr.sh index f67f74b6..b97f25f6 100755 --- a/tests/integration/21-options---crlf/601---tcp---client_crlf_no---server_sends_cr.sh +++ b/tests/integration/21-options---crlf/601---tcp---client_crlf_no---server_sends_cr.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/602---tcp---client_crlf_no---server_sends_crlf.sh b/tests/integration/21-options---crlf/602---tcp---client_crlf_no---server_sends_crlf.sh index bb63b87b..08c95a7d 100755 --- a/tests/integration/21-options---crlf/602---tcp---client_crlf_no---server_sends_crlf.sh +++ b/tests/integration/21-options---crlf/602---tcp---client_crlf_no---server_sends_crlf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/700---tcp---server_crlf_no---client_sends_lf.sh b/tests/integration/21-options---crlf/700---tcp---server_crlf_no---client_sends_lf.sh index 07c3733f..b8cfc9e9 100755 --- a/tests/integration/21-options---crlf/700---tcp---server_crlf_no---client_sends_lf.sh +++ b/tests/integration/21-options---crlf/700---tcp---server_crlf_no---client_sends_lf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/701---tcp---server_crlf_no---client_sends_cr.sh b/tests/integration/21-options---crlf/701---tcp---server_crlf_no---client_sends_cr.sh index 860af325..c9b5bd18 100755 --- a/tests/integration/21-options---crlf/701---tcp---server_crlf_no---client_sends_cr.sh +++ b/tests/integration/21-options---crlf/701---tcp---server_crlf_no---client_sends_cr.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/21-options---crlf/702---tcp---server_crlf_no---client_sends_crlf.sh b/tests/integration/21-options---crlf/702---tcp---server_crlf_no---client_sends_crlf.sh index f0cee2cc..533b47ce 100755 --- a/tests/integration/21-options---crlf/702---tcp---server_crlf_no---client_sends_crlf.sh +++ b/tests/integration/21-options---crlf/702---tcp---server_crlf_no---client_sends_crlf.sh @@ -136,19 +136,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vvvv" "${RHOST} ${RPORT} --crlf no " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} --crlf no -vvv " "${RHOST} ${RPORT} --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -vv " "${RHOST} ${RPORT} --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no -v " "${RHOST} ${RPORT} --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} --crlf no " "${RHOST} ${RPORT} --crlf no " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvvv" "${RHOST} ${RPORT} --no-shutdown --crlf no " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown --crlf no -vvv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -vv " "${RHOST} ${RPORT} --no-shutdown --crlf no -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no -v " "${RHOST} ${RPORT} --no-shutdown --crlf no -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown --crlf no " "${RHOST} ${RPORT} --no-shutdown --crlf no " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/22-options---keep_open/000---tcp---server_reacc---three_clients---server_default---cli_nosend-cli_nosend-cli_send.sh b/tests/integration/22-options---keep_open/000---tcp---server_reacc---three_clients---server_default---cli_nosend-cli_nosend-cli_send.sh index 3b947481..56f1c8ca 100755 --- a/tests/integration/22-options---keep_open/000---tcp---server_reacc---three_clients---server_default---cli_nosend-cli_nosend-cli_send.sh +++ b/tests/integration/22-options---keep_open/000---tcp---server_reacc---three_clients---server_default---cli_nosend-cli_nosend-cli_send.sh @@ -299,24 +299,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/22-options---keep_open/001---tcp---server_reacc---three_clients---server_default---cli_nosend-cli_send-cli_send.sh b/tests/integration/22-options---keep_open/001---tcp---server_reacc---three_clients---server_default---cli_nosend-cli_send-cli_send.sh index ce50e805..ae7f493b 100755 --- a/tests/integration/22-options---keep_open/001---tcp---server_reacc---three_clients---server_default---cli_nosend-cli_send-cli_send.sh +++ b/tests/integration/22-options---keep_open/001---tcp---server_reacc---three_clients---server_default---cli_nosend-cli_send-cli_send.sh @@ -308,24 +308,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/22-options---keep_open/002---tcp---server_reacc---three_clients---server_default---cli_send-cli_send-cli_send.sh b/tests/integration/22-options---keep_open/002---tcp---server_reacc---three_clients---server_default---cli_send-cli_send-cli_send.sh index 38608f46..1c9e5ac2 100755 --- a/tests/integration/22-options---keep_open/002---tcp---server_reacc---three_clients---server_default---cli_send-cli_send-cli_send.sh +++ b/tests/integration/22-options---keep_open/002---tcp---server_reacc---three_clients---server_default---cli_send-cli_send-cli_send.sh @@ -317,24 +317,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/22-options---keep_open/100---tcp---server_reacc---three_clients---server_default---srv_send-cli_nosend-cli_send.sh b/tests/integration/22-options---keep_open/100---tcp---server_reacc---three_clients---server_default---srv_send-cli_nosend-cli_send.sh index 541420b0..6220ad2b 100755 --- a/tests/integration/22-options---keep_open/100---tcp---server_reacc---three_clients---server_default---srv_send-cli_nosend-cli_send.sh +++ b/tests/integration/22-options---keep_open/100---tcp---server_reacc---three_clients---server_default---srv_send-cli_nosend-cli_send.sh @@ -308,24 +308,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/22-options---keep_open/101---tcp---server_reacc---three_clients---server_default---srv_send-cli_send-cli_send.sh b/tests/integration/22-options---keep_open/101---tcp---server_reacc---three_clients---server_default---srv_send-cli_send-cli_send.sh index bc5cb41c..7e46ae14 100755 --- a/tests/integration/22-options---keep_open/101---tcp---server_reacc---three_clients---server_default---srv_send-cli_send-cli_send.sh +++ b/tests/integration/22-options---keep_open/101---tcp---server_reacc---three_clients---server_default---srv_send-cli_send-cli_send.sh @@ -317,24 +317,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/22-options---keep_open/200---tcp---server_reacc---three_clients---server_command---cli_nosend-cli_nosend-cli_send.sh b/tests/integration/22-options---keep_open/200---tcp---server_reacc---three_clients---server_command---cli_nosend-cli_nosend-cli_send.sh index acc715ab..df827314 100755 --- a/tests/integration/22-options---keep_open/200---tcp---server_reacc---three_clients---server_command---cli_nosend-cli_nosend-cli_send.sh +++ b/tests/integration/22-options---keep_open/200---tcp---server_reacc---three_clients---server_command---cli_nosend-cli_nosend-cli_send.sh @@ -299,24 +299,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/22-options---keep_open/201---tcp---server_reacc---three_clients---server_command---cli_nosend-cli_send-cli_send.sh b/tests/integration/22-options---keep_open/201---tcp---server_reacc---three_clients---server_command---cli_nosend-cli_send-cli_send.sh index 3219e32c..d9318400 100755 --- a/tests/integration/22-options---keep_open/201---tcp---server_reacc---three_clients---server_command---cli_nosend-cli_send-cli_send.sh +++ b/tests/integration/22-options---keep_open/201---tcp---server_reacc---three_clients---server_command---cli_nosend-cli_send-cli_send.sh @@ -308,24 +308,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/22-options---keep_open/202---tcp---server_reacc---three_clients---server_command---cli_send-cli_send-cli_send.sh b/tests/integration/22-options---keep_open/202---tcp---server_reacc---three_clients---server_command---cli_send-cli_send-cli_send.sh index fb149495..25a0e281 100755 --- a/tests/integration/22-options---keep_open/202---tcp---server_reacc---three_clients---server_command---cli_send-cli_send-cli_send.sh +++ b/tests/integration/22-options---keep_open/202---tcp---server_reacc---three_clients---server_command---cli_send-cli_send-cli_send.sh @@ -317,24 +317,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -e /bin/sh --keep-open -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/23-options---reconn/000---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_nosend-srv_nosend-srv_send.sh b/tests/integration/23-options---reconn/000---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_nosend-srv_nosend-srv_send.sh index da143ed8..da0350d5 100755 --- a/tests/integration/23-options---reconn/000---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_nosend-srv_nosend-srv_send.sh +++ b/tests/integration/23-options---reconn/000---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_nosend-srv_nosend-srv_send.sh @@ -276,24 +276,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/23-options---reconn/001---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_nosend-srv_send-srv_send.sh b/tests/integration/23-options---reconn/001---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_nosend-srv_send-srv_send.sh index 07e081ef..6042eef1 100755 --- a/tests/integration/23-options---reconn/001---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_nosend-srv_send-srv_send.sh +++ b/tests/integration/23-options---reconn/001---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_nosend-srv_send-srv_send.sh @@ -285,24 +285,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/23-options---reconn/002---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_send-srv_send-srv_send.sh b/tests/integration/23-options---reconn/002---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_send-srv_send-srv_send.sh index a45b56b2..e791a699 100755 --- a/tests/integration/23-options---reconn/002---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_send-srv_send-srv_send.sh +++ b/tests/integration/23-options---reconn/002---tcp---client_reconn---three_servers---server_default---srv_down_cli_send-srv_send-srv_send-srv_send.sh @@ -294,24 +294,24 @@ run_test() { for curr_round in $(seq "${RUNS}"); do # server opts client opts # BIND ON ANY - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "1" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "2" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "3" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "1" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "2" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "3" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "4" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "5" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "4" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "5" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "6" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "7" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "6" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "7" "14" "${curr_round}" "${RUNS}" # BIND ON SPECIFIC - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "8" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "9" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "10" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "8" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "9" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "10" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "11" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -4 -vvvv" "${RHOST} ${RPORT} -4 --reconn -vvvv" "12" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "11" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -4 -vvvv" "${RHOST} ${RPORT} --no-shutdown -4 --reconn -vvvv" "12" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} --reconn -vvvv" "13" "14" "${curr_round}" "${RUNS}" - run_test "-l ${RHOST} ${RPORT} -6 -vvvv" "${RHOST} ${RPORT} -6 --reconn -vvvv" "14" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown --reconn -vvvv" "13" "14" "${curr_round}" "${RUNS}" + run_test "-l ${RHOST} ${RPORT} --no-shutdown -6 -vvvv" "${RHOST} ${RPORT} --no-shutdown -6 --reconn -vvvv" "14" "14" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/25-options---ping_intvl/000---udp---reverse-shell.sh b/tests/integration/25-options---ping_intvl/000---udp---reverse-shell.sh index 2c8a5804..9a2becf4 100755 --- a/tests/integration/25-options---ping_intvl/000---udp---reverse-shell.sh +++ b/tests/integration/25-options---ping_intvl/000---udp---reverse-shell.sh @@ -139,19 +139,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-intvl 1 -u -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vvv " "${RHOST} ${RPORT} --ping-intvl 1 -u -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vv " "${RHOST} ${RPORT} --ping-intvl 1 -u -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -v " "${RHOST} ${RPORT} --ping-intvl 1 -u -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u " "${RHOST} ${RPORT} --ping-intvl 1 -u -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-intvl 1 -u -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-intvl 1 -u -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-intvl 1 -u -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-intvl 1 -u " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} -u -vvv " "${RHOST} ${RPORT} --ping-intvl 1 -u -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vv " "${RHOST} ${RPORT} --ping-intvl 1 -u -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -v " "${RHOST} ${RPORT} --ping-intvl 1 -u -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u " "${RHOST} ${RPORT} --ping-intvl 1 -u " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vvv " "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vv " "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -v " "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u " "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown -u -vvv " "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vv " "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -v " "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u " "${RHOST} ${RPORT} --no-shutdown --ping-intvl 1 -u " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/integration/26-options---ping_word/000---udp---reverse-shell.sh b/tests/integration/26-options---ping_word/000---udp---reverse-shell.sh index 453df849..2e27a2c4 100755 --- a/tests/integration/26-options---ping_word/000---udp---reverse-shell.sh +++ b/tests/integration/26-options---ping_word/000---udp---reverse-shell.sh @@ -148,19 +148,19 @@ run_test() { for curr_round in $(seq "${RUNS}"); do echo # server opts client opts - run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vvvv" "1" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vvv " "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vvvv" "2" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vv " "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vvvv" "3" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -v " "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vvvv" "4" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u " "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vvvv" "5" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vvv " "6" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vv " "7" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -v " "8" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vvvv" "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u " "9" "13" "${curr_round}" "${RUNS}" - - #run_test "-l ${RPORT} -u -vvv " "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vvv " "10" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -vv " "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -vv " "11" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u -v " "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u -v " "12" "13" "${curr_round}" "${RUNS}" - #run_test "-l ${RPORT} -u " "${RHOST} ${RPORT} --ping-word test --ping-intvl 1 -u " "13" "13" "${curr_round}" "${RUNS}" + run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vvvv" "1" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vvv " "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vvvv" "2" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vv " "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vvvv" "3" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -v " "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vvvv" "4" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u " "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vvvv" "5" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vvv " "6" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vv " "7" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -v " "8" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vvvv" "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u " "9" "13" "${curr_round}" "${RUNS}" + + #run_test "-l ${RPORT} --no-shutdown -u -vvv " "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vvv " "10" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -vv " "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -vv " "11" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u -v " "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u -v " "12" "13" "${curr_round}" "${RUNS}" + #run_test "-l ${RPORT} --no-shutdown -u " "${RHOST} ${RPORT} --no-shutdown --ping-word test --ping-intvl 1 -u " "13" "13" "${curr_round}" "${RUNS}" done diff --git a/tests/smoke/200---tcp---keep_open/docker-compose.yml b/tests/smoke/200---tcp---keep_open/docker-compose.yml index 56f633ad..0778ae8a 100644 --- a/tests/smoke/200---tcp---keep_open/docker-compose.yml +++ b/tests/smoke/200---tcp---keep_open/docker-compose.yml @@ -9,7 +9,7 @@ services: server_1: image: python:${PYTHON_VERSION}-alpine hostname: server - command: python${PYTHON_VERSION} /usr/bin/pwncat -vvvvv -l 4444 --keep-open + command: python${PYTHON_VERSION} /usr/bin/pwncat --no-shutdown -vvvvv -l 4444 --keep-open restart: "no" ports: - "4444:4444/tcp" @@ -19,7 +19,7 @@ services: client_1: image: python:${PYTHON_VERSION}-alpine hostname: client - command: python${PYTHON_VERSION} /usr/bin/pwncat -vvvvv server_1 4444 + command: python${PYTHON_VERSION} /usr/bin/pwncat --no-shutdown -vvvvv server_1 4444 restart: "no" volumes: - ../../../bin/pwncat:/usr/bin/pwncat @@ -33,7 +33,7 @@ services: server_2: image: python:${PYTHON_VERSION}-alpine hostname: server - command: python${PYTHON_VERSION} /usr/bin/pwncat -vvvvv -l 4444 --keep-open + command: python${PYTHON_VERSION} /usr/bin/pwncat --no-shutdown -vvvvv -l 4444 --keep-open restart: "no" ports: - "4444:4444/tcp" diff --git a/tests/smoke/200---tcp---keep_open/start_client_send.sh b/tests/smoke/200---tcp---keep_open/start_client_send.sh index 0096d1e4..9612994f 100755 --- a/tests/smoke/200---tcp---keep_open/start_client_send.sh +++ b/tests/smoke/200---tcp---keep_open/start_client_send.sh @@ -6,4 +6,4 @@ set -x RHOST="${1}" RPORT="${2}" -printf "hi\\n" | "python${PYTHON_VERSION}" /usr/bin/pwncat -vvvvv "${RHOST}" "${RPORT}" +printf "hi\\n" | "python${PYTHON_VERSION}" /usr/bin/pwncat --no-shutdown -vvvvv "${RHOST}" "${RPORT}" From e2b90fb13d2427820a0990a7c03218288cf0c4e1 Mon Sep 17 00:00:00 2001 From: cytopia Date: Mon, 1 Jun 2020 20:22:58 +0200 Subject: [PATCH 09/61] Fix exception handline --- Makefile | 20 ++++++++++---------- bin/pwncat | 10 +++++----- docs/pwncat.api.html | 30 +++++++++++++++--------------- docs/pwncat.type.html | 10 +++++----- tests/smoke/run.sh | 4 ++-- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index 62788ed5..a0250dd1 100644 --- a/Makefile +++ b/Makefile @@ -193,19 +193,19 @@ smoke: _smoke-keep_open-after_client_send .PHONY: _smoke-keep_open-before_send: @# It's sometimes a race-condition, so we run it five times - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "2.7" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "3.5" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "3.6" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "3.7" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "3.8" _smoke-keep_open-after_client_send: @# It's sometimes a race-condition, so we run it five times - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "2.7" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "3.5" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "3.6" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "3.7" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "3.8" # ------------------------------------------------------------------------------------------------- diff --git a/bin/pwncat b/bin/pwncat index 259394e0..cf17fe00 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -1857,7 +1857,7 @@ class Net(object): self.__active["remote_port"], size - send, ) - except (BrokenPipeError, OSError, socket.error) as error: + except (IOError, OSError, socket.error) as error: msg = "Socket send Error: {}".format(error) raise socket.error(msg) return send @@ -3260,9 +3260,9 @@ class IONetworkScanner(IO): print(data) try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) finally: @@ -3378,9 +3378,9 @@ class IOStdinStdout(IO): try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) diff --git a/docs/pwncat.api.html b/docs/pwncat.api.html index 44fda8d0..5b4c3116 100644 --- a/docs/pwncat.api.html +++ b/docs/pwncat.api.html @@ -1891,7 +1891,7 @@

      Module pwncat

      self.__active["remote_port"], size - send, ) - except (BrokenPipeError, OSError, socket.error) as error: + except (IOError, OSError, socket.error) as error: msg = "Socket send Error: {}".format(error) raise socket.error(msg) return send @@ -3294,9 +3294,9 @@

      Module pwncat

      print(data) try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) finally: @@ -3441,9 +3441,9 @@

      Module pwncat

      try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) @@ -10723,9 +10723,9 @@

      Args

      print(data) try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) finally: @@ -10778,9 +10778,9 @@

      Methods

      print(data) try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) finally: @@ -11063,9 +11063,9 @@

      Args

      try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) @@ -11172,9 +11172,9 @@

      Methods

      try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno())
      @@ -11719,7 +11719,7 @@

      Args

      self.__active["remote_port"], size - send, ) - except (BrokenPipeError, OSError, socket.error) as error: + except (IOError, OSError, socket.error) as error: msg = "Socket send Error: {}".format(error) raise socket.error(msg) return send @@ -12758,7 +12758,7 @@

      Raises

      self.__active["remote_port"], size - send, ) - except (BrokenPipeError, OSError, socket.error) as error: + except (IOError, OSError, socket.error) as error: msg = "Socket send Error: {}".format(error) raise socket.error(msg) return send
      diff --git a/docs/pwncat.type.html b/docs/pwncat.type.html index 3396a6b8..514aee31 100644 --- a/docs/pwncat.type.html +++ b/docs/pwncat.type.html @@ -7721,7 +7721,7 @@

      pwncat

      self.__active["remote_port"], size - send, ) - except (BrokenPipeError, OSError, socket.error) as error: + except (IOError, OSError, socket.error) as error: msg = "Socket send Error: {}".format(error) raise socket.error(msg) return send @@ -9193,9 +9193,9 @@

      pwncat

      print(data) try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) @@ -9346,9 +9346,9 @@

      pwncat

      try: sys.stdout.flush() - except (BrokenPipeError, IOError): + except IOError: # Python flushes standard streams on exit; redirect remaining output - # to devnull to avoid another BrokenPipeError at shutdown + # to devnull to avoid another broken pipe at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) diff --git a/tests/smoke/run.sh b/tests/smoke/run.sh index 01254fd6..12f06c13 100755 --- a/tests/smoke/run.sh +++ b/tests/smoke/run.sh @@ -14,8 +14,8 @@ source "${SOURCEPATH}" # ------------------------------------------------------------------------------------------------- # SETTINGS # ------------------------------------------------------------------------------------------------- -WAIT_STARTUP=2 -WAIT_SHUTDOWN=2 +WAIT_STARTUP=6 +WAIT_SHUTDOWN=6 # ------------------------------------------------------------------------------------------------- From 35bd9dea656d3007753916cb7da7332ed119fb7d Mon Sep 17 00:00:00 2001 From: cytopia Date: Mon, 1 Jun 2020 20:34:19 +0200 Subject: [PATCH 10/61] Fix smoke tests --- .github/workflows/smoke-2.7.yml | 10 ++++++++++ .github/workflows/smoke-3.5.yml | 10 ++++++++++ .github/workflows/smoke-3.6.yml | 10 ++++++++++ .github/workflows/smoke-3.7.yml | 10 ++++++++++ .github/workflows/smoke-3.8.yml | 10 ++++++++++ Makefile | 20 +++++++++---------- tests/pipelines/template-smoke.yml.tpl | 10 ++++++++++ .../200---tcp---keep_open/docker-compose.yml | 12 +++++------ tests/smoke/run.sh | 17 +++++++++++++--- 9 files changed, 90 insertions(+), 19 deletions(-) diff --git a/.github/workflows/smoke-2.7.yml b/.github/workflows/smoke-2.7.yml index eb99b8c7..c43b63e6 100644 --- a/.github/workflows/smoke-2.7.yml +++ b/.github/workflows/smoke-2.7.yml @@ -23,6 +23,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Docker versions + shell: bash + run: | + docker version + + - name: Docker Compose versions + shell: bash + run: | + docker-compose version + # ------------------------------------------------------------ # Tests: Behaviour # ------------------------------------------------------------ diff --git a/.github/workflows/smoke-3.5.yml b/.github/workflows/smoke-3.5.yml index 0967e3b5..a73b05dd 100644 --- a/.github/workflows/smoke-3.5.yml +++ b/.github/workflows/smoke-3.5.yml @@ -23,6 +23,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Docker versions + shell: bash + run: | + docker version + + - name: Docker Compose versions + shell: bash + run: | + docker-compose version + # ------------------------------------------------------------ # Tests: Behaviour # ------------------------------------------------------------ diff --git a/.github/workflows/smoke-3.6.yml b/.github/workflows/smoke-3.6.yml index cdfd1bef..550b7316 100644 --- a/.github/workflows/smoke-3.6.yml +++ b/.github/workflows/smoke-3.6.yml @@ -23,6 +23,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Docker versions + shell: bash + run: | + docker version + + - name: Docker Compose versions + shell: bash + run: | + docker-compose version + # ------------------------------------------------------------ # Tests: Behaviour # ------------------------------------------------------------ diff --git a/.github/workflows/smoke-3.7.yml b/.github/workflows/smoke-3.7.yml index 4721ea84..d6b09448 100644 --- a/.github/workflows/smoke-3.7.yml +++ b/.github/workflows/smoke-3.7.yml @@ -23,6 +23,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Docker versions + shell: bash + run: | + docker version + + - name: Docker Compose versions + shell: bash + run: | + docker-compose version + # ------------------------------------------------------------ # Tests: Behaviour # ------------------------------------------------------------ diff --git a/.github/workflows/smoke-3.8.yml b/.github/workflows/smoke-3.8.yml index 0490470e..02ef80f2 100644 --- a/.github/workflows/smoke-3.8.yml +++ b/.github/workflows/smoke-3.8.yml @@ -23,6 +23,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Docker versions + shell: bash + run: | + docker version + + - name: Docker Compose versions + shell: bash + run: | + docker-compose version + # ------------------------------------------------------------ # Tests: Behaviour # ------------------------------------------------------------ diff --git a/Makefile b/Makefile index a0250dd1..62788ed5 100644 --- a/Makefile +++ b/Makefile @@ -193,19 +193,19 @@ smoke: _smoke-keep_open-after_client_send .PHONY: _smoke-keep_open-before_send: @# It's sometimes a race-condition, so we run it five times - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "2.7" - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "3.5" - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "3.6" - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "3.7" - tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "3.8" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_1" "client_1" "$(PYTHON_VERSION)" _smoke-keep_open-after_client_send: @# It's sometimes a race-condition, so we run it five times - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "2.7" - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "3.5" - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "3.6" - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "3.7" - tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "3.8" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" + tests/smoke/run.sh "200---tcp---keep_open" "server_2" "client_2" "$(PYTHON_VERSION)" # ------------------------------------------------------------------------------------------------- diff --git a/tests/pipelines/template-smoke.yml.tpl b/tests/pipelines/template-smoke.yml.tpl index a2aad23d..4b5dbad4 100644 --- a/tests/pipelines/template-smoke.yml.tpl +++ b/tests/pipelines/template-smoke.yml.tpl @@ -23,6 +23,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Docker versions + shell: bash + run: | + docker version + + - name: Docker Compose versions + shell: bash + run: | + docker-compose version + # ------------------------------------------------------------ # Tests: Behaviour # ------------------------------------------------------------ diff --git a/tests/smoke/200---tcp---keep_open/docker-compose.yml b/tests/smoke/200---tcp---keep_open/docker-compose.yml index 0778ae8a..938fe942 100644 --- a/tests/smoke/200---tcp---keep_open/docker-compose.yml +++ b/tests/smoke/200---tcp---keep_open/docker-compose.yml @@ -11,9 +11,9 @@ services: hostname: server command: python${PYTHON_VERSION} /usr/bin/pwncat --no-shutdown -vvvvv -l 4444 --keep-open restart: "no" - ports: - - "4444:4444/tcp" - - "4444:4444/udp" + # ports: + # - "4444:4444/tcp" + # - "4444:4444/udp" volumes: - ../../../bin/pwncat:/usr/bin/pwncat client_1: @@ -35,9 +35,9 @@ services: hostname: server command: python${PYTHON_VERSION} /usr/bin/pwncat --no-shutdown -vvvvv -l 4444 --keep-open restart: "no" - ports: - - "4444:4444/tcp" - - "4444:4444/udp" + # ports: + # - "4444:4444/tcp" + # - "4444:4444/udp" volumes: - ../../../bin/pwncat:/usr/bin/pwncat client_2: diff --git a/tests/smoke/run.sh b/tests/smoke/run.sh index 12f06c13..ad211067 100755 --- a/tests/smoke/run.sh +++ b/tests/smoke/run.sh @@ -107,23 +107,23 @@ run "sleep ${WAIT_STARTUP}" print_h2 "(3/5) Validate running" if ! run "docker-compose ps --filter 'status=running' --services | grep ${SERVER}"; then - print_error "Server is not running" run "docker-compose logs" run "docker-compose ps" run "docker-compose exec $( tty -s && echo || echo '-T' ) ${CLIENT} ps || true" run "docker-compose exec $( tty -s && echo || echo '-T' ) ${SERVER} ps || true" run "docker-compose kill || true 2>/dev/null" run "docker-compose rm -f || true 2>/dev/null" + print_error "Server is not running" exit 1 fi if ! run "docker-compose ps --filter 'status=running' --services | grep ${CLIENT}"; then - print_error "Client is not running" run "docker-compose logs" run "docker-compose ps" run "docker-compose exec $( tty -s && echo || echo '-T' ) ${CLIENT} ps || true" run "docker-compose exec $( tty -s && echo || echo '-T' ) ${SERVER} ps || true" run "docker-compose kill || true 2>/dev/null" run "docker-compose rm -f || true 2>/dev/null" + print_error "Client is not running" exit 1 fi @@ -136,7 +136,17 @@ run "docker-compose exec $( tty -s && echo || echo '-T' ) ${SERVER} ps || true" # ------------------------------------------------------------------------------------------------- print_h2 "(4/5) Test" -run "docker-compose exec $( tty -s && echo || echo '-T' ) ${SERVER} kill -2 1" +if ! run "docker-compose exec $( tty -s && echo || echo '-T' ) ${SERVER} kill -2 1"; then + run "docker-compose logs" + run "docker-compose ps" + run "docker-compose exec $( tty -s && echo || echo '-T' ) ${CLIENT} ps || true" + run "docker-compose exec $( tty -s && echo || echo '-T' ) ${SERVER} ps || true" + run "docker-compose kill || true 2>/dev/null" + run "docker-compose rm -f || true 2>/dev/null" + print_error "Kill command not successful" + exit 1 +fi + run "sleep ${WAIT_SHUTDOWN}" run "docker-compose exec $( tty -s && echo || echo '-T' ) ${CLIENT} ps || true" run "docker-compose exec $( tty -s && echo || echo '-T' ) ${SERVER} ps || true" @@ -176,3 +186,4 @@ run "docker-compose logs ${CLIENT}" run "docker-compose ps" run "docker-compose kill || true 2>/dev/null" run "docker-compose rm -f || true 2>/dev/null" +run "sleep ${WAIT_SHUTDOWN}" From 67667ce48dbf8dfb5cc67a8b5c16226389af4b7a Mon Sep 17 00:00:00 2001 From: cytopia Date: Fri, 5 Jun 2020 10:03:40 +0200 Subject: [PATCH 11/61] Fix signal handling --- README.md | 2 +- bin/pwncat | 183 +++++++--- docs/pwncat.api.html | 753 +++++++++++++++++++++++++++++------------- docs/pwncat.type.html | 317 +++++++++++++++--- man/pwncat.1 | 4 - 5 files changed, 951 insertions(+), 308 deletions(-) diff --git a/README.md b/README.md index 2ac86e05..cc132645 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ -> [1] mypy type coverage (fully typed: 93.56%)
      +> [1] mypy type coverage (fully typed: 93.55%)
      > [2] Linux builds are currently only failing, due to loss of IPv6 support: Issue
      > [3] Windows builds are currently only failing, because they are simply stuck on GitHub actions: Issue diff --git a/bin/pwncat b/bin/pwncat index cf17fe00..9a5349f6 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -1685,13 +1685,51 @@ class Sock(_Singleton("SingletonMeta", (object,), {})): # type: ignore # -------------------------------------------------------------------------- # Destroy functions # -------------------------------------------------------------------------- + def shutdown_recv(self, sock, name): + # type: (socket.socket, str) -> None + """Shuts down a socket for receiving data (only allow to send data). + + Args: + name (str): Name of the socket used for logging purposes. + sock (str): Socket to shutdown for receive. + """ + try: + # (SHUT_RD) 0 = Done receiving (disallows receiving) + # (SHUT_WR) 1 = Done sending (disallows sending) + # (SHUT_RDWR) 2 = Both + self.__log.trace("Shutting down %s socket for receiving", name) # type: ignore + sock.shutdown(socket.SHUT_RD) + except (OSError, socket.error): + # We do not log errors here, as unconnected sockets cannot + # be shutdown and we want to throw any socket at this function. + pass + + def shutdown_send(self, sock, name): + # type: (socket.socket, str) -> None + """Shuts down a socket for sending data (only allow to receive data). + + Args: + name (str): Name of the socket used for logging purposes. + sock (str): Socket to shutdown for send. + """ + try: + # (SHUT_RD) 0 = Done receiving (disallows receiving) + # (SHUT_WR) 1 = Done sending (disallows sending) + # (SHUT_RDWR) 2 = Both + self.__log.trace("Shutting down %s socket for sending", name) # type: ignore + sock.shutdown(socket.SHUT_WR) + except (OSError, socket.error): + # We do not log errors here, as unconnected sockets cannot + # be shutdown and we want to throw any socket at this function. + pass + def close(self, sock, name): # type: (socket.socket, str) -> None """Shuts down and closes a socket. Args: + sock (socket.socket): Socket to shutdown and close. name (str): Name of the socket used for logging purposes. - sock (str): Socket to shutdown and close. """ try: # (SHUT_RD) 0 = Done receiving (disallows receiving) @@ -1791,6 +1829,11 @@ class Net(object): # -------------------------------------------------------------------------- # Public Send / Receive Functions # -------------------------------------------------------------------------- + def send_eof(self): + # type: () -> None + """Close the active socket for sending. The remote part will get an EOF.""" + self.__sock.shutdown_send(self.__active["conn"], "conn") + def send(self, data): # type: (bytes) -> int """Send data through a connected (TCP) or unconnected (UDP) socket. @@ -2440,7 +2483,7 @@ class TransformSafeword(Transform): str: The string as it is without changes """ if StringEncoder.encode(self.__opts.safeword) in data: - self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore + self.log.trace("TERMINATE signal RAISED in TransformSafeword.transform") # type: ignore self.__opts.ssig.raise_terminate() return data @@ -2765,6 +2808,13 @@ class IONetwork(IO): yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action except socket.timeout as err: + # Check if we close the socket for sending + if self.ssig.has_sock_send_eof(): + self.log.trace( # type: ignore + "SOCK-SEND-EOF signal ACK in IONetwork.producer [1]: %s", err + ) + self.__net.send_eof() + # Let's ask the interrupter() function if we should terminate? if not self.ssig.has_sock_quit(): continue @@ -2786,7 +2836,7 @@ class IONetwork(IO): ) self.__cleanup() return - # [3/3] Upstream is gone (in one way or another) + # [3/3] Connection was closed remotely (EOF) or locally (Ctrl+C or similar) except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? if self.ssig.has_sock_quit(): @@ -2804,10 +2854,8 @@ class IONetwork(IO): if self.__role == "client" and self.__client_reconnect_to_server(): continue # Inform everybody that we are quitting - self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore - self.ssig.raise_sock_quit() - self.__cleanup() - return + self.log.trace("SOCK-EOF signal RAISE in IONetwork.producer") # type: ignore + self.ssig.raise_sock_eof() def consumer(self, data): # type: (bytes) -> None @@ -2820,7 +2868,7 @@ class IONetwork(IO): def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore + self.log.trace("SOCK-QUIT signal RAISE in IONetwork.interrupt") # type: ignore self.ssig.raise_sock_quit() self.__cleanup() @@ -2853,7 +2901,7 @@ class IONetwork(IO): # Don't know how fast the other threads are. if self.ssig.has_sock_quit(): self.log.trace( # type: ignore - "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" + "SOCK-QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" ) return False @@ -2865,7 +2913,7 @@ class IONetwork(IO): # we will check again here. if self.ssig.has_sock_quit(): self.log.trace( # type: ignore - "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" + "SOCK-QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" ) return False @@ -3271,7 +3319,7 @@ class IONetworkScanner(IO): def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore + self.log.trace("SOCK-QUIT signal RAISED in IONetworkScanner.interrupt") # type: ignore self.ssig.raise_sock_quit() # NOTE: Closing up to 65535 sockets (single thread) takes very very long @@ -3311,7 +3359,6 @@ class IOStdinStdout(IO): self.__opts = opts self.__py3 = sys.version_info >= (3, 0) # type: bool self.__win = os.name != "posix" # posix or nt - self.__abort = False # -------------------------------------------------------------------------- # Public Functions @@ -3330,9 +3377,6 @@ class IOStdinStdout(IO): # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.__abort: - self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore - return if self.ssig.has_stdin_quit(): self.log.trace( # type: ignore "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]" @@ -3363,7 +3407,8 @@ class IOStdinStdout(IO): # [send-on-eof] Dump data before quitting if lines and self.__opts.send_on_eof: yield StringEncoder.encode("").join(lines) - self.ssig.raise_stdin_quit() + self.log.trace("STDIN-EOF signal RAISE in IOStdinStdout.producer") # type: ignore + self.ssig.raise_stdin_eof() def consumer(self, data): # type: (bytes) -> None @@ -3388,14 +3433,9 @@ class IOStdinStdout(IO): # type: () -> None """Stop function that can be called externally to close this instance.""" # TODO: Does not work on windows as it has blocking read of stdin - self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore + self.log.trace("STDIN-QUIT signal RAISE in IOStdinStdout.interrupt") # type: ignore self.ssig.raise_stdin_quit() - self.log.trace( # type: ignore - "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" - ) - self.__abort = True - # -------------------------------------------------------------------------- # Private Functions # -------------------------------------------------------------------------- @@ -3524,7 +3564,7 @@ class IOCommand(IO): assert self.proc.stdout is not None while True: if self.ssig.has_command_quit(): - self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.log.trace("COMMAND-QUIT signal ACK IOCommand.producer") # type: ignore self.__cleanup() return self.log.trace("Reading command output") # type: ignore @@ -3534,10 +3574,9 @@ class IOCommand(IO): data = self.proc.stdout.read(1) self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: - self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore - self.ssig.raise_command_quit() - self.__cleanup() - return + self.log.trace("COMMAND-EOF signal RAISED IOCommand.producer") # type: ignore + self.ssig.raise_command_eof() + continue yield data def consumer(self, data): @@ -3555,7 +3594,7 @@ class IOCommand(IO): def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore + self.log.trace("COMMAND-QUIT signal RAISED IOCommand.interrupt") # type: ignore self.ssig.raise_command_quit() self.__cleanup() @@ -3564,7 +3603,7 @@ class IOCommand(IO): """Cleanup function.""" if not self.__cleaned_up: self.log.trace( # type: ignore - "CMD-QUIT-CLEANUP: killing executable: %s with pid %d", + "COMMAND-QUIT-CLEANUP: killing executable: %s with pid %d", self.__opts.executable, self.proc.pid, ) @@ -3682,11 +3721,18 @@ class InterruptHandler(object): self.__keep_open = keep_open self.__no_shutdown = no_shutdown + # Shutdown signals self.__terminate = False + self.__sock_send_eof = False self.__sock_quit = False self.__stdin_quit = False self.__command_quit = False + # Producers have received EOF + self.__sock_eof = False + self.__stdin_eof = False + self.__command_eof = False + def handler(signum, frame): # type: ignore # pylint: disable=unused-argument self.__log.trace("Ctrl+c caught.") # type: ignore self.raise_terminate() @@ -3702,6 +3748,11 @@ class InterruptHandler(object): """`bool`: Switch to be checked if pwncat should be terminated.""" return self.__terminate + def has_sock_send_eof(self): + # type: () -> bool + """`bool`: Switch to be checked if the socket connection should be closed for sending.""" + return self.__sock_send_eof + def has_sock_quit(self): # type: () -> bool """`bool`: Switch to be checked if the socket connection should be closed.""" @@ -3718,7 +3769,7 @@ class InterruptHandler(object): return self.__command_quit # -------------------------------------------------------------------------- - # Raise signals + # Raise Termination signal # -------------------------------------------------------------------------- def raise_terminate(self): # type: () -> None @@ -3729,6 +3780,22 @@ class InterruptHandler(object): self.__stdin_quit = True self.__command_quit = True + # -------------------------------------------------------------------------- + # Raise Socket signals + # -------------------------------------------------------------------------- + def raise_sock_send_eof(self): + # type: () -> None + """Signal the application that Socket should be closed for sending.""" + self.__log.trace("SIGNAL SOCK-CLOSE-SEND raised") # type: ignore + self.__sock_send_eof = True + + def raise_sock_eof(self): + # type: () -> None + """Signal the application that Socket has received EOF.""" + self.__log.trace("SIGNAL SOCK-EOF raised") # type: ignore + self.__sock_eof = True + self.raise_sock_quit() + def raise_sock_quit(self): # type: () -> None """Signal the application that Socket should be quit.""" @@ -3736,18 +3803,42 @@ class InterruptHandler(object): self.__sock_quit = True self.raise_terminate() + # -------------------------------------------------------------------------- + # Raise STDIN signals + # -------------------------------------------------------------------------- + def raise_stdin_eof(self): + # type: () -> None + """Signal the application that STDIN has received EOF.""" + self.__log.trace("SIGNAL STDIN-EOF raised") # type: ignore + self.__stdin_eof = True + self.raise_stdin_quit() + def raise_stdin_quit(self): # type: () -> None """Signal the application that STDIN should be quit.""" + self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore + self.__stdin_quit = True + # If --no-shutdown or -keep-open is specified + # pwncat will not invoke shutdown on a socket after seeing EOF on stdin if not (self.__no_shutdown or self.__keep_open): - self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore - self.__stdin_quit = True - self.raise_terminate() + # No more data from stdin, we can tell the remote side we are done + # by closing the socket for sending (they will receive an EOF). + self.raise_sock_send_eof() + + # -------------------------------------------------------------------------- + # Raise COMMAND signals + # -------------------------------------------------------------------------- + def raise_command_eof(self): + # type: () -> None + """Signal the application that Command has received EOF.""" + self.__log.trace("SIGNAL COMMAND-EOF raised") # type: ignore + self.__command_eof = True + self.raise_command_quit() def raise_command_quit(self): # type: () -> None """Signal the application that Command should be quit.""" - self.__log.trace("SIGNAL CMD-QUIT raised") # type: ignore + self.__log.trace("SIGNAL COMMAND-QUIT raised") # type: ignore self.__command_quit = True self.raise_terminate() @@ -3953,7 +4044,8 @@ class Runner(object): ), ) # Daemon threads are easier to kill - thread.daemon = True + # FIXME: Only use daemon threads for Port scanner + thread.daemon = False # Add delay if threads cannot be started delay = 0.0 @@ -4012,12 +4104,16 @@ class Runner(object): def check_stop(): # type: () -> bool """Stop threads.""" + # FIXME: Use two methods here + # if non-daemin threads - do join + # if scanner do not use join! # TODO: This is a workaround for using daemon threads. # Python < 3.3 is unable to detect Ctrl+c signal during # thread.join() operation in a fast loop (Port scan). - if self.__ssig.has_terminate(): - for key in self.__threads: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", getattr(interrupt, "__self__").__class__.__name__, @@ -4025,7 +4121,18 @@ class Runner(object): self.__threads[key].getName(), ) interrupt() - return True + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal handler + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): return True diff --git a/docs/pwncat.api.html b/docs/pwncat.api.html index 5b4c3116..fc32882e 100644 --- a/docs/pwncat.api.html +++ b/docs/pwncat.api.html @@ -107,15 +107,12 @@

      Module pwncat

      import ipaddress except ImportError: pass -<<<<<<< HEAD # Posix terminal try: import tty import termios except ImportError: pass -======= ->>>>>>> Heavy refactoring # Windows try: import msvcrt @@ -158,11 +155,7 @@

      Module pwncat

      APPNAME = "pwncat" APPREPO = "https://github.com/cytopia/pwncat" -<<<<<<< HEAD -VERSION = "0.0.23-alpha" -======= VERSION = "0.1.0" ->>>>>>> Heavy refactoring # Default timeout for timeout-based sys.stdin and socket.recv TIMEOUT_READ_STDIN = 0.05 @@ -1719,13 +1712,51 @@

      Module pwncat

      # -------------------------------------------------------------------------- # Destroy functions # -------------------------------------------------------------------------- + def shutdown_recv(self, sock, name): + # type: (socket.socket, str) -> None + """Shuts down a socket for receiving data (only allow to send data). + + Args: + name (str): Name of the socket used for logging purposes. + sock (str): Socket to shutdown for receive. + """ + try: + # (SHUT_RD) 0 = Done receiving (disallows receiving) + # (SHUT_WR) 1 = Done sending (disallows sending) + # (SHUT_RDWR) 2 = Both + self.__log.trace("Shutting down %s socket for receiving", name) # type: ignore + sock.shutdown(socket.SHUT_RD) + except (OSError, socket.error): + # We do not log errors here, as unconnected sockets cannot + # be shutdown and we want to throw any socket at this function. + pass + + def shutdown_send(self, sock, name): + # type: (socket.socket, str) -> None + """Shuts down a socket for sending data (only allow to receive data). + + Args: + name (str): Name of the socket used for logging purposes. + sock (str): Socket to shutdown for send. + """ + try: + # (SHUT_RD) 0 = Done receiving (disallows receiving) + # (SHUT_WR) 1 = Done sending (disallows sending) + # (SHUT_RDWR) 2 = Both + self.__log.trace("Shutting down %s socket for sending", name) # type: ignore + sock.shutdown(socket.SHUT_WR) + except (OSError, socket.error): + # We do not log errors here, as unconnected sockets cannot + # be shutdown and we want to throw any socket at this function. + pass + def close(self, sock, name): # type: (socket.socket, str) -> None """Shuts down and closes a socket. Args: + sock (socket.socket): Socket to shutdown and close. name (str): Name of the socket used for logging purposes. - sock (str): Socket to shutdown and close. """ try: # (SHUT_RD) 0 = Done receiving (disallows receiving) @@ -1825,6 +1856,11 @@

      Module pwncat

      # -------------------------------------------------------------------------- # Public Send / Receive Functions # -------------------------------------------------------------------------- + def send_eof(self): + # type: () -> None + """Close the active socket for sending. The remote part will get an EOF.""" + self.__sock.shutdown_send(self.__active["conn"], "conn") + def send(self, data): # type: (bytes) -> int """Send data through a connected (TCP) or unconnected (UDP) socket. @@ -2474,7 +2510,7 @@

      Module pwncat

      str: The string as it is without changes """ if StringEncoder.encode(self.__opts.safeword) in data: - self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore + self.log.trace("TERMINATE signal RAISED in TransformSafeword.transform") # type: ignore self.__opts.ssig.raise_terminate() return data @@ -2799,6 +2835,13 @@

      Module pwncat

      yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action except socket.timeout as err: + # Check if we close the socket for sending + if self.ssig.has_sock_send_eof(): + self.log.trace( # type: ignore + "SOCK-SEND-EOF signal ACK in IONetwork.producer [1]: %s", err + ) + self.__net.send_eof() + # Let's ask the interrupter() function if we should terminate? if not self.ssig.has_sock_quit(): continue @@ -2820,7 +2863,7 @@

      Module pwncat

      ) self.__cleanup() return - # [3/3] Upstream is gone (in one way or another) + # [3/3] Connection was closed remotely (EOF) or locally (Ctrl+C or similar) except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? if self.ssig.has_sock_quit(): @@ -2838,10 +2881,8 @@

      Module pwncat

      if self.__role == "client" and self.__client_reconnect_to_server(): continue # Inform everybody that we are quitting - self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore - self.ssig.raise_sock_quit() - self.__cleanup() - return + self.log.trace("SOCK-EOF signal RAISE in IONetwork.producer") # type: ignore + self.ssig.raise_sock_eof() def consumer(self, data): # type: (bytes) -> None @@ -2854,7 +2895,7 @@

      Module pwncat

      def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore + self.log.trace("SOCK-QUIT signal RAISE in IONetwork.interrupt") # type: ignore self.ssig.raise_sock_quit() self.__cleanup() @@ -2887,7 +2928,7 @@

      Module pwncat

      # Don't know how fast the other threads are. if self.ssig.has_sock_quit(): self.log.trace( # type: ignore - "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" + "SOCK-QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" ) return False @@ -2899,7 +2940,7 @@

      Module pwncat

      # we will check again here. if self.ssig.has_sock_quit(): self.log.trace( # type: ignore - "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" + "SOCK-QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" ) return False @@ -3305,7 +3346,7 @@

      Module pwncat

      def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore + self.log.trace("SOCK-QUIT signal RAISED in IONetworkScanner.interrupt") # type: ignore self.ssig.raise_sock_quit() # NOTE: Closing up to 65535 sockets (single thread) takes very very long @@ -3344,11 +3385,7 @@

      Module pwncat

      super(IOStdinStdout, self).__init__(ssig) self.__opts = opts self.__py3 = sys.version_info >= (3, 0) # type: bool -<<<<<<< HEAD self.__win = os.name != "posix" # posix or nt -======= - self.__abort = False ->>>>>>> Heavy refactoring # -------------------------------------------------------------------------- # Public Functions @@ -3367,35 +3404,13 @@

      Module pwncat

      # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.__abort: - self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore - return if self.ssig.has_stdin_quit(): self.log.trace( # type: ignore "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]" ) return try: -<<<<<<< HEAD data = self.__read_stdin() -======= - # TODO: select() does not work for windows on stdin/stdout - if os.name != "nt": - self.__set_input_timeout() - if self.__py3: - line = sys.stdin.buffer.readline() - else: - if sys.platform == "win32": - # Python 2 on Windows opens sys.stdin in text mode, and - # binary data that read from it becomes corrupted on \r\n. - # Setting sys.stdin to binary mode fixes that. - if hasattr(os, "O_BINARY"): - msvcrt.setmode( - sys.stdin.fileno(), os.O_BINARY, # pylint: disable=no-member - ) - line = sys.stdin.readline() # type: ignore - ->>>>>>> Heavy refactoring except EOFError: # When using select() with timeout, we don't have any input # at this point and simply continue the loop or quit if @@ -3406,27 +3421,21 @@

      Module pwncat

      ) return continue -<<<<<<< HEAD if data: self.log.debug("Received %d bytes from STDIN", len(data)) self.log.trace("Received: %s", repr(data)) # type: ignore - yield data -======= - if line: - self.log.debug("Received %d bytes from STDIN", len(line)) - self.log.trace("Received: %s", repr(line)) # type: ignore # [send-on-eof] Append data if self.__opts.send_on_eof: - lines.append(line) + lines.append(data) else: - yield line ->>>>>>> Heavy refactoring + yield data # EOF or <Ctrl>+<d> else: # [send-on-eof] Dump data before quitting if lines and self.__opts.send_on_eof: yield StringEncoder.encode("").join(lines) - self.ssig.raise_stdin_quit() + self.log.trace("STDIN-EOF signal RAISE in IOStdinStdout.producer") # type: ignore + self.ssig.raise_stdin_eof() def consumer(self, data): # type: (bytes) -> None @@ -3451,14 +3460,9 @@

      Module pwncat

      # type: () -> None """Stop function that can be called externally to close this instance.""" # TODO: Does not work on windows as it has blocking read of stdin - self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore + self.log.trace("STDIN-QUIT signal RAISE in IOStdinStdout.interrupt") # type: ignore self.ssig.raise_stdin_quit() - self.log.trace( # type: ignore - "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" - ) - self.__abort = True - # -------------------------------------------------------------------------- # Private Functions # -------------------------------------------------------------------------- @@ -3587,26 +3591,19 @@

      Module pwncat

      assert self.proc.stdout is not None while True: if self.ssig.has_command_quit(): - self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.log.trace("COMMAND-QUIT signal ACK IOCommand.producer") # type: ignore self.__cleanup() return self.log.trace("Reading command output") # type: ignore -<<<<<<< HEAD # Byte-wise reading is required to make it work for remote ends being in raw mode # However, the performance of self.proc.stdout.readline() is way faster. # To improve performance we will get rid of all other logging calls here. data = self.proc.stdout.read(1) -======= - # Much better performance than self.proc.read(1) - # TODO: check if self.proc.read(1) might be better in raw mode - data = self.proc.stdout.readline() ->>>>>>> Heavy refactoring self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: - self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore - self.ssig.raise_command_quit() - self.__cleanup() - return + self.log.trace("COMMAND-EOF signal RAISED IOCommand.producer") # type: ignore + self.ssig.raise_command_eof() + continue yield data def consumer(self, data): @@ -3624,7 +3621,7 @@

      Module pwncat

      def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore + self.log.trace("COMMAND-QUIT signal RAISED IOCommand.interrupt") # type: ignore self.ssig.raise_command_quit() self.__cleanup() @@ -3633,7 +3630,7 @@

      Module pwncat

      """Cleanup function.""" if not self.__cleaned_up: self.log.trace( # type: ignore - "CMD-QUIT-CLEANUP: killing executable: %s with pid %d", + "COMMAND-QUIT-CLEANUP: killing executable: %s with pid %d", self.__opts.executable, self.proc.pid, ) @@ -3751,11 +3748,18 @@

      Module pwncat

      self.__keep_open = keep_open self.__no_shutdown = no_shutdown + # Shutdown signals self.__terminate = False + self.__sock_send_eof = False self.__sock_quit = False self.__stdin_quit = False self.__command_quit = False + # Producers have received EOF + self.__sock_eof = False + self.__stdin_eof = False + self.__command_eof = False + def handler(signum, frame): # type: ignore # pylint: disable=unused-argument self.__log.trace("Ctrl+c caught.") # type: ignore self.raise_terminate() @@ -3771,6 +3775,11 @@

      Module pwncat

      """`bool`: Switch to be checked if pwncat should be terminated.""" return self.__terminate + def has_sock_send_eof(self): + # type: () -> bool + """`bool`: Switch to be checked if the socket connection should be closed for sending.""" + return self.__sock_send_eof + def has_sock_quit(self): # type: () -> bool """`bool`: Switch to be checked if the socket connection should be closed.""" @@ -3787,7 +3796,7 @@

      Module pwncat

      return self.__command_quit # -------------------------------------------------------------------------- - # Raise signals + # Raise Termination signal # -------------------------------------------------------------------------- def raise_terminate(self): # type: () -> None @@ -3798,6 +3807,22 @@

      Module pwncat

      self.__stdin_quit = True self.__command_quit = True + # -------------------------------------------------------------------------- + # Raise Socket signals + # -------------------------------------------------------------------------- + def raise_sock_send_eof(self): + # type: () -> None + """Signal the application that Socket should be closed for sending.""" + self.__log.trace("SIGNAL SOCK-CLOSE-SEND raised") # type: ignore + self.__sock_send_eof = True + + def raise_sock_eof(self): + # type: () -> None + """Signal the application that Socket has received EOF.""" + self.__log.trace("SIGNAL SOCK-EOF raised") # type: ignore + self.__sock_eof = True + self.raise_sock_quit() + def raise_sock_quit(self): # type: () -> None """Signal the application that Socket should be quit.""" @@ -3805,18 +3830,42 @@

      Module pwncat

      self.__sock_quit = True self.raise_terminate() + # -------------------------------------------------------------------------- + # Raise STDIN signals + # -------------------------------------------------------------------------- + def raise_stdin_eof(self): + # type: () -> None + """Signal the application that STDIN has received EOF.""" + self.__log.trace("SIGNAL STDIN-EOF raised") # type: ignore + self.__stdin_eof = True + self.raise_stdin_quit() + def raise_stdin_quit(self): # type: () -> None """Signal the application that STDIN should be quit.""" + self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore + self.__stdin_quit = True + # If --no-shutdown or -keep-open is specified + # pwncat will not invoke shutdown on a socket after seeing EOF on stdin if not (self.__no_shutdown or self.__keep_open): - self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore - self.__stdin_quit = True - self.raise_terminate() + # No more data from stdin, we can tell the remote side we are done + # by closing the socket for sending (they will receive an EOF). + self.raise_sock_send_eof() + + # -------------------------------------------------------------------------- + # Raise COMMAND signals + # -------------------------------------------------------------------------- + def raise_command_eof(self): + # type: () -> None + """Signal the application that Command has received EOF.""" + self.__log.trace("SIGNAL COMMAND-EOF raised") # type: ignore + self.__command_eof = True + self.raise_command_quit() def raise_command_quit(self): # type: () -> None """Signal the application that Command should be quit.""" - self.__log.trace("SIGNAL CMD-QUIT raised") # type: ignore + self.__log.trace("SIGNAL COMMAND-QUIT raised") # type: ignore self.__command_quit = True self.raise_terminate() @@ -4022,7 +4071,8 @@

      Module pwncat

      ), ) # Daemon threads are easier to kill - thread.daemon = True + # FIXME: Only use daemon threads for Port scanner + thread.daemon = False # Add delay if threads cannot be started delay = 0.0 @@ -4081,12 +4131,16 @@

      Module pwncat

      def check_stop(): # type: () -> bool """Stop threads.""" + # FIXME: Use two methods here + # if non-daemin threads - do join + # if scanner do not use join! # TODO: This is a workaround for using daemon threads. # Python < 3.3 is unable to detect Ctrl+c signal during # thread.join() operation in a fast loop (Port scan). - if self.__ssig.has_terminate(): - for key in self.__threads: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", getattr(interrupt, "__self__").__class__.__name__, @@ -4094,7 +4148,18 @@

      Module pwncat

      self.__threads[key].getName(), ) interrupt() - return True + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal handler + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): return True @@ -9807,26 +9872,19 @@

      Args

      assert self.proc.stdout is not None while True: if self.ssig.has_command_quit(): - self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.log.trace("COMMAND-QUIT signal ACK IOCommand.producer") # type: ignore self.__cleanup() return self.log.trace("Reading command output") # type: ignore -<<<<<<< HEAD # Byte-wise reading is required to make it work for remote ends being in raw mode # However, the performance of self.proc.stdout.readline() is way faster. # To improve performance we will get rid of all other logging calls here. data = self.proc.stdout.read(1) -======= - # Much better performance than self.proc.read(1) - # TODO: check if self.proc.read(1) might be better in raw mode - data = self.proc.stdout.readline() ->>>>>>> Heavy refactoring self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: - self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore - self.ssig.raise_command_quit() - self.__cleanup() - return + self.log.trace("COMMAND-EOF signal RAISED IOCommand.producer") # type: ignore + self.ssig.raise_command_eof() + continue yield data def consumer(self, data): @@ -9844,7 +9902,7 @@

      Args

      def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore + self.log.trace("COMMAND-QUIT signal RAISED IOCommand.interrupt") # type: ignore self.ssig.raise_command_quit() self.__cleanup() @@ -9853,7 +9911,7 @@

      Args

      """Cleanup function.""" if not self.__cleaned_up: self.log.trace( # type: ignore - "CMD-QUIT-CLEANUP: killing executable: %s with pid %d", + "COMMAND-QUIT-CLEANUP: killing executable: %s with pid %d", self.__opts.executable, self.proc.pid, ) @@ -9906,7 +9964,7 @@

      Args

      def interrupt(self):
           # type: () -> None
           """Stop function that can be called externally to close this instance."""
      -    self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt")  # type: ignore
      +    self.log.trace("COMMAND-QUIT signal RAISED IOCommand.interrupt")  # type: ignore
           self.ssig.raise_command_quit()
           self.__cleanup()
      @@ -9935,26 +9993,19 @@

      Yields

      assert self.proc.stdout is not None while True: if self.ssig.has_command_quit(): - self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore + self.log.trace("COMMAND-QUIT signal ACK IOCommand.producer") # type: ignore self.__cleanup() return self.log.trace("Reading command output") # type: ignore -<<<<<<< HEAD # Byte-wise reading is required to make it work for remote ends being in raw mode # However, the performance of self.proc.stdout.readline() is way faster. # To improve performance we will get rid of all other logging calls here. data = self.proc.stdout.read(1) -======= - # Much better performance than self.proc.read(1) - # TODO: check if self.proc.read(1) might be better in raw mode - data = self.proc.stdout.readline() ->>>>>>> Heavy refactoring self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: - self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore - self.ssig.raise_command_quit() - self.__cleanup() - return + self.log.trace("COMMAND-EOF signal RAISED IOCommand.producer") # type: ignore + self.ssig.raise_command_eof() + continue yield data @@ -10076,6 +10127,13 @@

      Args

      yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action except socket.timeout as err: + # Check if we close the socket for sending + if self.ssig.has_sock_send_eof(): + self.log.trace( # type: ignore + "SOCK-SEND-EOF signal ACK in IONetwork.producer [1]: %s", err + ) + self.__net.send_eof() + # Let's ask the interrupter() function if we should terminate? if not self.ssig.has_sock_quit(): continue @@ -10097,7 +10155,7 @@

      Args

      ) self.__cleanup() return - # [3/3] Upstream is gone (in one way or another) + # [3/3] Connection was closed remotely (EOF) or locally (Ctrl+C or similar) except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? if self.ssig.has_sock_quit(): @@ -10115,10 +10173,8 @@

      Args

      if self.__role == "client" and self.__client_reconnect_to_server(): continue # Inform everybody that we are quitting - self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore - self.ssig.raise_sock_quit() - self.__cleanup() - return + self.log.trace("SOCK-EOF signal RAISE in IONetwork.producer") # type: ignore + self.ssig.raise_sock_eof() def consumer(self, data): # type: (bytes) -> None @@ -10131,7 +10187,7 @@

      Args

      def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore + self.log.trace("SOCK-QUIT signal RAISE in IONetwork.interrupt") # type: ignore self.ssig.raise_sock_quit() self.__cleanup() @@ -10164,7 +10220,7 @@

      Args

      # Don't know how fast the other threads are. if self.ssig.has_sock_quit(): self.log.trace( # type: ignore - "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" + "SOCK-QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" ) return False @@ -10176,7 +10232,7 @@

      Args

      # we will check again here. if self.ssig.has_sock_quit(): self.log.trace( # type: ignore - "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" + "SOCK-QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" ) return False @@ -10338,7 +10394,7 @@

      Methods

      def interrupt(self):
           # type: () -> None
           """Stop function that can be called externally to close this instance."""
      -    self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt")  # type: ignore
      +    self.log.trace("SOCK-QUIT signal RAISE in IONetwork.interrupt")  # type: ignore
           self.ssig.raise_sock_quit()
           self.__cleanup()
      @@ -10375,6 +10431,13 @@

      Yields

      yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action except socket.timeout as err: + # Check if we close the socket for sending + if self.ssig.has_sock_send_eof(): + self.log.trace( # type: ignore + "SOCK-SEND-EOF signal ACK in IONetwork.producer [1]: %s", err + ) + self.__net.send_eof() + # Let's ask the interrupter() function if we should terminate? if not self.ssig.has_sock_quit(): continue @@ -10396,7 +10459,7 @@

      Yields

      ) self.__cleanup() return - # [3/3] Upstream is gone (in one way or another) + # [3/3] Connection was closed remotely (EOF) or locally (Ctrl+C or similar) except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? if self.ssig.has_sock_quit(): @@ -10414,10 +10477,8 @@

      Yields

      if self.__role == "client" and self.__client_reconnect_to_server(): continue # Inform everybody that we are quitting - self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore - self.ssig.raise_sock_quit() - self.__cleanup() - return + self.log.trace("SOCK-EOF signal RAISE in IONetwork.producer") # type: ignore + self.ssig.raise_sock_eof() @@ -10734,7 +10795,7 @@

      Args

      def interrupt(self): # type: () -> None """Stop function that can be called externally to close this instance.""" - self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore + self.log.trace("SOCK-QUIT signal RAISED in IONetworkScanner.interrupt") # type: ignore self.ssig.raise_sock_quit()

      Ancestors

      @@ -10799,7 +10860,7 @@

      Methods

      def interrupt(self):
           # type: () -> None
           """Stop function that can be called externally to close this instance."""
      -    self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt")  # type: ignore
      +    self.log.trace("SOCK-QUIT signal RAISED in IONetworkScanner.interrupt")  # type: ignore
           self.ssig.raise_sock_quit()
      @@ -10966,11 +11027,7 @@

      Args

      super(IOStdinStdout, self).__init__(ssig) self.__opts = opts self.__py3 = sys.version_info >= (3, 0) # type: bool -<<<<<<< HEAD self.__win = os.name != "posix" # posix or nt -======= - self.__abort = False ->>>>>>> Heavy refactoring # -------------------------------------------------------------------------- # Public Functions @@ -10989,35 +11046,13 @@

      Args

      # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.__abort: - self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore - return if self.ssig.has_stdin_quit(): self.log.trace( # type: ignore "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]" ) return try: -<<<<<<< HEAD data = self.__read_stdin() -======= - # TODO: select() does not work for windows on stdin/stdout - if os.name != "nt": - self.__set_input_timeout() - if self.__py3: - line = sys.stdin.buffer.readline() - else: - if sys.platform == "win32": - # Python 2 on Windows opens sys.stdin in text mode, and - # binary data that read from it becomes corrupted on \r\n. - # Setting sys.stdin to binary mode fixes that. - if hasattr(os, "O_BINARY"): - msvcrt.setmode( - sys.stdin.fileno(), os.O_BINARY, # pylint: disable=no-member - ) - line = sys.stdin.readline() # type: ignore - ->>>>>>> Heavy refactoring except EOFError: # When using select() with timeout, we don't have any input # at this point and simply continue the loop or quit if @@ -11028,27 +11063,21 @@

      Args

      ) return continue -<<<<<<< HEAD if data: self.log.debug("Received %d bytes from STDIN", len(data)) self.log.trace("Received: %s", repr(data)) # type: ignore - yield data -======= - if line: - self.log.debug("Received %d bytes from STDIN", len(line)) - self.log.trace("Received: %s", repr(line)) # type: ignore # [send-on-eof] Append data if self.__opts.send_on_eof: - lines.append(line) + lines.append(data) else: - yield line ->>>>>>> Heavy refactoring + yield data # EOF or <Ctrl>+<d> else: # [send-on-eof] Dump data before quitting if lines and self.__opts.send_on_eof: yield StringEncoder.encode("").join(lines) - self.ssig.raise_stdin_quit() + self.log.trace("STDIN-EOF signal RAISE in IOStdinStdout.producer") # type: ignore + self.ssig.raise_stdin_eof() def consumer(self, data): # type: (bytes) -> None @@ -11073,14 +11102,9 @@

      Args

      # type: () -> None """Stop function that can be called externally to close this instance.""" # TODO: Does not work on windows as it has blocking read of stdin - self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore + self.log.trace("STDIN-QUIT signal RAISE in IOStdinStdout.interrupt") # type: ignore self.ssig.raise_stdin_quit() - self.log.trace( # type: ignore - "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" - ) - self.__abort = True - # -------------------------------------------------------------------------- # Private Functions # -------------------------------------------------------------------------- @@ -11192,13 +11216,8 @@

      Methods

      # type: () -> None """Stop function that can be called externally to close this instance.""" # TODO: Does not work on windows as it has blocking read of stdin - self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore - self.ssig.raise_stdin_quit() - - self.log.trace( # type: ignore - "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" - ) - self.__abort = True + self.log.trace("STDIN-QUIT signal RAISE in IOStdinStdout.interrupt") # type: ignore + self.ssig.raise_stdin_quit()
      @@ -11229,35 +11248,13 @@

      Yields

      # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.__abort: - self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore - return if self.ssig.has_stdin_quit(): self.log.trace( # type: ignore "STDIN-QUIT signal ACK in IOStdinStdout.producer [1]" ) return try: -<<<<<<< HEAD data = self.__read_stdin() -======= - # TODO: select() does not work for windows on stdin/stdout - if os.name != "nt": - self.__set_input_timeout() - if self.__py3: - line = sys.stdin.buffer.readline() - else: - if sys.platform == "win32": - # Python 2 on Windows opens sys.stdin in text mode, and - # binary data that read from it becomes corrupted on \r\n. - # Setting sys.stdin to binary mode fixes that. - if hasattr(os, "O_BINARY"): - msvcrt.setmode( - sys.stdin.fileno(), os.O_BINARY, # pylint: disable=no-member - ) - line = sys.stdin.readline() # type: ignore - ->>>>>>> Heavy refactoring except EOFError: # When using select() with timeout, we don't have any input # at this point and simply continue the loop or quit if @@ -11268,27 +11265,21 @@

      Yields

      ) return continue -<<<<<<< HEAD if data: self.log.debug("Received %d bytes from STDIN", len(data)) self.log.trace("Received: %s", repr(data)) # type: ignore - yield data -======= - if line: - self.log.debug("Received %d bytes from STDIN", len(line)) - self.log.trace("Received: %s", repr(line)) # type: ignore # [send-on-eof] Append data if self.__opts.send_on_eof: - lines.append(line) + lines.append(data) else: - yield line ->>>>>>> Heavy refactoring + yield data # EOF or <Ctrl>+<d> else: # [send-on-eof] Dump data before quitting if lines and self.__opts.send_on_eof: yield StringEncoder.encode("").join(lines) - self.ssig.raise_stdin_quit()
      + self.log.trace("STDIN-EOF signal RAISE in IOStdinStdout.producer") # type: ignore + self.ssig.raise_stdin_eof() @@ -11348,11 +11339,18 @@

      Args

      self.__keep_open = keep_open self.__no_shutdown = no_shutdown + # Shutdown signals self.__terminate = False + self.__sock_send_eof = False self.__sock_quit = False self.__stdin_quit = False self.__command_quit = False + # Producers have received EOF + self.__sock_eof = False + self.__stdin_eof = False + self.__command_eof = False + def handler(signum, frame): # type: ignore # pylint: disable=unused-argument self.__log.trace("Ctrl+c caught.") # type: ignore self.raise_terminate() @@ -11368,6 +11366,11 @@

      Args

      """`bool`: Switch to be checked if pwncat should be terminated.""" return self.__terminate + def has_sock_send_eof(self): + # type: () -> bool + """`bool`: Switch to be checked if the socket connection should be closed for sending.""" + return self.__sock_send_eof + def has_sock_quit(self): # type: () -> bool """`bool`: Switch to be checked if the socket connection should be closed.""" @@ -11384,7 +11387,7 @@

      Args

      return self.__command_quit # -------------------------------------------------------------------------- - # Raise signals + # Raise Termination signal # -------------------------------------------------------------------------- def raise_terminate(self): # type: () -> None @@ -11395,6 +11398,22 @@

      Args

      self.__stdin_quit = True self.__command_quit = True + # -------------------------------------------------------------------------- + # Raise Socket signals + # -------------------------------------------------------------------------- + def raise_sock_send_eof(self): + # type: () -> None + """Signal the application that Socket should be closed for sending.""" + self.__log.trace("SIGNAL SOCK-CLOSE-SEND raised") # type: ignore + self.__sock_send_eof = True + + def raise_sock_eof(self): + # type: () -> None + """Signal the application that Socket has received EOF.""" + self.__log.trace("SIGNAL SOCK-EOF raised") # type: ignore + self.__sock_eof = True + self.raise_sock_quit() + def raise_sock_quit(self): # type: () -> None """Signal the application that Socket should be quit.""" @@ -11402,18 +11421,42 @@

      Args

      self.__sock_quit = True self.raise_terminate() + # -------------------------------------------------------------------------- + # Raise STDIN signals + # -------------------------------------------------------------------------- + def raise_stdin_eof(self): + # type: () -> None + """Signal the application that STDIN has received EOF.""" + self.__log.trace("SIGNAL STDIN-EOF raised") # type: ignore + self.__stdin_eof = True + self.raise_stdin_quit() + def raise_stdin_quit(self): # type: () -> None """Signal the application that STDIN should be quit.""" + self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore + self.__stdin_quit = True + # If --no-shutdown or -keep-open is specified + # pwncat will not invoke shutdown on a socket after seeing EOF on stdin if not (self.__no_shutdown or self.__keep_open): - self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore - self.__stdin_quit = True - self.raise_terminate() + # No more data from stdin, we can tell the remote side we are done + # by closing the socket for sending (they will receive an EOF). + self.raise_sock_send_eof() + + # -------------------------------------------------------------------------- + # Raise COMMAND signals + # -------------------------------------------------------------------------- + def raise_command_eof(self): + # type: () -> None + """Signal the application that Command has received EOF.""" + self.__log.trace("SIGNAL COMMAND-EOF raised") # type: ignore + self.__command_eof = True + self.raise_command_quit() def raise_command_quit(self): # type: () -> None """Signal the application that Command should be quit.""" - self.__log.trace("SIGNAL CMD-QUIT raised") # type: ignore + self.__log.trace("SIGNAL COMMAND-QUIT raised") # type: ignore self.__command_quit = True self.raise_terminate() @@ -11449,6 +11492,21 @@

      Methods

      return self.__sock_quit +
      +def has_sock_send_eof(self) +
      +
      +

      bool: Switch to be checked if the socket connection should be closed for sending.

      +
      + +Expand source code + +
      def has_sock_send_eof(self):
      +    # type: () -> bool
      +    """`bool`: Switch to be checked if the socket connection should be closed for sending."""
      +    return self.__sock_send_eof
      +
      +
      def has_stdin_quit(self)
      @@ -11479,6 +11537,23 @@

      Methods

      return self.__terminate +
      +def raise_command_eof(self) +
      +
      +

      Signal the application that Command has received EOF.

      +
      + +Expand source code + +
      def raise_command_eof(self):
      +    # type: () -> None
      +    """Signal the application that Command has received EOF."""
      +    self.__log.trace("SIGNAL COMMAND-EOF raised")  # type: ignore
      +    self.__command_eof = True
      +    self.raise_command_quit()
      +
      +
      def raise_command_quit(self)
      @@ -11491,11 +11566,28 @@

      Methods

      def raise_command_quit(self):
           # type: () -> None
           """Signal the application that Command should be quit."""
      -    self.__log.trace("SIGNAL CMD-QUIT raised")  # type: ignore
      +    self.__log.trace("SIGNAL COMMAND-QUIT raised")  # type: ignore
           self.__command_quit = True
           self.raise_terminate()
      +
      +def raise_sock_eof(self) +
      +
      +

      Signal the application that Socket has received EOF.

      +
      + +Expand source code + +
      def raise_sock_eof(self):
      +    # type: () -> None
      +    """Signal the application that Socket has received EOF."""
      +    self.__log.trace("SIGNAL SOCK-EOF raised")  # type: ignore
      +    self.__sock_eof = True
      +    self.raise_sock_quit()
      +
      +
      def raise_sock_quit(self)
      @@ -11513,6 +11605,39 @@

      Methods

      self.raise_terminate() +
      +def raise_sock_send_eof(self) +
      +
      +

      Signal the application that Socket should be closed for sending.

      +
      + +Expand source code + +
      def raise_sock_send_eof(self):
      +    # type: () -> None
      +    """Signal the application that Socket should be closed for sending."""
      +    self.__log.trace("SIGNAL SOCK-CLOSE-SEND raised")  # type: ignore
      +    self.__sock_send_eof = True
      +
      +
      +
      +def raise_stdin_eof(self) +
      +
      +

      Signal the application that STDIN has received EOF.

      +
      + +Expand source code + +
      def raise_stdin_eof(self):
      +    # type: () -> None
      +    """Signal the application that STDIN has received EOF."""
      +    self.__log.trace("SIGNAL STDIN-EOF raised")  # type: ignore
      +    self.__stdin_eof = True
      +    self.raise_stdin_quit()
      +
      +
      def raise_stdin_quit(self)
      @@ -11525,10 +11650,14 @@

      Methods

      def raise_stdin_quit(self):
           # type: () -> None
           """Signal the application that STDIN should be quit."""
      +    self.__log.trace("SIGNAL STDIN-QUIT raised")  # type: ignore
      +    self.__stdin_quit = True
      +    # If --no-shutdown or -keep-open is specified
      +    # pwncat will not invoke shutdown on a socket after seeing EOF on stdin
           if not (self.__no_shutdown or self.__keep_open):
      -        self.__log.trace("SIGNAL STDIN-QUIT raised")  # type: ignore
      -        self.__stdin_quit = True
      -        self.raise_terminate()
      + # No more data from stdin, we can tell the remote side we are done + # by closing the socket for sending (they will receive an EOF). + self.raise_sock_send_eof()
      @@ -11653,6 +11782,11 @@

      Args

      # -------------------------------------------------------------------------- # Public Send / Receive Functions # -------------------------------------------------------------------------- + def send_eof(self): + # type: () -> None + """Close the active socket for sending. The remote part will get an EOF.""" + self.__sock.shutdown_send(self.__active["conn"], "conn") + def send(self, data): # type: (bytes) -> int """Send data through a connected (TCP) or unconnected (UDP) socket. @@ -12764,6 +12898,21 @@

      Raises

      return send
      +
      +def send_eof(self) +
      +
      +

      Close the active socket for sending. The remote part will get an EOF.

      +
      + +Expand source code + +
      def send_eof(self):
      +    # type: () -> None
      +    """Close the active socket for sending. The remote part will get an EOF."""
      +    self.__sock.shutdown_send(self.__active["conn"], "conn")
      +
      +
      @@ -13141,7 +13290,8 @@

      Args

      ), ) # Daemon threads are easier to kill - thread.daemon = True + # FIXME: Only use daemon threads for Port scanner + thread.daemon = False # Add delay if threads cannot be started delay = 0.0 @@ -13200,12 +13350,16 @@

      Args

      def check_stop(): # type: () -> bool """Stop threads.""" + # FIXME: Use two methods here + # if non-daemin threads - do join + # if scanner do not use join! # TODO: This is a workaround for using daemon threads. # Python < 3.3 is unable to detect Ctrl+c signal during # thread.join() operation in a fast loop (Port scan). - if self.__ssig.has_terminate(): - for key in self.__threads: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", getattr(interrupt, "__self__").__class__.__name__, @@ -13213,7 +13367,18 @@

      Args

      self.__threads[key].getName(), ) interrupt() - return True + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal handler + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): return True @@ -13482,7 +13647,8 @@

      Args

      ), ) # Daemon threads are easier to kill - thread.daemon = True + # FIXME: Only use daemon threads for Port scanner + thread.daemon = False # Add delay if threads cannot be started delay = 0.0 @@ -13541,12 +13707,16 @@

      Args

      def check_stop(): # type: () -> bool """Stop threads.""" + # FIXME: Use two methods here + # if non-daemin threads - do join + # if scanner do not use join! # TODO: This is a workaround for using daemon threads. # Python < 3.3 is unable to detect Ctrl+c signal during # thread.join() operation in a fast loop (Port scan). - if self.__ssig.has_terminate(): - for key in self.__threads: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", getattr(interrupt, "__self__").__class__.__name__, @@ -13554,7 +13724,18 @@

      Args

      self.__threads[key].getName(), ) interrupt() - return True + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal handler + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): return True @@ -14222,13 +14403,51 @@

      Args

      # -------------------------------------------------------------------------- # Destroy functions # -------------------------------------------------------------------------- + def shutdown_recv(self, sock, name): + # type: (socket.socket, str) -> None + """Shuts down a socket for receiving data (only allow to send data). + + Args: + name (str): Name of the socket used for logging purposes. + sock (str): Socket to shutdown for receive. + """ + try: + # (SHUT_RD) 0 = Done receiving (disallows receiving) + # (SHUT_WR) 1 = Done sending (disallows sending) + # (SHUT_RDWR) 2 = Both + self.__log.trace("Shutting down %s socket for receiving", name) # type: ignore + sock.shutdown(socket.SHUT_RD) + except (OSError, socket.error): + # We do not log errors here, as unconnected sockets cannot + # be shutdown and we want to throw any socket at this function. + pass + + def shutdown_send(self, sock, name): + # type: (socket.socket, str) -> None + """Shuts down a socket for sending data (only allow to receive data). + + Args: + name (str): Name of the socket used for logging purposes. + sock (str): Socket to shutdown for send. + """ + try: + # (SHUT_RD) 0 = Done receiving (disallows receiving) + # (SHUT_WR) 1 = Done sending (disallows sending) + # (SHUT_RDWR) 2 = Both + self.__log.trace("Shutting down %s socket for sending", name) # type: ignore + sock.shutdown(socket.SHUT_WR) + except (OSError, socket.error): + # We do not log errors here, as unconnected sockets cannot + # be shutdown and we want to throw any socket at this function. + pass + def close(self, sock, name): # type: (socket.socket, str) -> None """Shuts down and closes a socket. Args: + sock (socket.socket): Socket to shutdown and close. name (str): Name of the socket used for logging purposes. - sock (str): Socket to shutdown and close. """ try: # (SHUT_RD) 0 = Done receiving (disallows receiving) @@ -14490,10 +14709,10 @@

      Raises

      Shuts down and closes a socket.

      Args

      +
      sock : socket.socket
      +
      Socket to shutdown and close.
      name : str
      Name of the socket used for logging purposes.
      -
      sock : str
      -
      Socket to shutdown and close.
      @@ -14504,8 +14723,8 @@

      Args

      """Shuts down and closes a socket. Args: + sock (socket.socket): Socket to shutdown and close. name (str): Name of the socket used for logging purposes. - sock (str): Socket to shutdown and close. """ try: # (SHUT_RD) 0 = Done receiving (disallows receiving) @@ -14978,6 +15197,78 @@

      Raises

      raise socket.error(msg)
      +
      +def shutdown_recv(self, sock, name) +
      +
      +

      Shuts down a socket for receiving data (only allow to send data).

      +

      Args

      +
      +
      name : str
      +
      Name of the socket used for logging purposes.
      +
      sock : str
      +
      Socket to shutdown for receive.
      +
      +
      + +Expand source code + +
      def shutdown_recv(self, sock, name):
      +    # type: (socket.socket, str) -> None
      +    """Shuts down a socket for receiving data (only allow to send data).
      +
      +    Args:
      +        name (str): Name of the socket used for logging purposes.
      +        sock (str): Socket to shutdown for receive.
      +    """
      +    try:
      +        # (SHUT_RD)   0 = Done receiving (disallows receiving)
      +        # (SHUT_WR)   1 = Done sending (disallows sending)
      +        # (SHUT_RDWR) 2 = Both
      +        self.__log.trace("Shutting down %s socket for receiving", name)  # type: ignore
      +        sock.shutdown(socket.SHUT_RD)
      +    except (OSError, socket.error):
      +        # We do not log errors here, as unconnected sockets cannot
      +        # be shutdown and we want to throw any socket at this function.
      +        pass
      +
      +
      +
      +def shutdown_send(self, sock, name) +
      +
      +

      Shuts down a socket for sending data (only allow to receive data).

      +

      Args

      +
      +
      name : str
      +
      Name of the socket used for logging purposes.
      +
      sock : str
      +
      Socket to shutdown for send.
      +
      +
      + +Expand source code + +
      def shutdown_send(self, sock, name):
      +    # type: (socket.socket, str) -> None
      +    """Shuts down a socket for sending data (only allow to receive data).
      +
      +    Args:
      +        name (str): Name of the socket used for logging purposes.
      +        sock (str): Socket to shutdown for send.
      +    """
      +    try:
      +        # (SHUT_RD)   0 = Done receiving (disallows receiving)
      +        # (SHUT_WR)   1 = Done sending (disallows sending)
      +        # (SHUT_RDWR) 2 = Both
      +        self.__log.trace("Shutting down %s socket for sending", name)  # type: ignore
      +        sock.shutdown(socket.SHUT_WR)
      +    except (OSError, socket.error):
      +        # We do not log errors here, as unconnected sockets cannot
      +        # be shutdown and we want to throw any socket at this function.
      +        pass
      +
      +
      @@ -15891,7 +16182,7 @@

      Args

      str: The string as it is without changes """ if StringEncoder.encode(self.__opts.safeword) in data: - self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore + self.log.trace("TERMINATE signal RAISED in TransformSafeword.transform") # type: ignore self.__opts.ssig.raise_terminate() return data
      @@ -15924,7 +16215,7 @@

      Returns

      str: The string as it is without changes """ if StringEncoder.encode(self.__opts.safeword) in data: - self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore + self.log.trace("TERMINATE signal RAISED in TransformSafeword.transform") # type: ignore self.__opts.ssig.raise_terminate() return data @@ -16157,10 +16448,15 @@

      Int @@ -16175,6 +16471,7 @@

      Net

    • run_client
    • run_server
    • send
    • +
    • send_eof
  • @@ -16212,6 +16509,8 @@

    Sock

  • is_ipv4_address
  • is_ipv6_address
  • listen
  • +
  • shutdown_recv
  • +
  • shutdown_send
  • diff --git a/docs/pwncat.type.html b/docs/pwncat.type.html index 514aee31..48dee351 100644 --- a/docs/pwncat.type.html +++ b/docs/pwncat.type.html @@ -14,6 +14,7 @@

    Mypy Type Check Coverage Summary

    Total +<<<<<<< HEAD 6.44% imprecise <<<<<<< HEAD 5283 LOC @@ -29,6 +30,15 @@

    Mypy Type Check Coverage Summary

    ======= 5687 LOC >>>>>>> Heavy refactoring +======= +6.45% imprecise +5795 LOC + + +bin/pwncat +6.45% imprecise +5795 LOC +>>>>>>> Fix signal handling @@ -5732,7 +5742,118 @@

    pwncat

    5685 5686 5687 +<<<<<<< HEAD >>>>>>> Heavy refactoring +======= +5688 +5689 +5690 +5691 +5692 +5693 +5694 +5695 +5696 +5697 +5698 +5699 +5700 +5701 +5702 +5703 +5704 +5705 +5706 +5707 +5708 +5709 +5710 +5711 +5712 +5713 +5714 +5715 +5716 +5717 +5718 +5719 +5720 +5721 +5722 +5723 +5724 +5725 +5726 +5727 +5728 +5729 +5730 +5731 +5732 +5733 +5734 +5735 +5736 +5737 +5738 +5739 +5740 +5741 +5742 +5743 +5744 +5745 +5746 +5747 +5748 +5749 +5750 +5751 +5752 +5753 +5754 +5755 +5756 +5757 +5758 +5759 +5760 +5761 +5762 +5763 +5764 +5765 +5766 +5767 +5768 +5769 +5770 +5771 +5772 +5773 +5774 +5775 +5776 +5777 +5778 +5779 +5780 +5781 +5782 +5783 +5784 +5785 +5786 +5787 +5788 +5789 +5790 +5791 +5792 +5793 +5794 +5795 +>>>>>>> Fix signal handling
    #!/usr/bin/env python3
     """pwncat."""
    @@ -7539,13 +7660,53 @@ 

    pwncat

    # -------------------------------------------------------------------------- # Destroy functions # -------------------------------------------------------------------------- + def shutdown_recv(self, sock, name): + # type: (socket.socket, str) -> None + """Shuts down a socket for receiving data (only allow to send data). + + Args: + name (str): Name of the socket used for logging purposes. + sock (str): Socket to shutdown for receive. + """ + try: + # (SHUT_RD) 0 = Done receiving (disallows receiving) + # (SHUT_WR) 1 = Done sending (disallows sending) + # (SHUT_RDWR) 2 = Both + self.__log.trace("Shutting down %s socket for receiving", name) # type: ignore + sock.shutdown(socket.SHUT_RD) + except (OSError, socket.error): + # We do not log errors here, as unconnected sockets cannot + # be shutdown and we want to throw any socket at this function. + pass + + def shutdown_send(self, sock, name): + # type: (socket.socket, str) -> None + """Shuts down a socket for sending data (only allow to receive data). + + Args: + name (str): Name of the socket used for logging purposes. + sock (str): Socket to shutdown for send. + """ + try: + # (SHUT_RD) 0 = Done receiving (disallows receiving) + # (SHUT_WR) 1 = Done sending (disallows sending) + # (SHUT_RDWR) 2 = Both + self.__log.trace("Shutting down %s socket for sending", name) # type: ignore + sock.shutdown(socket.SHUT_WR) + except (OSError, socket.error): + # We do not log errors here, as unconnected sockets cannot + # be shutdown and we want to throw any socket at this function. + pass + def close(self, sock, name): # type: (socket.socket, str) -> None """Shuts down and closes a socket. Args: + sock (socket.socket): Socket to shutdown and close. name (str): Name of the socket used for logging purposes. - sock (str): Socket to shutdown and close. """ try: # (SHUT_RD) 0 = Done receiving (disallows receiving) @@ -7648,6 +7809,11 @@

    pwncat

    # -------------------------------------------------------------------------- # Public Send / Receive Functions # -------------------------------------------------------------------------- + def send_eof(self): + # type: () -> None + """Close the active socket for sending. The remote part will get an EOF.""" + self.__sock.shutdown_send(self.__active["conn"], "conn") + def send(self, data): # type: (bytes) -> int """Send data through a connected (TCP) or unconnected (UDP) socket. @@ -8338,7 +8504,7 @@

    pwncat

    """ if StringEncoder.encode(self.__opts.safeword) in data: self.log.trace("TERMINATE signal REQ in TransformSafeword.transform") # type: ignore +Error (x2)"> self.log.trace("TERMINATE signal RAISED in TransformSafeword.transform") # type: ignore self.__opts.ssig.raise_terminate() return data @@ -8665,6 +8831,14 @@

    pwncat

    yield self.__net.receive() # [2/3] Non-blocking socket is finished receiving data and allows us to do some action except socket.timeout as err: + # Check if we close the socket for sending + if self.ssig.has_sock_send_eof(): + self.log.trace( # type: ignore + "SOCK-SEND-EOF signal ACK in IONetwork.producer [1]: %s", err + ) + self.__net.send_eof() + # Let's ask the interrupter() function if we should terminate? if not self.ssig.has_sock_quit(): continue @@ -8688,7 +8862,7 @@

    pwncat

    ) self.__cleanup() return - # [3/3] Upstream is gone (in one way or another) + # [3/3] Connection was closed remotely (EOF) or locally (Ctrl+C or similar) except (EOFError, AttributeError, socket.error) as err: # Do we have a stop signal? if self.ssig.has_sock_quit(): @@ -8708,10 +8882,8 @@

    pwncat

    continue # Inform everybody that we are quitting self.log.trace("SOCK-QUIT signal REQ in IONetwork.producer") # type: ignore - self.ssig.raise_sock_quit() - self.__cleanup() - return +Error (x2)"> self.log.trace("SOCK-EOF signal RAISE in IONetwork.producer") # type: ignore + self.ssig.raise_sock_eof() def consumer(self, data): # type: (bytes) -> None @@ -8725,7 +8897,7 @@

    pwncat

    # type: () -> None """Stop function that can be called externally to close this instance.""" self.log.trace("SOCK-QUIT signal REQ in IONetwork.interrupt") # type: ignore +Error (x2)"> self.log.trace("SOCK-QUIT signal RAISE in IONetwork.interrupt") # type: ignore self.ssig.raise_sock_quit() self.__cleanup() @@ -8760,7 +8932,7 @@

    pwncat

    if self.ssig.has_sock_quit(): self.log.trace( # type: ignore - "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" + "SOCK-QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [1]" ) return False @@ -8773,7 +8945,7 @@

    pwncat

    if self.ssig.has_sock_quit(): self.log.trace( # type: ignore - "QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" + "SOCK-QUIT signal ACK in IONetwork.__clienet_reconnect_to_server [2]" ) return False @@ -9206,7 +9378,7 @@

    pwncat

    # type: () -> None """Stop function that can be called externally to close this instance.""" self.log.trace("SOCK-QUIT signal REQ in IONetworkScanner.interrupt") # type: ignore +Error (x2)"> self.log.trace("SOCK-QUIT signal RAISED in IONetworkScanner.interrupt") # type: ignore self.ssig.raise_sock_quit() # NOTE: Closing up to 65535 sockets (single thread) takes very very long @@ -9246,10 +9418,13 @@

    pwncat

    self.__opts = opts self.__py3 = sys.version_info >= (3, 0) # type: bool <<<<<<< HEAD +<<<<<<< HEAD self.__win = os.name != "posix" # posix or nt ======= self.__abort = False >>>>>>> Heavy refactoring +======= +>>>>>>> Fix signal handling # -------------------------------------------------------------------------- # Public Functions @@ -9269,10 +9444,6 @@

    pwncat

    # while True: line = sys.stdin.readline() <- reads a whole line (faster) # for line in sys.stdin.readlin(): <- reads one byte at a time while True: - if self.__abort: - self.log.trace("External interrupt signal triggered. Aborting.") # type: ignore - return if self.ssig.has_stdin_quit(): self.log.trace( # type: ignore @@ -9331,7 +9502,9 @@

    pwncat

    # [send-on-eof] Dump data before quitting if lines and self.__opts.send_on_eof: yield StringEncoder.encode("").join(lines) - self.ssig.raise_stdin_quit() + self.log.trace("STDIN-EOF signal RAISE in IOStdinStdout.producer") # type: ignore + self.ssig.raise_stdin_eof() def consumer(self, data): # type: (bytes) -> None @@ -9358,15 +9531,9 @@

    pwncat

    """Stop function that can be called externally to close this instance.""" # TODO: Does not work on windows as it has blocking read of stdin self.log.trace("STDIN-QUIT signal REQ in IOStdinStdout.interrupt") # type: ignore +Error (x2)"> self.log.trace("STDIN-QUIT signal RAISE in IOStdinStdout.interrupt") # type: ignore self.ssig.raise_stdin_quit() - self.log.trace( # type: ignore - "[IOStdinStdout] setting __abort to True was raised by interrupt() externally" - ) - self.__abort = True - # -------------------------------------------------------------------------- # Private Functions # -------------------------------------------------------------------------- @@ -9505,7 +9672,7 @@

    pwncat

    while True: if self.ssig.has_command_quit(): self.log.trace("CMD-QUIT signal ACK IOCommand.producer") # type: ignore +Error (x2)"> self.log.trace("COMMAND-QUIT signal ACK IOCommand.producer") # type: ignore self.__cleanup() return self.log.trace("Command output: %s", repr(data)) # type: ignore if not data: self.log.trace("CMD-QUIT signal REQ IOCommand.producer") # type: ignore - self.ssig.raise_command_quit() - self.__cleanup() - return +Error (x2)"> self.log.trace("COMMAND-EOF signal RAISED IOCommand.producer") # type: ignore + self.ssig.raise_command_eof() + continue yield data def consumer(self, data): @@ -9547,7 +9713,7 @@

    pwncat

    # type: () -> None """Stop function that can be called externally to close this instance.""" self.log.trace("CMD-QUIT signal REQ IOCommand.interrupt") # type: ignore +Error (x2)"> self.log.trace("COMMAND-QUIT signal RAISED IOCommand.interrupt") # type: ignore self.ssig.raise_command_quit() self.__cleanup() @@ -9557,7 +9723,7 @@

    pwncat

    if not self.__cleaned_up: self.log.trace( # type: ignore - "CMD-QUIT-CLEANUP: killing executable: %s with pid %d", + "COMMAND-QUIT-CLEANUP: killing executable: %s with pid %d", self.__opts.executable, self.proc.pid, ) @@ -9680,11 +9846,18 @@

    pwncat

    self.__keep_open = keep_open self.__no_shutdown = no_shutdown + # Shutdown signals self.__terminate = False + self.__sock_send_eof = False self.__sock_quit = False self.__stdin_quit = False self.__command_quit = False + # Producers have received EOF + self.__sock_eof = False + self.__stdin_eof = False + self.__command_eof = False + def handler(signum, frame): # type: ignore # pylint: disable=unused-argument self.__log.trace("Ctrl+c caught.") # type: ignore @@ -9702,6 +9875,11 @@

    pwncat

    """`bool`: Switch to be checked if pwncat should be terminated.""" return self.__terminate + def has_sock_send_eof(self): + # type: () -> bool + """`bool`: Switch to be checked if the socket connection should be closed for sending.""" + return self.__sock_send_eof + def has_sock_quit(self): # type: () -> bool """`bool`: Switch to be checked if the socket connection should be closed.""" @@ -9718,7 +9896,7 @@

    pwncat

    return self.__command_quit # -------------------------------------------------------------------------- - # Raise signals + # Raise Termination signal # -------------------------------------------------------------------------- def raise_terminate(self): # type: () -> None @@ -9730,6 +9908,24 @@

    pwncat

    self.__stdin_quit = True self.__command_quit = True + # -------------------------------------------------------------------------- + # Raise Socket signals + # -------------------------------------------------------------------------- + def raise_sock_send_eof(self): + # type: () -> None + """Signal the application that Socket should be closed for sending.""" + self.__log.trace("SIGNAL SOCK-CLOSE-SEND raised") # type: ignore + self.__sock_send_eof = True + + def raise_sock_eof(self): + # type: () -> None + """Signal the application that Socket has received EOF.""" + self.__log.trace("SIGNAL SOCK-EOF raised") # type: ignore + self.__sock_eof = True + self.raise_sock_quit() + def raise_sock_quit(self): # type: () -> None """Signal the application that Socket should be quit.""" @@ -9738,20 +9934,46 @@

    pwncat

    self.__sock_quit = True self.raise_terminate() + # -------------------------------------------------------------------------- + # Raise STDIN signals + # -------------------------------------------------------------------------- + def raise_stdin_eof(self): + # type: () -> None + """Signal the application that STDIN has received EOF.""" + self.__log.trace("SIGNAL STDIN-EOF raised") # type: ignore + self.__stdin_eof = True + self.raise_stdin_quit() + def raise_stdin_quit(self): # type: () -> None """Signal the application that STDIN should be quit.""" + self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore + self.__stdin_quit = True + # If --no-shutdown or -keep-open is specified + # pwncat will not invoke shutdown on a socket after seeing EOF on stdin if not (self.__no_shutdown or self.__keep_open): + # No more data from stdin, we can tell the remote side we are done + # by closing the socket for sending (they will receive an EOF). + self.raise_sock_send_eof() + + # -------------------------------------------------------------------------- + # Raise COMMAND signals + # -------------------------------------------------------------------------- + def raise_command_eof(self): + # type: () -> None + """Signal the application that Command has received EOF.""" self.__log.trace("SIGNAL STDIN-QUIT raised") # type: ignore - self.__stdin_quit = True - self.raise_terminate() +Error (x2)"> self.__log.trace("SIGNAL COMMAND-EOF raised") # type: ignore + self.__command_eof = True + self.raise_terminate() def raise_command_quit(self): # type: () -> None """Signal the application that Command should be quit.""" self.__log.trace("SIGNAL CMD-QUIT raised") # type: ignore +Error (x2)"> self.__log.trace("SIGNAL COMMAND-QUIT raised") # type: ignore self.__command_quit = True self.raise_terminate() @@ -9978,7 +10200,8 @@

    pwncat

    ), ) # Daemon threads are easier to kill - thread.daemon = True + # FIXME: Only use daemon threads for Port scanner + thread.daemon = False # Add delay if threads cannot be started delay = 0.0 @@ -10048,12 +10271,16 @@

    pwncat

    def check_stop(): # type: () -> bool """Stop threads.""" + # FIXME: Use two methods here + # if non-daemin threads - do join + # if scanner do not use join! # TODO: This is a workaround for using daemon threads. # Python < 3.3 is unable to detect Ctrl+c signal during # thread.join() operation in a fast loop (Port scan). - if self.__ssig.has_terminate(): - for key in self.__threads: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore "Call INTERRUPT: %s.%s() for %s", @@ -10063,6 +10290,20 @@

    pwncat

    self.__threads[key].getName(), ) interrupt() + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal handler + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass return True # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): diff --git a/man/pwncat.1 b/man/pwncat.1 index 45d93ee0..a992d5be 100644 --- a/man/pwncat.1 +++ b/man/pwncat.1 @@ -1,8 +1,4 @@ -<<<<<<< HEAD .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.15. -======= -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.11. ->>>>>>> Heavy refactoring .TH PWNCAT: "1" "June 2020" "https://github.com/cytopia/pwncat" "User Commands" .SH NAME pwncat: \- pwncat From 62e044c56b7369571f3874ddf2e983b1781ff6f7 Mon Sep 17 00:00:00 2001 From: cytopia Date: Fri, 5 Jun 2020 15:35:07 +0200 Subject: [PATCH 12/61] Fix quit behaviour with signalling --- .github/workflows/test-x64-macos-2.7.yml | 29 ++ .github/workflows/test-x64-macos-3.5.yml | 29 ++ .github/workflows/test-x64-macos-3.6.yml | 29 ++ .github/workflows/test-x64-macos-3.7.yml | 29 ++ .github/workflows/test-x64-macos-3.8.yml | 29 ++ .github/workflows/test-x64-macos-pypy2.yml | 29 ++ .github/workflows/test-x64-macos-pypy3.yml | 29 ++ .github/workflows/test-x64-ubuntu-2.7.yml | 29 ++ .github/workflows/test-x64-ubuntu-3.5.yml | 29 ++ .github/workflows/test-x64-ubuntu-3.6.yml | 29 ++ .github/workflows/test-x64-ubuntu-3.7.yml | 29 ++ .github/workflows/test-x64-ubuntu-3.8.yml | 29 ++ .github/workflows/test-x64-ubuntu-pypy2.yml | 29 ++ .github/workflows/test-x64-ubuntu-pypy3.yml | 29 ++ .github/workflows/test-x64-windows-2.7.yml | 29 ++ .github/workflows/test-x64-windows-3.5.yml | 29 ++ .github/workflows/test-x64-windows-3.6.yml | 29 ++ .github/workflows/test-x64-windows-3.7.yml | 29 ++ .github/workflows/test-x64-windows-3.8.yml | 29 ++ .github/workflows/test-x64-windows-pypy2.yml | 29 ++ .github/workflows/test-x64-windows-pypy3.yml | 29 ++ Makefile | 6 + README.md | 49 +- bin/pwncat | 160 +++--- docs/pwncat.api.html | 465 +++++++++--------- docs/pwncat.type.html | 185 +++---- .../000---tcp---client_sends.sh | 169 +++++++ .../000---tcp---www-forward.sh | 30 +- .../000---tcp---www-forward.sh | 30 +- tests/pipelines/template-test.yml.tpl | 12 + 30 files changed, 1292 insertions(+), 423 deletions(-) create mode 100755 tests/integration/03-behaviour-base--file_transfer/000---tcp---client_sends.sh diff --git a/.github/workflows/test-x64-macos-2.7.yml b/.github/workflows/test-x64-macos-2.7.yml index f67e071f..4255a78b 100644 --- a/.github/workflows/test-x64-macos-2.7.yml +++ b/.github/workflows/test-x64-macos-2.7.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-macos-3.5.yml b/.github/workflows/test-x64-macos-3.5.yml index b9357786..40c5004b 100644 --- a/.github/workflows/test-x64-macos-3.5.yml +++ b/.github/workflows/test-x64-macos-3.5.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-macos-3.6.yml b/.github/workflows/test-x64-macos-3.6.yml index 7918e0d8..8c8ef46d 100644 --- a/.github/workflows/test-x64-macos-3.6.yml +++ b/.github/workflows/test-x64-macos-3.6.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-macos-3.7.yml b/.github/workflows/test-x64-macos-3.7.yml index 13ad982d..002dcb10 100644 --- a/.github/workflows/test-x64-macos-3.7.yml +++ b/.github/workflows/test-x64-macos-3.7.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-macos-3.8.yml b/.github/workflows/test-x64-macos-3.8.yml index cbad3434..cf9c5ae2 100644 --- a/.github/workflows/test-x64-macos-3.8.yml +++ b/.github/workflows/test-x64-macos-3.8.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-macos-pypy2.yml b/.github/workflows/test-x64-macos-pypy2.yml index 7405f848..0f5f311f 100644 --- a/.github/workflows/test-x64-macos-pypy2.yml +++ b/.github/workflows/test-x64-macos-pypy2.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-macos-pypy3.yml b/.github/workflows/test-x64-macos-pypy3.yml index 3ab7f5d6..ce6385fd 100644 --- a/.github/workflows/test-x64-macos-pypy3.yml +++ b/.github/workflows/test-x64-macos-pypy3.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-ubuntu-2.7.yml b/.github/workflows/test-x64-ubuntu-2.7.yml index 0d0cefb6..dd0bd664 100644 --- a/.github/workflows/test-x64-ubuntu-2.7.yml +++ b/.github/workflows/test-x64-ubuntu-2.7.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-ubuntu-3.5.yml b/.github/workflows/test-x64-ubuntu-3.5.yml index 52ae5296..fdf2ac5e 100644 --- a/.github/workflows/test-x64-ubuntu-3.5.yml +++ b/.github/workflows/test-x64-ubuntu-3.5.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-ubuntu-3.6.yml b/.github/workflows/test-x64-ubuntu-3.6.yml index 0e1720fe..59fadcb4 100644 --- a/.github/workflows/test-x64-ubuntu-3.6.yml +++ b/.github/workflows/test-x64-ubuntu-3.6.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-ubuntu-3.7.yml b/.github/workflows/test-x64-ubuntu-3.7.yml index d4a47098..ba5f83ac 100644 --- a/.github/workflows/test-x64-ubuntu-3.7.yml +++ b/.github/workflows/test-x64-ubuntu-3.7.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-ubuntu-3.8.yml b/.github/workflows/test-x64-ubuntu-3.8.yml index 83578181..e5abec49 100644 --- a/.github/workflows/test-x64-ubuntu-3.8.yml +++ b/.github/workflows/test-x64-ubuntu-3.8.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-ubuntu-pypy2.yml b/.github/workflows/test-x64-ubuntu-pypy2.yml index 6081960f..91320b9d 100644 --- a/.github/workflows/test-x64-ubuntu-pypy2.yml +++ b/.github/workflows/test-x64-ubuntu-pypy2.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-ubuntu-pypy3.yml b/.github/workflows/test-x64-ubuntu-pypy3.yml index 81e8dace..2f47a683 100644 --- a/.github/workflows/test-x64-ubuntu-pypy3.yml +++ b/.github/workflows/test-x64-ubuntu-pypy3.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-windows-2.7.yml b/.github/workflows/test-x64-windows-2.7.yml index 8a98de03..7947db19 100644 --- a/.github/workflows/test-x64-windows-2.7.yml +++ b/.github/workflows/test-x64-windows-2.7.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-windows-3.5.yml b/.github/workflows/test-x64-windows-3.5.yml index bf038797..d6a251b5 100644 --- a/.github/workflows/test-x64-windows-3.5.yml +++ b/.github/workflows/test-x64-windows-3.5.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-windows-3.6.yml b/.github/workflows/test-x64-windows-3.6.yml index 621aaf23..bdd32b13 100644 --- a/.github/workflows/test-x64-windows-3.6.yml +++ b/.github/workflows/test-x64-windows-3.6.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-windows-3.7.yml b/.github/workflows/test-x64-windows-3.7.yml index e3572ba9..2ec2c39c 100644 --- a/.github/workflows/test-x64-windows-3.7.yml +++ b/.github/workflows/test-x64-windows-3.7.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-windows-3.8.yml b/.github/workflows/test-x64-windows-3.8.yml index a08000f7..16415c75 100644 --- a/.github/workflows/test-x64-windows-3.8.yml +++ b/.github/workflows/test-x64-windows-3.8.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-windows-pypy2.yml b/.github/workflows/test-x64-windows-pypy2.yml index a2d05823..413b8663 100644 --- a/.github/workflows/test-x64-windows-pypy2.yml +++ b/.github/workflows/test-x64-windows-pypy2.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/.github/workflows/test-x64-windows-pypy3.yml b/.github/workflows/test-x64-windows-pypy3.yml index dff9523e..420552a2 100644 --- a/.github/workflows/test-x64-windows-pypy3.yml +++ b/.github/workflows/test-x64-windows-pypy3.yml @@ -627,6 +627,35 @@ jobs: env: RETRIES: 5 + # ------------------------------------------------------------ + # Tests: Behaviour (File Transfer) + # ------------------------------------------------------------ + + - name: "[BEHAVIOUR] File Transfer" + shell: bash + run: | + retry() { + _make=${1} + _target=${2} + _host=${3:-localhost} + _port=${4:-4444} + _wait=${5:-5} + _runs=${6:-1} + for n in $(seq ${RETRIES}); do + _port=$(( _port + n )) + echo "[${n}/${RETRIES}] make ${_target} ${_host} ${_port} ${_wait} ${_runs}"; + if "${_make}" "${_target}" "TEST_PWNCAT_HOST=${_host}" "TEST_PWNCAT_PORT=${_port}" "TEST_PWNCAT_WAIT=${_wait}" "TEST_PWNCAT_RUNS=${_runs}"; then + return 0; + fi; + sleep 10; + done; + return 1; + } + + retry make _test-behaviour-base--file_transfer + env: + RETRIES: 5 + # ------------------------------------------------------------ # Tests: Modes # ------------------------------------------------------------ diff --git a/Makefile b/Makefile index 62788ed5..c07e8603 100644 --- a/Makefile +++ b/Makefile @@ -217,6 +217,7 @@ TEST_PWNCAT_WAIT=2 TEST_PWNCAT_RUNS=1 test: _test-behaviour-quit--client test: _test-behaviour-quit--server +test: _test-behaviour-base--file_transfer test: _test-mode--local_forward test: _test-mode--remote_forward test: _test-options--nodns @@ -324,6 +325,11 @@ __test-behaviour-quit--server-201: $(INTPATH)02-behaviour-quit--server/201---udp---server_reacc---when_client_is_killed---server_command---after_client_sent_command.sh \ "$(TEST_PWNCAT_HOST)" "$(TEST_PWNCAT_PORT)" "$(TEST_PWNCAT_WAIT)" "$(TEST_PWNCAT_RUNS)" "$(TEST_PYTHON_VERSION)" +.PHONY: _test-behaviour-base--file_transfer +_test-behaviour-base--file_transfer: + tests/integration/run.sh "03-behaviour-base--file_transfer" \ + "$(TEST_PWNCAT_HOST)" "$(TEST_PWNCAT_PORT)" "$(TEST_PWNCAT_WAIT)" "$(TEST_PWNCAT_RUNS)" "$(TEST_PYTHON_VERSION)" + .PHONY: _test-mode--local_forward _test-mode--local_forward: tests/integration/run.sh "10-mode---local_forward" \ diff --git a/README.md b/README.md index cc132645..ec9a9bd1 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ -> [1] mypy type coverage (fully typed: 93.55%)
    +> [1] mypy type coverage (fully typed: 93.48%)
    > [2] Linux builds are currently only failing, due to loss of IPv6 support: Issue
    > [3] Windows builds are currently only failing, because they are simply stuck on GitHub actions: Issue @@ -153,7 +153,6 @@ tool that works on older and newer machines (hence Python 2+3 compat). Most impo ## :tada: Install - | [Pip](https://pypi.org/project/pwncat/) | [ArchLinux](https://aur.archlinux.org/packages/pwncat/) | |:-:|:-:| | [![](https://raw.githubusercontent.com/cytopia/icons/master/64x64/python.png)](https://pypi.org/project/pwncat/) | [![](https://raw.githubusercontent.com/cytopia/icons/master/64x64/archlinux.png)](https://aur.archlinux.org/packages/pwncat/) | @@ -338,31 +337,45 @@ pwncat -R 10.0.0.1:4444 everythingcli.org 3306 -u Like the original implementation of `netcat`, when using **TCP**, `pwncat` (in client and listen mode) will automatically quit, if the network connection has been terminated, properly or improperly. -In case the remote peer does not terminate the connection, or in **UDP** mode, `pwncat` will stay open. +In case the remote peer does not terminate the connection, or in **UDP** mode, `netcat` and `pwncat` will stay open. The behaviour differs a bit when STDIN is closed. + +1. `netcat`: If STDIN is closed, but connection stays open, `netcat` will stay open +2. `pwncat`: If STDIN is closed, but connection stays open, `pwncat` will close + +You can emulate the `netcat` behaviour with `--no-shutdown` command line argument. Have a look at the following commands to better understand this behaviour: ```bash -# [Valid HTTP request] Does not quit, web server keeps connection intact +# [Valid HTTP request] Quits, web server keeps connection intact, but STDIN is EOF printf "GET / HTTP/1.1\n\n" | pwncat www.google.com 80 + +# [Valid HTTP request] Does not quit, web server keeps connection intact, but STDIN is EOF +printf "GET / HTTP/1.1\n\n" | pwncat www.google.com 80 --no-shutdown ``` ```bash -# [Invalid HTTP request] Quits, because the web server closes the connection +# [Invalid HTTP request] Quits, because the web server closes the connection and STDIN is EOF printf "GET / \n\n" | pwncat www.google.com 80 ``` ```bash +# [TCP] +# Both instances will quit after successful file transfer. +pwncat -l 4444 > output.txt +pwncat localhost 4444 < input.txt + # [TCP] # Neither of both, client and server will quit after successful transfer # and they will be stuck, waiting for more input or output. # When exiting one (e.g.: via Ctrl+c), the other one will quit as well. -pwncat -l 4444 > output.txt -pwncat localhost 4444 < input.txt +pwncat -l 4444 --no-shutdown > output.txt +pwncat localhost 4444 --no-shutdown < input.txt ``` +Be advised that it is not reliable to send files via UDP ```bash -# [UDP] +# [UDP] (--no-shutdown has no effect, as this is the default behaviour in UDP) # Neither of both, client and server will quit after successful transfer # and they will be stuck, waiting for more input or output. # When exiting one (e.g.: via Ctrl+c), the other one will still stay open in UDP mode. @@ -386,6 +399,26 @@ Documentation will evolve over time. ## :computer: Usage +### Keys + +| Behaviour | ![Alt][Linux] | ![Alt][MacOS] | ![Alt][Windows] | +|----------------|---------------|---------------|-----------------| +| Quit (SIGINT) | Ctrl+c | ? | ? | +| Quit (SIGQUIT) | Ctrl+\\ | ? | ? | +| Quit (SIGQUIT) | Ctrl+4 | ? | ? | +| Quit STDIN[1] | Ctrl+d | ? | ? | +| Send | Ctrl+j | ? | ? | +| Send | Ctrl+m | ? | ? | +| Send | Enter | ? | ? | + +> [1] Only works when not using `--no-shutdown` and `--keep`. Will then shutdown it's socket for sending, signaling the remote end and EOF on its socket. + +[Linux]: https://raw.githubusercontent.com/cytopia/icons/master/64x64/linux.png "Linux" +[MacOS]: https://raw.githubusercontent.com/cytopia/icons/master/64x64/osx.png "MacOS" +[Windows]: https://raw.githubusercontent.com/cytopia/icons/master/64x64/windows.png "Windows" + +### Command line arguments + Type `pwncat -h` or click below to see all available options.
    diff --git a/bin/pwncat b/bin/pwncat index 9a5349f6..04ca8b46 100755 --- a/bin/pwncat +++ b/bin/pwncat @@ -274,6 +274,12 @@ class DsRunnerAction(object): """`[Transform.transformer]`: List of transformer functions applied before consumer.""" return self.__transformers + @property + def daemon_thread(self): + # type: () -> bool + """`bool`: Determines if the action will be started in a daemon thread.""" + return self.__daemon_thread + @property def code(self): # type: () -> Optional[Union[str, bytes, CodeType]] @@ -289,6 +295,7 @@ class DsRunnerAction(object): consumer, # type: Callable[[bytes], None] interrupts, # type: List[Callable[[], None]] transformers, # type: List[Transform] + daemon_thread, # type: bool code, # type: Optional[Union[str, bytes, CodeType]] ): # type: (...) -> None @@ -296,6 +303,7 @@ class DsRunnerAction(object): self.__consumer = consumer self.__interrupts = interrupts self.__transformers = transformers + self.__daemon_thread = daemon_thread self.__code = code @@ -3305,7 +3313,7 @@ class IONetworkScanner(IO): # https://stackoverflow.com/questions/26692284 # https://docs.python.org/3/library/signal.html#note-on-sigpipe self.__screen_lock.acquire() - print(data) + print(StringEncoder.decode(data)) try: sys.stdout.flush() except IOError: @@ -3852,12 +3860,13 @@ class Runner(object): # -------------------------------------------------------------------------- # Constructor / Destructor # -------------------------------------------------------------------------- - def __init__(self, ssig, pse): - # type: (InterruptHandler, PSEStore) -> None + def __init__(self, ssig, fast_quit, pse): + # type: (InterruptHandler, bool, PSEStore) -> None """Create a new Runner object. Args: ssig (InterruptHandler): Instance of InterruptHandler. + fast_quit (boo): On `True` do not join threads upon exit, just raise terminate and exit. pse (PSEStore): Pwncat Scripting Engine store. """ self.log = logging.getLogger(__name__) @@ -3880,6 +3889,7 @@ class Runner(object): self.__threads = {} # type: Dict[str, threading.Thread] self.__ssig = ssig + self.__fast_quit = fast_quit self.__pse = pse # -------------------------------------------------------------------------- @@ -4044,8 +4054,7 @@ class Runner(object): ), ) # Daemon threads are easier to kill - # FIXME: Only use daemon threads for Port scanner - thread.daemon = False + thread.daemon = self.__actions[key].daemon_thread # Add delay if threads cannot be started delay = 0.0 @@ -4058,10 +4067,14 @@ class Runner(object): try: # Start and break the loop upon success to go to the next thread to start thread.start() + self.log.trace( # type: ignore + "Started thread %s with daemon=%i", key, self.__actions[key].daemon_thread + ) break - except (RuntimeError, Exception): # pylint: disable=broad-except + except (RuntimeError, Exception) as err: # pylint: disable=broad-except delay += 0.1 time.sleep(delay) # Give the system some time to release open fd's + self.log.trace("Thread start delaying to %d: %s", delay, err) # type: ignore self.__threads[key] = thread # [2/3] Start available timers in a thread @@ -4104,81 +4117,61 @@ class Runner(object): def check_stop(): # type: () -> bool """Stop threads.""" - # FIXME: Use two methods here - # if non-daemin threads - do join - # if scanner do not use join! - # TODO: This is a workaround for using daemon threads. - # Python < 3.3 is unable to detect Ctrl+c signal during - # thread.join() operation in a fast loop (Port scan). - for key in self.__threads: - if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): - for interrupt in self.__actions[key].interrupts: - # [1/3] Call external interrupters - self.log.trace( # type: ignore - "Call INTERRUPT: %s.%s() for %s", - getattr(interrupt, "__self__").__class__.__name__, - interrupt.__name__, - self.__threads[key].getName(), - ) - interrupt() - # [2/3] All blocking events inside the threads are gone, now join them - try: - self.log.trace( # type: ignore - "Joining %s", self.__threads[key].getName() - ) - # NOTE: The thread.join() operating will also block the signal handler - self.__threads[key].join() + # [1/2] Fast shutdown + # For Python < 3.3 we are unable to detect Ctrl+c signal during thread.join() + # in a fast loop. Also for port-scan we will have thousands of threads that need + # to be joined and the signal handler is unable to abort the whole program during that + # time. Outcome is it would take a few minutes to abort during port scan. + # The fix is to use a "faster" method to kill the threads. + # 1. The port scanner threads need to be started in daemon mode + # 2. the fast_quit param to Runner() must be set to True + if self.__fast_quit: + if self.__ssig.has_terminate(): + self.log.trace("Fast quit - shutting down.") # type: ignore + return True + + # [2/2] Normal shutdown for non-daemon threads + else: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): + for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore - "Joined %s", self.__threads[key].getName() + "Call INTERRUPT: %s.%s() for %s", + getattr(interrupt, "__self__").__class__.__name__, + interrupt.__name__, + self.__threads[key].getName(), ) - except RuntimeError: - pass + interrupt() + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal + # handler if we try to join too many threads at once. + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): + self.log.trace("All threads dead - shutting down.") # type: ignore return True return False - # NOTE: This was for previous non-daemon threads - # for key in self.__threads: - # if not self.__threads[key].is_alive() or force: - # # TODO: How are we gonna call the stop signal now? - # # # [1/3] Inform all threads (inside) about a stop signal. - # # # All threads with non-blocking funcs will be able to stop themselves - # # self.log.trace( # type: ignore - # # "Raise stop signal: StopSignal.stop() for thread [%s]", - # # self.__threads[key].getName(), - # # ) - # # self.__actions[key].signal.signal_quit() - # # [2/3] Call external interrupters - # # These will shutdown all blocking functions inside a thread, - # # so that they are actually able to join - # for interrupt in self.__actions[key].interrupts: - # self.log.trace( # type: ignore - # "Call INTERRUPT: %s.%s() for %s", - # getattr(interrupt, "__self__").__class__.__name__, - # interrupt.__name__, - # self.__threads[key].getName(), - # ) - # interrupt() - # # [3/3] All blocking events inside the threads are gone, now join them - # try: - # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore - # # NOTE: The thread.join() operating will also block the signal handler - # #self.__threads[key].join(timeout=0.1) - # self.__threads[key].join() - # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore - # except RuntimeError as err: - # print(err) - # #pass - # # If all threads have died or force is requested, then exit - # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: - # return True - # return False while True: if check_stop(): sys.exit(0) # Need a timeout to not skyrocket the CPU - time.sleep(0.01) + if sys.version_info < (3, 3): + # Signal Handler in Python < 3.3 is broken and might not catch on + # a too small timeout invervall + time.sleep(0.5) + else: + time.sleep(0.01) # ################################################################################################# @@ -5669,7 +5662,7 @@ def main(): net_srv = IONetwork(ssig, enc, lhost, [lport], "server", srv_opts, cli_opts, sock_opts) net_cli = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(ssig, PSEStore(ssig, [net_srv, net_cli])) + run = Runner(ssig, False, PSEStore(ssig, [net_srv, net_cli])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -5677,6 +5670,7 @@ def main(): net_cli.consumer, # (send) Data parsed on to PC-CLIENT to send to TARGET [net_cli.interrupt, net_srv.interrupt], transformers, + False, None, ), ) @@ -5687,6 +5681,7 @@ def main(): net_srv.consumer, # (send) Data parsed on to PC-SERVER to back send to USER [net_cli.interrupt, net_srv.interrupt], transformers, + False, None, ), ) @@ -5704,7 +5699,7 @@ def main(): net_cli_l = IONetwork(ssig, enc, lhost, [lport], "client", srv_opts, cli_opts, sock_opts) net_cli_r = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(ssig, PSEStore(ssig, [net_cli_l, net_cli_r])) + run = Runner(ssig, False, PSEStore(ssig, [net_cli_l, net_cli_r])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -5712,6 +5707,7 @@ def main(): net_cli_r.consumer, # (send) Data parsed on to PC-CLIENT to send to TARGET [], transformers, + False, None, ), ) @@ -5722,6 +5718,7 @@ def main(): net_cli_l.consumer, # (send) Data parsed on to PC-SERVER to back send to USER [], transformers, + False, None, ), ) @@ -5731,7 +5728,7 @@ def main(): if mode == "scan": print("Scanning {} ports".format(len(ports))) net = IONetworkScanner(ssig, enc, host, args.banner, cli_opts, sock_opts) - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, True, PSEStore(ssig, [net])) for port in ports: run.add_action( "PORT-{}".format(port), @@ -5740,6 +5737,7 @@ def main(): net.consumer, # Output results [net.interrupt], [], + True, None, ), ) @@ -5764,14 +5762,15 @@ def main(): trans_recv = transformers trans_send = transformers - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, False, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, - [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err + [net.interrupt], trans_recv, + False, code_recv, ), ) @@ -5780,8 +5779,9 @@ def main(): DsRunnerAction( DsCallableProducer(mod.producer), net.consumer, # send data - [mod.interrupt], # Externally stop the produer itself + [mod.interrupt], trans_send, + False, code_send, ), ) @@ -5800,14 +5800,15 @@ def main(): trans_recv = transformers trans_send = transformers - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, False, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, - [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err + [net.interrupt], trans_recv, + False, code_recv, ), ) @@ -5816,8 +5817,9 @@ def main(): DsRunnerAction( DsCallableProducer(mod.producer), net.consumer, # send data - [net.interrupt, mod.interrupt], # Externally stop the produer itself + [mod.interrupt], trans_send, + False, code_send, ), ) diff --git a/docs/pwncat.api.html b/docs/pwncat.api.html index fc32882e..19815b3a 100644 --- a/docs/pwncat.api.html +++ b/docs/pwncat.api.html @@ -301,6 +301,12 @@

    Module pwncat

    """`[Transform.transformer]`: List of transformer functions applied before consumer.""" return self.__transformers + @property + def daemon_thread(self): + # type: () -> bool + """`bool`: Determines if the action will be started in a daemon thread.""" + return self.__daemon_thread + @property def code(self): # type: () -> Optional[Union[str, bytes, CodeType]] @@ -316,6 +322,7 @@

    Module pwncat

    consumer, # type: Callable[[bytes], None] interrupts, # type: List[Callable[[], None]] transformers, # type: List[Transform] + daemon_thread, # type: bool code, # type: Optional[Union[str, bytes, CodeType]] ): # type: (...) -> None @@ -323,6 +330,7 @@

    Module pwncat

    self.__consumer = consumer self.__interrupts = interrupts self.__transformers = transformers + self.__daemon_thread = daemon_thread self.__code = code @@ -3332,7 +3340,7 @@

    Module pwncat

    # https://stackoverflow.com/questions/26692284 # https://docs.python.org/3/library/signal.html#note-on-sigpipe self.__screen_lock.acquire() - print(data) + print(StringEncoder.decode(data)) try: sys.stdout.flush() except IOError: @@ -3879,12 +3887,13 @@

    Module pwncat

    # -------------------------------------------------------------------------- # Constructor / Destructor # -------------------------------------------------------------------------- - def __init__(self, ssig, pse): - # type: (InterruptHandler, PSEStore) -> None + def __init__(self, ssig, fast_quit, pse): + # type: (InterruptHandler, bool, PSEStore) -> None """Create a new Runner object. Args: ssig (InterruptHandler): Instance of InterruptHandler. + fast_quit (boo): On `True` do not join threads upon exit, just raise terminate and exit. pse (PSEStore): Pwncat Scripting Engine store. """ self.log = logging.getLogger(__name__) @@ -3907,6 +3916,7 @@

    Module pwncat

    self.__threads = {} # type: Dict[str, threading.Thread] self.__ssig = ssig + self.__fast_quit = fast_quit self.__pse = pse # -------------------------------------------------------------------------- @@ -4071,8 +4081,7 @@

    Module pwncat

    ), ) # Daemon threads are easier to kill - # FIXME: Only use daemon threads for Port scanner - thread.daemon = False + thread.daemon = self.__actions[key].daemon_thread # Add delay if threads cannot be started delay = 0.0 @@ -4085,10 +4094,14 @@

    Module pwncat

    try: # Start and break the loop upon success to go to the next thread to start thread.start() + self.log.trace( # type: ignore + "Started thread %s with daemon=%i", key, self.__actions[key].daemon_thread + ) break - except (RuntimeError, Exception): # pylint: disable=broad-except + except (RuntimeError, Exception) as err: # pylint: disable=broad-except delay += 0.1 time.sleep(delay) # Give the system some time to release open fd's + self.log.trace("Thread start delaying to %d: %s", delay, err) # type: ignore self.__threads[key] = thread # [2/3] Start available timers in a thread @@ -4131,81 +4144,66 @@

    Module pwncat

    def check_stop(): # type: () -> bool """Stop threads.""" - # FIXME: Use two methods here - # if non-daemin threads - do join - # if scanner do not use join! - # TODO: This is a workaround for using daemon threads. - # Python < 3.3 is unable to detect Ctrl+c signal during - # thread.join() operation in a fast loop (Port scan). - for key in self.__threads: - if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): - for interrupt in self.__actions[key].interrupts: - # [1/3] Call external interrupters - self.log.trace( # type: ignore - "Call INTERRUPT: %s.%s() for %s", - getattr(interrupt, "__self__").__class__.__name__, - interrupt.__name__, - self.__threads[key].getName(), - ) - interrupt() - # [2/3] All blocking events inside the threads are gone, now join them - try: - self.log.trace( # type: ignore - "Joining %s", self.__threads[key].getName() - ) - # NOTE: The thread.join() operating will also block the signal handler - self.__threads[key].join() + # [1/2] Fast shutdown + # For Python < 3.3 we are unable to detect Ctrl+c signal during thread.join() + # in a fast loop. Also for port-scan we will have thousands of threads that need + # to be joined and the signal handler is unable to abort the whole program during that + # time. Outcome is it would take a few minutes to abort during port scan. + # The fix is to use a "faster" method to kill the threads. + # 1. The port scanner threads need to be started in daemon mode + # 2. the fast_quit param to Runner() must be set to True + if self.__fast_quit: + if self.__ssig.has_terminate(): + self.log.trace("Fast quit - shutting down.") # type: ignore + return True + + # [2/2] Normal shutdown for non-daemon threads + else: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): + for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore - "Joined %s", self.__threads[key].getName() + "Call INTERRUPT: %s.%s() for %s", + getattr(interrupt, "__self__").__class__.__name__, + interrupt.__name__, + self.__threads[key].getName(), ) +<<<<<<< HEAD except RuntimeError: pass +======= + interrupt() + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal + # handler if we try to join too many threads at once. + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass +>>>>>>> Fix quit behaviour with signalling # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): + self.log.trace("All threads dead - shutting down.") # type: ignore return True return False - # NOTE: This was for previous non-daemon threads - # for key in self.__threads: - # if not self.__threads[key].is_alive() or force: - # # TODO: How are we gonna call the stop signal now? - # # # [1/3] Inform all threads (inside) about a stop signal. - # # # All threads with non-blocking funcs will be able to stop themselves - # # self.log.trace( # type: ignore - # # "Raise stop signal: StopSignal.stop() for thread [%s]", - # # self.__threads[key].getName(), - # # ) - # # self.__actions[key].signal.signal_quit() - # # [2/3] Call external interrupters - # # These will shutdown all blocking functions inside a thread, - # # so that they are actually able to join - # for interrupt in self.__actions[key].interrupts: - # self.log.trace( # type: ignore - # "Call INTERRUPT: %s.%s() for %s", - # getattr(interrupt, "__self__").__class__.__name__, - # interrupt.__name__, - # self.__threads[key].getName(), - # ) - # interrupt() - # # [3/3] All blocking events inside the threads are gone, now join them - # try: - # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore - # # NOTE: The thread.join() operating will also block the signal handler - # #self.__threads[key].join(timeout=0.1) - # self.__threads[key].join() - # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore - # except RuntimeError as err: - # print(err) - # #pass - # # If all threads have died or force is requested, then exit - # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: - # return True - # return False while True: if check_stop(): sys.exit(0) # Need a timeout to not skyrocket the CPU - time.sleep(0.01) + if sys.version_info < (3, 3): + # Signal Handler in Python < 3.3 is broken and might not catch on + # a too small timeout invervall + time.sleep(0.5) + else: + time.sleep(0.01) # ################################################################################################# @@ -5696,7 +5694,7 @@

    Module pwncat

    net_srv = IONetwork(ssig, enc, lhost, [lport], "server", srv_opts, cli_opts, sock_opts) net_cli = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(ssig, PSEStore(ssig, [net_srv, net_cli])) + run = Runner(ssig, False, PSEStore(ssig, [net_srv, net_cli])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -5704,6 +5702,7 @@

    Module pwncat

    net_cli.consumer, # (send) Data parsed on to PC-CLIENT to send to TARGET [net_cli.interrupt, net_srv.interrupt], transformers, + False, None, ), ) @@ -5714,6 +5713,7 @@

    Module pwncat

    net_srv.consumer, # (send) Data parsed on to PC-SERVER to back send to USER [net_cli.interrupt, net_srv.interrupt], transformers, + False, None, ), ) @@ -5731,7 +5731,7 @@

    Module pwncat

    net_cli_l = IONetwork(ssig, enc, lhost, [lport], "client", srv_opts, cli_opts, sock_opts) net_cli_r = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(ssig, PSEStore(ssig, [net_cli_l, net_cli_r])) + run = Runner(ssig, False, PSEStore(ssig, [net_cli_l, net_cli_r])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -5739,6 +5739,7 @@

    Module pwncat

    net_cli_r.consumer, # (send) Data parsed on to PC-CLIENT to send to TARGET [], transformers, + False, None, ), ) @@ -5749,6 +5750,7 @@

    Module pwncat

    net_cli_l.consumer, # (send) Data parsed on to PC-SERVER to back send to USER [], transformers, + False, None, ), ) @@ -5758,7 +5760,7 @@

    Module pwncat

    if mode == "scan": print("Scanning {} ports".format(len(ports))) net = IONetworkScanner(ssig, enc, host, args.banner, cli_opts, sock_opts) - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, True, PSEStore(ssig, [net])) for port in ports: run.add_action( "PORT-{}".format(port), @@ -5767,6 +5769,7 @@

    Module pwncat

    net.consumer, # Output results [net.interrupt], [], + True, None, ), ) @@ -5791,14 +5794,15 @@

    Module pwncat

    trans_recv = transformers trans_send = transformers - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, False, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, - [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err + [net.interrupt], trans_recv, + False, code_recv, ), ) @@ -5807,8 +5811,9 @@

    Module pwncat

    DsRunnerAction( DsCallableProducer(mod.producer), net.consumer, # send data - [mod.interrupt], # Externally stop the produer itself + [mod.interrupt], trans_send, + False, code_send, ), ) @@ -5827,14 +5832,15 @@

    Module pwncat

    trans_recv = transformers trans_send = transformers - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, False, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, - [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err + [net.interrupt], trans_recv, + False, code_recv, ), ) @@ -5843,8 +5849,9 @@

    Module pwncat

    DsRunnerAction( DsCallableProducer(mod.producer), net.consumer, # send data - [net.interrupt, mod.interrupt], # Externally stop the produer itself + [mod.interrupt], trans_send, + False, code_send, ), ) @@ -6703,7 +6710,7 @@

    Functions

    net_srv = IONetwork(ssig, enc, lhost, [lport], "server", srv_opts, cli_opts, sock_opts) net_cli = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(ssig, PSEStore(ssig, [net_srv, net_cli])) + run = Runner(ssig, False, PSEStore(ssig, [net_srv, net_cli])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -6711,6 +6718,7 @@

    Functions

    net_cli.consumer, # (send) Data parsed on to PC-CLIENT to send to TARGET [net_cli.interrupt, net_srv.interrupt], transformers, + False, None, ), ) @@ -6721,6 +6729,7 @@

    Functions

    net_srv.consumer, # (send) Data parsed on to PC-SERVER to back send to USER [net_cli.interrupt, net_srv.interrupt], transformers, + False, None, ), ) @@ -6738,7 +6747,7 @@

    Functions

    net_cli_l = IONetwork(ssig, enc, lhost, [lport], "client", srv_opts, cli_opts, sock_opts) net_cli_r = IONetwork(ssig, enc, host, ports, "client", srv_opts, cli_opts, sock_opts) # Create Runner - run = Runner(ssig, PSEStore(ssig, [net_cli_l, net_cli_r])) + run = Runner(ssig, False, PSEStore(ssig, [net_cli_l, net_cli_r])) run.add_action( "TRANSMIT", DsRunnerAction( @@ -6746,6 +6755,7 @@

    Functions

    net_cli_r.consumer, # (send) Data parsed on to PC-CLIENT to send to TARGET [], transformers, + False, None, ), ) @@ -6756,6 +6766,7 @@

    Functions

    net_cli_l.consumer, # (send) Data parsed on to PC-SERVER to back send to USER [], transformers, + False, None, ), ) @@ -6765,7 +6776,7 @@

    Functions

    if mode == "scan": print("Scanning {} ports".format(len(ports))) net = IONetworkScanner(ssig, enc, host, args.banner, cli_opts, sock_opts) - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, True, PSEStore(ssig, [net])) for port in ports: run.add_action( "PORT-{}".format(port), @@ -6774,6 +6785,7 @@

    Functions

    net.consumer, # Output results [net.interrupt], [], + True, None, ), ) @@ -6798,14 +6810,15 @@

    Functions

    trans_recv = transformers trans_send = transformers - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, False, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, - [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err + [net.interrupt], trans_recv, + False, code_recv, ), ) @@ -6814,8 +6827,9 @@

    Functions

    DsRunnerAction( DsCallableProducer(mod.producer), net.consumer, # send data - [mod.interrupt], # Externally stop the produer itself + [mod.interrupt], trans_send, + False, code_send, ), ) @@ -6834,14 +6848,15 @@

    Functions

    trans_recv = transformers trans_send = transformers - run = Runner(ssig, PSEStore(ssig, [net])) + run = Runner(ssig, False, PSEStore(ssig, [net])) run.add_action( "RECV", DsRunnerAction( DsCallableProducer(net.producer), # receive data mod.consumer, - [net.interrupt, mod.interrupt], # Also force the prod. to stop on net err + [net.interrupt], trans_recv, + False, code_recv, ), ) @@ -6850,8 +6865,9 @@

    Functions

    DsRunnerAction( DsCallableProducer(mod.producer), net.consumer, # send data - [net.interrupt, mod.interrupt], # Externally stop the produer itself + [mod.interrupt], trans_send, + False, code_send, ), ) @@ -8682,7 +8698,7 @@

    Instance variables

    class DsRunnerAction -(producer, consumer, interrupts, transformers, code) +(producer, consumer, interrupts, transformers, daemon_thread, code)

    A type-safe data structure for Action functions for the Runner class.

    @@ -8720,6 +8736,12 @@

    Instance variables

    """`[Transform.transformer]`: List of transformer functions applied before consumer.""" return self.__transformers + @property + def daemon_thread(self): + # type: () -> bool + """`bool`: Determines if the action will be started in a daemon thread.""" + return self.__daemon_thread + @property def code(self): # type: () -> Optional[Union[str, bytes, CodeType]] @@ -8735,6 +8757,7 @@

    Instance variables

    consumer, # type: Callable[[bytes], None] interrupts, # type: List[Callable[[], None]] transformers, # type: List[Transform] + daemon_thread, # type: bool code, # type: Optional[Union[str, bytes, CodeType]] ): # type: (...) -> None @@ -8742,6 +8765,7 @@

    Instance variables

    self.__consumer = consumer self.__interrupts = interrupts self.__transformers = transformers + self.__daemon_thread = daemon_thread self.__code = code

    Instance variables

    @@ -8774,6 +8798,20 @@

    Instance variables

    return self.__consumer +
    var daemon_thread
    +
    +

    bool: Determines if the action will be started in a daemon thread.

    +
    + +Expand source code + +
    @property
    +def daemon_thread(self):
    +    # type: () -> bool
    +    """`bool`: Determines if the action will be started in a daemon thread."""
    +    return self.__daemon_thread
    +
    +
    var interrupts

    [List[Callable[[], None]]]: List of interrupt functions for the producer/consumer.

    @@ -10781,7 +10819,7 @@

    Args

    # https://stackoverflow.com/questions/26692284 # https://docs.python.org/3/library/signal.html#note-on-sigpipe self.__screen_lock.acquire() - print(data) + print(StringEncoder.decode(data)) try: sys.stdout.flush() except IOError: @@ -10836,7 +10874,7 @@

    Methods

    # https://stackoverflow.com/questions/26692284 # https://docs.python.org/3/library/signal.html#note-on-sigpipe self.__screen_lock.acquire() - print(data) + print(StringEncoder.decode(data)) try: sys.stdout.flush() except IOError: @@ -13076,7 +13114,7 @@

    Instance variables

    class Runner -(ssig, pse) +(ssig, fast_quit, pse)

    Runner class that takes care about putting everything into threads.

    @@ -13085,6 +13123,8 @@

    Args

    ssig : InterruptHandler
    Instance of InterruptHandler.
    +
    fast_quit : boo
    +
    On True do not join threads upon exit, just raise terminate and exit.
    pse : PSEStore
    Pwncat Scripting Engine store.
    @@ -13098,12 +13138,13 @@

    Args

    # -------------------------------------------------------------------------- # Constructor / Destructor # -------------------------------------------------------------------------- - def __init__(self, ssig, pse): - # type: (InterruptHandler, PSEStore) -> None + def __init__(self, ssig, fast_quit, pse): + # type: (InterruptHandler, bool, PSEStore) -> None """Create a new Runner object. Args: ssig (InterruptHandler): Instance of InterruptHandler. + fast_quit (boo): On `True` do not join threads upon exit, just raise terminate and exit. pse (PSEStore): Pwncat Scripting Engine store. """ self.log = logging.getLogger(__name__) @@ -13126,6 +13167,7 @@

    Args

    self.__threads = {} # type: Dict[str, threading.Thread] self.__ssig = ssig + self.__fast_quit = fast_quit self.__pse = pse # -------------------------------------------------------------------------- @@ -13290,8 +13332,7 @@

    Args

    ), ) # Daemon threads are easier to kill - # FIXME: Only use daemon threads for Port scanner - thread.daemon = False + thread.daemon = self.__actions[key].daemon_thread # Add delay if threads cannot be started delay = 0.0 @@ -13304,10 +13345,14 @@

    Args

    try: # Start and break the loop upon success to go to the next thread to start thread.start() + self.log.trace( # type: ignore + "Started thread %s with daemon=%i", key, self.__actions[key].daemon_thread + ) break - except (RuntimeError, Exception): # pylint: disable=broad-except + except (RuntimeError, Exception) as err: # pylint: disable=broad-except delay += 0.1 time.sleep(delay) # Give the system some time to release open fd's + self.log.trace("Thread start delaying to %d: %s", delay, err) # type: ignore self.__threads[key] = thread # [2/3] Start available timers in a thread @@ -13350,81 +13395,66 @@

    Args

    def check_stop(): # type: () -> bool """Stop threads.""" - # FIXME: Use two methods here - # if non-daemin threads - do join - # if scanner do not use join! - # TODO: This is a workaround for using daemon threads. - # Python < 3.3 is unable to detect Ctrl+c signal during - # thread.join() operation in a fast loop (Port scan). - for key in self.__threads: - if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): - for interrupt in self.__actions[key].interrupts: - # [1/3] Call external interrupters - self.log.trace( # type: ignore - "Call INTERRUPT: %s.%s() for %s", - getattr(interrupt, "__self__").__class__.__name__, - interrupt.__name__, - self.__threads[key].getName(), - ) - interrupt() - # [2/3] All blocking events inside the threads are gone, now join them - try: + # [1/2] Fast shutdown + # For Python < 3.3 we are unable to detect Ctrl+c signal during thread.join() + # in a fast loop. Also for port-scan we will have thousands of threads that need + # to be joined and the signal handler is unable to abort the whole program during that + # time. Outcome is it would take a few minutes to abort during port scan. + # The fix is to use a "faster" method to kill the threads. + # 1. The port scanner threads need to be started in daemon mode + # 2. the fast_quit param to Runner() must be set to True + if self.__fast_quit: + if self.__ssig.has_terminate(): + self.log.trace("Fast quit - shutting down.") # type: ignore + return True + + # [2/2] Normal shutdown for non-daemon threads + else: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): + for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore - "Joining %s", self.__threads[key].getName() - ) - # NOTE: The thread.join() operating will also block the signal handler - self.__threads[key].join() - self.log.trace( # type: ignore - "Joined %s", self.__threads[key].getName() + "Call INTERRUPT: %s.%s() for %s", + getattr(interrupt, "__self__").__class__.__name__, + interrupt.__name__, + self.__threads[key].getName(), ) +<<<<<<< HEAD except RuntimeError: pass +======= + interrupt() + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal + # handler if we try to join too many threads at once. + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass +>>>>>>> Fix quit behaviour with signalling # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): + self.log.trace("All threads dead - shutting down.") # type: ignore return True return False - # NOTE: This was for previous non-daemon threads - # for key in self.__threads: - # if not self.__threads[key].is_alive() or force: - # # TODO: How are we gonna call the stop signal now? - # # # [1/3] Inform all threads (inside) about a stop signal. - # # # All threads with non-blocking funcs will be able to stop themselves - # # self.log.trace( # type: ignore - # # "Raise stop signal: StopSignal.stop() for thread [%s]", - # # self.__threads[key].getName(), - # # ) - # # self.__actions[key].signal.signal_quit() - # # [2/3] Call external interrupters - # # These will shutdown all blocking functions inside a thread, - # # so that they are actually able to join - # for interrupt in self.__actions[key].interrupts: - # self.log.trace( # type: ignore - # "Call INTERRUPT: %s.%s() for %s", - # getattr(interrupt, "__self__").__class__.__name__, - # interrupt.__name__, - # self.__threads[key].getName(), - # ) - # interrupt() - # # [3/3] All blocking events inside the threads are gone, now join them - # try: - # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore - # # NOTE: The thread.join() operating will also block the signal handler - # #self.__threads[key].join(timeout=0.1) - # self.__threads[key].join() - # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore - # except RuntimeError as err: - # print(err) - # #pass - # # If all threads have died or force is requested, then exit - # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: - # return True - # return False while True: if check_stop(): sys.exit(0) # Need a timeout to not skyrocket the CPU - time.sleep(0.01) + if sys.version_info < (3, 3): + # Signal Handler in Python < 3.3 is broken and might not catch on + # a too small timeout invervall + time.sleep(0.5) + else: + time.sleep(0.01)

    Methods

    @@ -13647,8 +13677,7 @@

    Args

    ), ) # Daemon threads are easier to kill - # FIXME: Only use daemon threads for Port scanner - thread.daemon = False + thread.daemon = self.__actions[key].daemon_thread # Add delay if threads cannot be started delay = 0.0 @@ -13661,10 +13690,14 @@

    Args

    try: # Start and break the loop upon success to go to the next thread to start thread.start() + self.log.trace( # type: ignore + "Started thread %s with daemon=%i", key, self.__actions[key].daemon_thread + ) break - except (RuntimeError, Exception): # pylint: disable=broad-except + except (RuntimeError, Exception) as err: # pylint: disable=broad-except delay += 0.1 time.sleep(delay) # Give the system some time to release open fd's + self.log.trace("Thread start delaying to %d: %s", delay, err) # type: ignore self.__threads[key] = thread # [2/3] Start available timers in a thread @@ -13707,81 +13740,66 @@

    Args

    def check_stop(): # type: () -> bool """Stop threads.""" - # FIXME: Use two methods here - # if non-daemin threads - do join - # if scanner do not use join! - # TODO: This is a workaround for using daemon threads. - # Python < 3.3 is unable to detect Ctrl+c signal during - # thread.join() operation in a fast loop (Port scan). - for key in self.__threads: - if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): - for interrupt in self.__actions[key].interrupts: - # [1/3] Call external interrupters - self.log.trace( # type: ignore - "Call INTERRUPT: %s.%s() for %s", - getattr(interrupt, "__self__").__class__.__name__, - interrupt.__name__, - self.__threads[key].getName(), - ) - interrupt() - # [2/3] All blocking events inside the threads are gone, now join them - try: - self.log.trace( # type: ignore - "Joining %s", self.__threads[key].getName() - ) - # NOTE: The thread.join() operating will also block the signal handler - self.__threads[key].join() + # [1/2] Fast shutdown + # For Python < 3.3 we are unable to detect Ctrl+c signal during thread.join() + # in a fast loop. Also for port-scan we will have thousands of threads that need + # to be joined and the signal handler is unable to abort the whole program during that + # time. Outcome is it would take a few minutes to abort during port scan. + # The fix is to use a "faster" method to kill the threads. + # 1. The port scanner threads need to be started in daemon mode + # 2. the fast_quit param to Runner() must be set to True + if self.__fast_quit: + if self.__ssig.has_terminate(): + self.log.trace("Fast quit - shutting down.") # type: ignore + return True + + # [2/2] Normal shutdown for non-daemon threads + else: + for key in self.__threads: + if not self.__threads[key].is_alive() or self.__ssig.has_terminate(): + for interrupt in self.__actions[key].interrupts: + # [1/3] Call external interrupters self.log.trace( # type: ignore - "Joined %s", self.__threads[key].getName() + "Call INTERRUPT: %s.%s() for %s", + getattr(interrupt, "__self__").__class__.__name__, + interrupt.__name__, + self.__threads[key].getName(), ) +<<<<<<< HEAD except RuntimeError: pass +======= + interrupt() + # [2/3] All blocking events inside the threads are gone, now join them + try: + self.log.trace( # type: ignore + "Joining %s", self.__threads[key].getName() + ) + # NOTE: The thread.join() operating will also block the signal + # handler if we try to join too many threads at once. + self.__threads[key].join() + self.log.trace( # type: ignore + "Joined %s", self.__threads[key].getName() + ) + except RuntimeError: + pass +>>>>>>> Fix quit behaviour with signalling # If all threads are done, also stop if not all([self.__threads[key].is_alive() for key in self.__threads]): + self.log.trace("All threads dead - shutting down.") # type: ignore return True return False - # NOTE: This was for previous non-daemon threads - # for key in self.__threads: - # if not self.__threads[key].is_alive() or force: - # # TODO: How are we gonna call the stop signal now? - # # # [1/3] Inform all threads (inside) about a stop signal. - # # # All threads with non-blocking funcs will be able to stop themselves - # # self.log.trace( # type: ignore - # # "Raise stop signal: StopSignal.stop() for thread [%s]", - # # self.__threads[key].getName(), - # # ) - # # self.__actions[key].signal.signal_quit() - # # [2/3] Call external interrupters - # # These will shutdown all blocking functions inside a thread, - # # so that they are actually able to join - # for interrupt in self.__actions[key].interrupts: - # self.log.trace( # type: ignore - # "Call INTERRUPT: %s.%s() for %s", - # getattr(interrupt, "__self__").__class__.__name__, - # interrupt.__name__, - # self.__threads[key].getName(), - # ) - # interrupt() - # # [3/3] All blocking events inside the threads are gone, now join them - # try: - # self.log.trace("Joining %s", self.__threads[key].getName())# type: ignore - # # NOTE: The thread.join() operating will also block the signal handler - # #self.__threads[key].join(timeout=0.1) - # self.__threads[key].join() - # self.log.trace("Joined %s", self.__threads[key].getName()) # type: ignore - # except RuntimeError as err: - # print(err) - # #pass - # # If all threads have died or force is requested, then exit - # if not all([self.__threads[key].is_alive() for key in self.__threads]) or force: - # return True - # return False while True: if check_stop(): sys.exit(0) # Need a timeout to not skyrocket the CPU - time.sleep(0.01) + if sys.version_info < (3, 3): + # Signal Handler in Python < 3.3 is broken and might not catch on + # a too small timeout invervall + time.sleep(0.5) + else: + time.sleep(0.01)
    @@ -16338,9 +16356,10 @@

    DsIOS

  • DsRunnerAction

    -