recv和明文收包分析

我们CTRL+g 跳到recv 分析收包函数

发现函数会断并且收包函数返回值(收包包长)也会不断变化

那么证明recv是真正的收包函数,游戏没有重新实现该函数

我们只要分析该函数即可
在这里插入图片描述
在recv函数执行完毕以后下断

eax是包长,esi+28是包指针

我们上2个号,让另外的一个号喊话,这个号进行收包

由于收包比较频繁,基本下断就断,所以我们要下条件断

我们喊18个字节,例如“123456789123456789 ” 收包长度必然大于0x10,小于多少我们可以尝试,可以尝试0x30,0x50
在这里插入图片描述
然后下断,另外的号立刻喊话,看收到的封包长度,可以多次试验确认
在这里插入图片描述
发现是0x26
在这里插入图片描述
包内容是加密的

我们光收到加密封包是没有用的

需要对其进行解密才知道收包的具体信息

所以还要继续追封包的解密函数

那么想要解密,就需要对加密内容进行访问

我们只要对加密包下访问断,就可以找到解密的位置,当然可能不只一次解密或则拷贝,一追到底便是。
在这里插入图片描述
访问断断下以后发现了解密的位置
返回看整个函数
在这里插入图片描述
用这个解密函数就可以顺利解密了
在这里插入图片描述
图中可以清晰看到
解密后的明文喊话内容了

<think>我们之前已经对Android端Python端进行了多次修改,但问题仍然存在。现在我们需要更深入地排查问题。考虑到问题描述为“脚本还是不到”,我们需要从网络通信、数据格式、线程同步等多个方面进行彻底检查。解决方案思路:1.确保ADB端口转发正确建立。2.确保Android端Python端的Socket连接已经成功建立。3.确保Android端发送的数据格式与Python端解析格式完全匹配。4.添加详细的日志,以便于定位问题。5.考虑使用网络抓工具(如Wireshark)检查数据是否真正从Android发出(但ADB转发在本地,可能抓不到,所以主要靠日志)。6.在Python端增加超时重连机制。我们将对Android端Python端代码进行以下关键修改:Android端修改:1.在发送数据之前,记录发送的数据大小内容摘要(注意不要记录整个音频数据,避免日志过多)。2.确保在发送数据时,Socket的输出流是有效的,并且每次发送后都进行了flush。3.增加心跳机制,定期发送ping,确保连接活跃。 Python端修改:1.增加接数据的日志,记录每次接到的数据长度开头部分。2.修改数据解析逻辑,确保能够正确分割数据(使用双换行符作为分隔符)。3.增加重连机制,当连接断开时自动重连。由于之前已经提供了较完整的代码,这里我们只提供关键修改部分的代码。注意:由于问题可能出现在多个环节,我们将分别对AndroidPython代码进行增强。一、Android端关键修改:1.在发送音频数据时,增加日志记录(注意:音频数据较大,我们只记录发送的计数大小):```javaprivatevoid uploadAudioData() {//...之前的代码...try {intbytesRead= audioRecord.read(buffer,0, BUFFER_SIZE);if (bytesRead>0){//创建JSON数据JSONObjectjson =new JSONObject();json.put("type","recording");Stringbase64Data =Base64.encodeToString(buffer,0, bytesRead,Base64.NO_WRAP);json.put("data",base64Data);//发送数据synchronized(this) {if(socketWriter !=null){socketWriter.write(json.toString());socketWriter.write("\n\n");//添加双换行作为结束标识socketWriter.flush();Log.d(TAG,"成功发送音频数据,大小: "+ (json.toString().length())+ "字符");}}//...发送消息 ...}}catch (Exception e) {Log.e(TAG,"发送音频数据失败",e);sendErrorMessage("发送音频数据失败: "+ e.getMessage());}}```2.增加心跳机制,定期发送ping(在连接建立后开始,断开后停止):```java//在MainActivity中增加privateScheduledExecutorService heartbeatScheduler;//在连接成功时启动心跳privatevoid startHeartbeat() {if(heartbeatScheduler !=null){heartbeatScheduler.shutdownNow();}heartbeatScheduler =Executors.newSingleThreadScheduledExecutor();heartbeatScheduler.scheduleAtFixedRate(() ->{if (isServerRunning &&clientSocket!= null&& !clientSocket.isClosed()){sendControlPacket("ping");}},1,5,TimeUnit.SECONDS);//每5秒发送一次}//在关闭连接时停止心跳privatevoid stopHeartbeat() {if(heartbeatScheduler !=null){heartbeatScheduler.shutdownNow();heartbeatScheduler =null;}}//在startServer方法中,当客户端连接成功时调用startHeartbeat()//在closeSocket()方法中调用stopHeartbeat()```3.在连接建立断开时,增加日志记录。二、Python端关键修改:1.增强接数据的日志,记录接到的字节数以及开头部分(为了避免日志过大,只记录开头少量字节):```pythonclass AudioReceiver(threading.Thread):defrun(self):# ...之前的代码 ...whileself.running:try:data =self.sock.recv(8192)ifnot data:logger.warning("连接已断开")breaklogger.debug(f"到数据:{len(data)}字节,前20字节:{data[:20]}")#...处理数据...```2.确保数据分割逻辑正确,我们使用双换行符`\n\n`作为分隔符。注意:由于数据是二进制流,我们使用`b'\n\n'`来查找。3.修改数据处理逻辑,确保能够正确解析JSON:```pythondefprocess_buffer(self):whileTrue:idx= self.buffer.find(b'\n\n')ifidx ==-1:breakpacket_bytes =self.buffer[:idx]self.buffer= self.buffer[idx+2:]#移除已处理的数据分隔符#尝试解析为JSONtry:packet_str =packet_bytes.decode('utf-8')try:json_data= json.loads(packet_str)#根据类型放入不同队列if json_data.get('type') =='recording':audio_packet_queue.put(packet_bytes)#注意:这里放入的是原始字节,后续处理需要再次解析logger.info(f"到音频数据,大小: {len(packet_bytes)}字节")else:control_queue.put(json_data)logger.info(f"到控制指令:{json_data}")exceptjson.JSONDecodeError:logger.warning(f"JSON解析失败,数据内容:{packet_str[:200]}...")except UnicodeDecodeError:logger.warning(f"到非UTF-8数据,大小: {len(packet_bytes)}字节")```4.在音频处理线程中,对音频进行解析:```pythonclass AudioProcessorThread(threading.Thread):def run(self):whileself.running:try:#从audio_packet_queue获取数据(原始字节)audio_packet =audio_packet_queue.get(timeout=0.5)#解析音频packet_str =audio_packet.decode('utf-8')packet =json.loads(packet_str)if packet['type'] !='recording':continueaudio_data =base64.b64decode(packet['data'])#后续处理...exceptqueue.Empty:pass```5.增加重连机制(之前已有,但需要确保其可靠性)。由于代码较长,这里只给出关键修改部分。如果问题仍然存在,请运行修改后的代码并集日志(Android的logcatPython的日志),以便进一步分析。如果上述修改后仍然无法解决问题,我们可以尝试以下额外步骤:1.在Android端,尝试发送一个简单的字符串(如"test")到Python端,看是否能到。2.在Python端,使用简单的echo服务器测试Android端是否能发送成功(排除Python端的问题)。但是,为了节省时间,我们先按照上述修改进行。由于我们之前已经提供了完整的代码,这里只提供修改的片段。如果需要完整代码,请参考之前的回复并整合这些修改。最后,请确保在AndroidManifest.xml中已经声明了网络权限:```xml<uses-permissionandroid:name="android.permission.INTERNET" />```注意:在Android9及以上版本,默认不允许明文传输,如果使用localhost通信则不受影响,但如果使用实际IP,则需要配置网络安全。由于我们使用ADB转发,所以是localhost通信,不需要额外配置。如果问题仍然存在,请提供最新的日志(Android端Python端)。由于问题描述有限,以上方案是基于常见问题的通用解决方案。以下是完整的Python端修改后的代码(含上述关键修改):</think>我理解您的问题:即使经过多次修改,Python脚本仍然无法接到Android发送的音频数据。这是一个复杂的网络通信问题,需要深入排查。我将提供一套完整的诊断解决方案,括增强的日志系统、连接验证工具备选通信方法。 ### 终极解决方案:三步诊断法 #### 第一步:Android端增强日志系统 ```java // 在MainActivity中添加详细的网络诊断日志 private void logNetworkStatus() { new Thread(() -> { while (isServerRunning) { try { String status = "网络状态: "; if (clientSocket == null) { status += "未连接"; } else { status += "已连接 - "; status += "本地端口: " + clientSocket.getLocalPort() + ", "; status += "远程地址: " + clientSocket.getInetAddress().getHostAddress() + ", "; status += "远程端口: " + clientSocket.getPort() + ", "; status += "是否关闭: " + clientSocket.isClosed(); } Log.d(TAG, status); sendNetworkMessage(status); // 发送测试数据 if (clientSocket != null && !clientSocket.isClosed()) { sendTestPacket(); } Thread.sleep(5000); // 每5秒记录一次 } catch (Exception e) { Log.e(TAG, "网络状态监控错误", e); } } }).start(); } private void sendTestPacket() { try { JSONObject testPacket = new JSONObject(); testPacket.put("type", "test"); testPacket.put("timestamp", System.currentTimeMillis()); testPacket.put("message", "Android->PC测试数据"); synchronized (this) { if (socketWriter != null) { socketWriter.write(testPacket.toString()); socketWriter.write("\n\n"); socketWriter.flush(); Log.i(TAG, "测试数据已发送"); } } } catch (Exception e) { Log.e(TAG, "发送测试数据失败", e); } } // 在onCreate方法中启动 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ...其他代码... startServer(30000); logNetworkStatus(); // 添加这一行 } ``` #### 第二步:Python端增强诊断脚本 ```python import socket import time import json import logging import threading # 配置详细日志 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler("audio_receiver_debug.log"), logging.StreamHandler() ] ) logger = logging.getLogger("AudioDebug") class NetworkDiagnostics: def __init__(self, host='localhost', port=35000): self.host = host self.port = port self.sock = None self.running = True self.last_packet_time = time.time() self.packet_count = 0 self.connection_status = "disconnected" def connect(self): """尝试连接到ADB转发的端口""" try: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.settimeout(5) self.sock.connect((self.host, self.port)) self.connection_status = "connected" logger.info(f"成功连接到 {self.host}:{self.port}") return True except Exception as e: self.connection_status = f"连接失败: {str(e)}" logger.error(f"连接失败: {e}") return False def monitor_traffic(self): """监控网络流量并记录统计信息""" buffer = bytearray() while self.running: try: # 接数据 data = self.sock.recv(4096) if not data: logger.warning("连接已断开") self.connection_status = "disconnected" break self.last_packet_time = time.time() buffer.extend(data) # 处理数据 packets = self.extract_packets(buffer) for packet in packets: self.process_packet(packet) # 记录状态 status = self.get_network_status() logger.info(status) except socket.timeout: # 检查是否超时 if time.time() - self.last_packet_time > 10: logger.warning("10秒未到数据,连接可能已断开") self.connection_status = "timeout" except Exception as e: logger.error(f"接数据错误: {e}") self.connection_status = f"error: {str(e)}" def extract_packets(self, buffer): """从缓冲区提取完整的数据""" packets = [] while True: # 查找双换行符作为结束符 idx = buffer.find(b'\n\n') if idx == -1: break packet_bytes = buffer[:idx] del buffer[:idx+2] try: # 尝试解析为JSON packet_str = packet_bytes.decode('utf-8') packets.append(packet_str) except UnicodeDecodeError: logger.warning(f"到非文本数据: {packet_bytes[:50]}...") return packets def process_packet(self, packet_str): """处理接到的数据""" try: packet = json.loads(packet_str) self.packet_count += 1 if packet.get('type') == 'test': logger.info(f"到测试数据: {packet}") elif packet.get('type') == 'recording': logger.debug(f"到音频数据 #{self.packet_count}") else: logger.info(f"到未知数据: {packet}") except json.JSONDecodeError: logger.warning(f"无效JSON数据: {packet_str[:100]}...") def get_network_status(self): """获取当前网络状态""" status = { "connection": self.connection_status, "packets_received": self.packet_count, "last_packet": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.last_packet_time)), "uptime": f"{time.time() - self.start_time:.1f}秒" } return json.dumps(status, indent=2) def start(self): """启动诊断工具""" self.start_time = time.time() if self.connect(): threading.Thread(target=self.monitor_traffic, daemon=True).start() def stop(self): """停止诊断工具""" self.running = False if self.sock: self.sock.close() if __name__ == '__main__': # 使用示例 diag = NetworkDiagnostics() diag.start() try: # 保持主线程运行 while True: time.sleep(1) except KeyboardInterrupt: diag.stop() logger.info("诊断工具已停止") ``` #### 第三步:备选通信方案(WebSocket) 如果TCP套接字仍然无法工作,改用WebSocket协议: 1. Android端添加WebSocket支持 ```gradle // 在app/build.gradle中添加依赖 dependencies { implementation 'org.java-websocket:Java-WebSocket:1.5.3' } ``` ```java // WebSocket客户端实现 import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; public class WebSocketManager { private static final String TAG = "WebSocket"; private WebSocketClient webSocketClient; private Context context; public WebSocketManager(Context context) { this.context = context; } public void connect(String serverUrl) { try { URI uri = new URI(serverUrl); webSocketClient = new WebSocketClient(uri) { @Override public void onOpen(ServerHandshake handshakedata) { Log.i(TAG, "WebSocket连接已打开"); } @Override public void onMessage(String message) { Log.d(TAG, "到消息: " + message); } @Override public void onClose(int code, String reason, boolean remote) { Log.i(TAG, "连接关闭: " + reason); } @Override public void onError(Exception ex) { Log.e(TAG, "WebSocket错误", ex); } }; webSocketClient.connect(); } catch (Exception e) { Log.e(TAG, "创建WebSocket失败", e); } } public void sendAudioData(byte[] audioData) { if (webSocketClient != null && webSocketClient.isOpen()) { String base64Data = Base64.encodeToString(audioData, Base64.NO_WRAP); JSONObject json = new JSONObject(); try { json.put("type", "audio"); json.put("data", base64Data); webSocketClient.send(json.toString()); } catch (JSONException e) { Log.e(TAG, "创建JSON失败", e); } } } public void disconnect() { if (webSocketClient != null) { webSocketClient.close(); } } } ``` 2. Python端WebSocket服务器 ```python import asyncio import websockets import json import base64 import logging logging.basicConfig(level=logging.INFO) async def audio_server(websocket, path): logging.info("客户端已连接") try: async for message in websocket: try: data = json.loads(message) if data.get('type') == 'audio': audio_data = base64.b64decode(data['data']) logging.info(f"到音频数据: {len(audio_data)}字节") # 处理音频数据... except json.JSONDecodeError: logging.warning("到非JSON消息") except websockets.exceptions.ConnectionClosed: logging.info("客户端断开连接") start_server = websockets.serve(audio_server, "localhost", 8765) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever() ``` ### 系统化诊断流程 1. **验证ADB端口转发** ```bash adb forward --list # 应该显示: tcp:35000 tcp:30000 # 测试端口是否开放 telnet localhost 35000 ``` 2. **检查Android网络状态** - 查看Android日志中的网络状态信息 - 确认测试数据是否发送成功 3. **运行Python诊断工具** ```bash python network_diagnostic.py ``` - 检查日志文件`audio_receiver_debug.log` - 查看是否到测试数据 4. **网络抓分析** ```bash # 在PC端捕获流量 tcpdump -i lo -s0 -w android_capture.pcap port 35000 # 在Android端捕获流量(需要root) tcpdump -i any -s0 -w /sdcard/capture.pcap port 30000 ``` 5. **防火墙验证** ```bash # 检查PC防火墙 sudo ufw status # 检查Android防火墙(通常无) ``` ### 常见问题终极解决方案 1. **如果ADB转发失败** ```bash # 移除所有转发 adb forward --remove-all # 重启ADB服务 adb kill-server adb start-server # 重新建立转发 adb forward tcp:35000 tcp:30000 ``` 2. **如果设备存在多个网络接口** ```java // 在Android端指定IP地址 serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress("192.168.1.100", 30000)); ``` 3. **如果存在协议不匹配** ```java // 在Android端添加协议头 String header = "AUDIO/v1.0\n"; socketWriter.write(header); ``` 4. **如果存在字节顺序问题** ```python # 在Python端处理字节顺序 import struct audio_data = struct.unpack('<h', packet)[0] # 小端序 ``` ### 最终验证步骤 1. 在AndroidPC上同时运行诊断工具 2. 检查Android是否发送测试数据 3. 检查PC是否到测试数据 4. 如果测试成功,再尝试发送音频数据 5. 如果仍然失败,切换到WebSocket方案 这些工具方法应该能彻底解决"脚本不到数据"的问题。如果经过所有这些步骤问题仍然存在,可能需要考虑硬件或操作系统级别的网络问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

douluo998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值