客户端输出
为了说明这个问题,下面是在客户端上运行时的代码。可以看出,第一个命令成功了(它总是成功的(,即使在返回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 ~>
服务器输出
这是我的服务器的输出。
└─$ /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客户端程序
这是我的客户代码:
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程序
这是socketserver程序(我怀疑我在这里做了什么,非常感谢帮助(
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()
客户端和服务器都有问题。
客户端使用套接字.recv()
读取数据,但当服务器输出完成时,这将在第一个命令结束时永远阻塞。它将仅在服务器关闭套接字时的EOF处返回b''
。由于服务器问题(如下(,它似乎可以工作。
服务器代码只读取一行,生成命令,发送输出,然后从handle()
返回,然后关闭连接。由于这个关闭,客户端实际上可以工作(它从recv()
获得b''
(。
要修复服务器,请循环执行readline()
,直到它在发送命令输出后返回b''
(客户端关闭的套接字(,最好是flush()
写入流。
示例服务器处理程序:
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")
while True:
line: str = self.rfile.readline()
if line == b'':
break
client_cmd: str = line.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)
self.wfile.flush()
要修复客户端和整个设置,您可能需要实现某种框架,对于客户端命令,这目前是一条换行符(因为您使用了readline(,但对于服务器输出,您需要找到一个单独的框架。