From 485fd76b5aff87b106ce711cc79621de7b6a68fe Mon Sep 17 00:00:00 2001 From: Tabdiukov Date: Tue, 25 Feb 2020 20:26:59 -0600 Subject: [PATCH 1/7] Serial implementation attempt --- pwintools.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/pwintools.py b/pwintools.py index 8759876..a494144 100644 --- a/pwintools.py +++ b/pwintools.py @@ -503,6 +503,88 @@ def interactive2(self): t.sock = fs t.interact() +class serialtube(serial.Serial): + def __init__( + self, port = None, baudrate = 115200, + convert_newlines = True, + bytesize = 8, parity='N', stopbits=1, xonxoff = False, + rtscts = False, dsrdtr = False, *a, **kw): + super(serialtube, self).__init__(*a, **kw) + + if port is None: + port = "COM1" + + self.convert_newlines = convert_newlines + self.conn = serial.Serial( + port = port, + baudrate = baudrate, + bytesize = bytesize, + parity = parity, + stopbits = stopbits, + timeout = 0, + xonxoff = xonxoff, + rtscts = rtscts, + writeTimeout = None, + dsrdtr = dsrdtr, + interCharTimeout = 0 + ) + + # Implementation of the methods required for tube + def recv_raw(self, numb): + if not self.conn: + raise EOFError + + with self.countdown(): + while self.conn and self.countdown_active(): + data = self.conn.read(numb) + + if data: + return data + + time.sleep(min(self.timeout, 0.1)) + + return None + + def send_raw(self, data): + if not self.conn: + raise EOFError + + if self.convert_newlines: + data = data.replace(b'\n', b'\r\n') + + while data: + n = self.conn.write(data) + data = data[n:] + self.conn.flush() + + def settimeout_raw(self, timeout): + pass + + def can_recv_raw(self, timeout): + with self.countdown(timeout): + while self.conn and self.countdown_active(): + if self.conn.inWaiting(): + return True + time.sleep(min(self.timeout, 0.1)) + return False + + def connected_raw(self, direction): + return self.conn != None + + def close(self): + if self.conn: + self.conn.close() + self.conn = None + + def fileno(self): + if not self.connected(): + self.error("A closed serialtube does not have a file number") + + return self.conn.fileno() + + def shutdown_raw(self, direction): + self.close() + class Process(windows.winobject.process.WinProcess): """ Wrapper for Windows process From e24efc45f58f9688a40f6d3ea4fb48e9b6b61b7f Mon Sep 17 00:00:00 2001 From: Tabdiukov Date: Tue, 25 Feb 2020 21:08:57 -0600 Subject: [PATCH 2/7] remove unimplemented timeout; fix error from original pwntools --- pwintools.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/pwintools.py b/pwintools.py index a494144..4ad72d6 100644 --- a/pwintools.py +++ b/pwintools.py @@ -18,6 +18,7 @@ from windows.generated_def.winstructs import * import windows.native_exec.simple_x64 as x64 +import serial try: import capstone @@ -534,14 +535,13 @@ def recv_raw(self, numb): if not self.conn: raise EOFError - with self.countdown(): - while self.conn and self.countdown_active(): - data = self.conn.read(numb) + while self.conn: + data = self.conn.read(numb) - if data: - return data + if data: + return data - time.sleep(min(self.timeout, 0.1)) + time.sleep(min(self.conn.timeout, 0.1)) return None @@ -561,11 +561,10 @@ def settimeout_raw(self, timeout): pass def can_recv_raw(self, timeout): - with self.countdown(timeout): - while self.conn and self.countdown_active(): - if self.conn.inWaiting(): - return True - time.sleep(min(self.timeout, 0.1)) + while self.conn: + if self.conn.inWaiting(): + return True + time.sleep(min(self.timeout, 0.1)) return False def connected_raw(self, direction): From f65b8c79395109e3ef8f4454f5943cc6d3171482 Mon Sep 17 00:00:00 2001 From: Tabdiukov Date: Tue, 25 Feb 2020 21:49:04 -0600 Subject: [PATCH 3/7] Unofficial pwntools-like functions for pwnintools. Why aren't they in official pwntools? --- pwintools.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pwintools.py b/pwintools.py index 4ad72d6..0bf187a 100644 --- a/pwintools.py +++ b/pwintools.py @@ -530,6 +530,32 @@ def __init__( interCharTimeout = 0 ) + + # not from original pwntools, + # why are they left unimplemented if the + # super's method are pretty good (at least as of 3.0.1) + def is_line(self, s): + if(len(s) > 0 and (s is not None)): + return True + return False + + def recvline(self): + if not self.conn: + raise EOFError + + buf = "" + while(not self.is_line(buf)): + time.sleep(0.1) + buf = self.conn.readline() + + return buf + + def sendline(self, data, flush=True): + # flush means "remove from recvline" + # how to remove from recvline? Do one recvline + self.send_raw(data.encode()+b'\r\n') + self.recvline() + # Implementation of the methods required for tube def recv_raw(self, numb): if not self.conn: From cf677af5b7283fb66c0339a413854062e2469274 Mon Sep 17 00:00:00 2001 From: Tabdiukov Date: Tue, 25 Feb 2020 21:53:45 -0600 Subject: [PATCH 4/7] add serial dependencies --- requirements.txt | 3 ++- setup.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0832917..8ab2d13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -git+git://github.com/hakril/PythonForWindows@master#egg=PythonForWindows \ No newline at end of file +git+git://github.com/hakril/PythonForWindows@master#egg=PythonForWindows +pyserial==3.0.1 #for windows XP. Otherwise use the latest version diff --git a/setup.py b/setup.py index 8387573..dd93ddc 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup PKG_NAME = "PWiNTOOLS" -VERSION = "0.3" +VERSION = "0.31" setup( @@ -16,6 +16,7 @@ py_modules=['pwintools'], install_requires=[ 'PythonForWindows==0.4', + 'pyserial==3.0.1', #for windows XP. Otherwise use the latest version ], dependency_links=[ 'git+git://github.com/hakril/PythonForWindows@master#egg=PythonForWindows-0.4', From c071d42fe636e55523fa59e13d27be13f6d609c1 Mon Sep 17 00:00:00 2001 From: Tabdiukov Date: Tue, 25 Feb 2020 21:57:08 -0600 Subject: [PATCH 5/7] add forgotten if statement --- pwintools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwintools.py b/pwintools.py index 0bf187a..ddf70c1 100644 --- a/pwintools.py +++ b/pwintools.py @@ -554,7 +554,7 @@ def sendline(self, data, flush=True): # flush means "remove from recvline" # how to remove from recvline? Do one recvline self.send_raw(data.encode()+b'\r\n') - self.recvline() + if(flush): self.recvline() # Implementation of the methods required for tube def recv_raw(self, numb): From 22a4baa1afb80f8be260c9ca09b975e25718dcbd Mon Sep 17 00:00:00 2001 From: Tabdiukov Date: Wed, 26 Feb 2020 11:41:05 -0600 Subject: [PATCH 6/7] add recvn(), recvuntil(), and recvall() functions. Add timeout supports to some of them (min used in original pwntools; I use max for timeout since it makes more sense). Minor optimisations --- pwintools.py | 59 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/pwintools.py b/pwintools.py index ddf70c1..e162f17 100644 --- a/pwintools.py +++ b/pwintools.py @@ -522,13 +522,14 @@ def __init__( bytesize = bytesize, parity = parity, stopbits = stopbits, - timeout = 0, + timeout = 0.1, xonxoff = xonxoff, rtscts = rtscts, writeTimeout = None, dsrdtr = dsrdtr, interCharTimeout = 0 ) + #assert self.can_recv_raw() # not from original pwntools, @@ -539,15 +540,20 @@ def is_line(self, s): return True return False - def recvline(self): + def recvline(self, timeout=None): + if(timeout is None): + timeout=max(self.conn.timeout, 0.1) + if not self.conn: raise EOFError buf = "" - while(not self.is_line(buf)): - time.sleep(0.1) + fin = False + while(not fin): buf = self.conn.readline() - + fin = self.is_line(buf) + if(not fin): time.sleep(timeout) + return buf def sendline(self, data, flush=True): @@ -557,7 +563,12 @@ def sendline(self, data, flush=True): if(flush): self.recvline() # Implementation of the methods required for tube - def recv_raw(self, numb): + def recv_raw(self, numb, timeout = None): + + if(timeout is None): + timeout=max(self.conn.timeout, 0.1) + + if not self.conn: raise EOFError @@ -567,10 +578,24 @@ def recv_raw(self, numb): if data: return data - time.sleep(min(self.conn.timeout, 0.1)) + time.sleep(timeout) return None + def recvn(self, n, timeout = None): + """recvn(n, timeout = None) reads exactly n bytes on the socket before timeout""" + buf = self.recv_raw(n, timeout) + if len(buf) != n: + raise(EOFError("Timeout {:s} - Incomplete read".format(self))) + return buf + + def recvuntil(self, delim, timeout = None): + """recvuntil(delim, timeout = None) reads bytes until the delim is present on the socket before timeout""" + buf = '' + while delim not in buf: + buf += self.recvn(1, timeout) + return buf + def send_raw(self, data): if not self.conn: raise EOFError @@ -586,12 +611,26 @@ def send_raw(self, data): def settimeout_raw(self, timeout): pass - def can_recv_raw(self, timeout): - while self.conn: + def can_recv_raw(self, timeout=None): + if(timeout is None): + timeout=max(self.conn.timeout, 0.1) + + if self.conn: if self.conn.inWaiting(): return True - time.sleep(min(self.timeout, 0.1)) + else: + time.sleep(timeout) + return (self.conn.inWaiting() > 0) return False + + def recvall(self, timeout=None): + if(timeout is None): + timeout=max(self.conn.timeout, 0.1) + + buf = "" + while(self.can_recv_raw(timeout)): + buf = buf + self.recvline() + return buf def connected_raw(self, direction): return self.conn != None From a66f7ae8e4a4fc972e23c4e3a7bd807bf622174a Mon Sep 17 00:00:00 2001 From: Tim A Date: Fri, 31 Jul 2020 03:36:43 +1000 Subject: [PATCH 7/7] add suggested changes; add a function that should be there? --- pwintools.py | 26 ++++++++++++++++++++------ setup.py | 1 - 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pwintools.py b/pwintools.py index e162f17..81d43e8 100644 --- a/pwintools.py +++ b/pwintools.py @@ -504,16 +504,17 @@ def interactive2(self): t.sock = fs t.interact() -class serialtube(serial.Serial): +class SerialTube(object): # you don't need serial.Serial parent since you use conn def __init__( - self, port = None, baudrate = 115200, + self, port = "COM1", baudrate = 115200, convert_newlines = True, bytesize = 8, parity='N', stopbits=1, xonxoff = False, rtscts = False, dsrdtr = False, *a, **kw): - super(serialtube, self).__init__(*a, **kw) - - if port is None: - port = "COM1" + + try: + import serial + except ImportError: + raise(ImportError("pyserial module not found :: Please pip install pyserial==3.0.1")) self.convert_newlines = convert_newlines self.conn = serial.Serial( @@ -581,6 +582,12 @@ def recv_raw(self, numb, timeout = None): time.sleep(timeout) return None + + # Not sure if it's a good idea from the "pwntools" philosophy, + # but it seems like recv() should redirect to recv_raw() + # maybe things change as Serial implementation advances? Who knows + def recv(self, numb, timeout = None): + return self.recv_raw(*args, **kwargs) def recvn(self, n, timeout = None): """recvn(n, timeout = None) reads exactly n bytes on the socket before timeout""" @@ -608,6 +615,13 @@ def send_raw(self, data): data = data[n:] self.conn.flush() + # Not sure if it's a good idea from the "pwntools" philosophy, + # but it seems like send() should redirect to send_raw() + # maybe things change as Serial implementation advances? Who knows + def send(self, data): + return self.send_raw(data) + + def settimeout_raw(self, timeout): pass diff --git a/setup.py b/setup.py index dd93ddc..3dd0d4e 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,6 @@ url = 'https://github.com/masthoon/pwintools', py_modules=['pwintools'], install_requires=[ - 'PythonForWindows==0.4', 'pyserial==3.0.1', #for windows XP. Otherwise use the latest version ], dependency_links=[