Client Output
To show the problem, here is the code in action when running on the client. As can be seen the first command succeeds (it always does) and it succeeds even in case of a faulty command by which it will return stderr.
Pwny ~>df
Filesystem 1K-blocks Used Available Use% Mounted on
udev 1895788 0 1895788 0% /dev
tmpfs 386392 1416 384976 1% /run
/dev/sda1 478612200 43470808 410755756 10% /
tmpfs 1931948 78200 1853748 5% /dev/shm
tmpfs 5120 0 5120 0% /run/lock
tmpfs 386388 60 386328 1% /run/user/1000
Pwny ~>pwd
Pwny ~>pwd
[~] Connection aborted
Pwny ~>
Server output
Here is the output from my server.
└─$ /bin/python3 /home/user/Desktop/tcpserver/socketserver.py
[*] Started server 0.0.0.0:9999
[*] 192.168.137.1:1051 connected
[~] 192.168.137.1:1051 df
TCP Client Program
This is my client code:
import socket
class TCPClient:
@staticmethod
def run(host, port, buffer_size=1024, encoding='utf-8'):
HOST = host
PORT = port
BUFFER_SIZE = buffer_size
ENCODING = encoding
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
tx: bytes = bytes(input("Pwny ~>"), ENCODING)
tx += b"\n"
if tx == b"exit":
break
else:
try:
s.sendall(tx)
full_msg: bytes = b''
while True:
msg: bytes = s.recv(BUFFER_SIZE)
if len(msg) == 0:
break
full_msg += msg
print(full_msg.decode(ENCODING))
except ConnectionAbortedError:
print("[~] Connection aborted")
except OSError:
print("[~] An OS error occurred")
if __name__ == '__main__':
tcp_client = TCPClient()
tcp_client.run(host='192.168.137.2', port=9999, buffer_size=128, encoding='utf-8')
TCP SocketServer Program
And this is the socketserver program (I suspect I'm doing something here, help greatly appreciated)
import socketserver
import subprocess
from subprocess import CompletedProcess
class ThreadingServer(socketserver.ThreadingMixIn,socketserver.TCPServer): pass
class TCPRequestHandler(socketserver.StreamRequestHandler):
def setup(self) -> None:
return super().setup()
def handle(self) -> None:
ENCODING: str = 'utf-8'
BUFFER_SIZE: int = 128
client_address: str = self.request.getpeername()[0]
client_port: int = self.request.getpeername()[1]
print(f"[*] {client_address}:{client_port} connected")
client_cmd: str = self.rfile.readline().decode(ENCODING).strip()
print(f"[~] {client_address}:{client_port} {client_cmd}")
output: CompletedProcess = subprocess.run(client_cmd,shell=True,capture_output=True)
""" Returns 0 for success and >= 1 for failure"""
if output.returncode == 0: # success
self.wfile.write(output.stdout)
else: # failure when > 0
self.wfile.write(output.stderr)
def finish(self) -> None:
return super().finish()
if __name__ == '__main__':
with ThreadingServer(('0.0.0.0',9999),TCPRequestHandler) as server:
print(f"[*] Started server {server.server_address[0]}:{server.server_address[1]}")
server.serve_forever()