解码基于Socket.io的WebSocket负载:Wireshark抓包分析求助
解码Socket.io的WebSocket掩码负载步骤
首先,我们分三步来搞定这个问题:先解码WebSocket的掩码,再处理压缩(你的帧启用了permessage-deflate),最后解析Socket.io的协议格式。
1. 基础:解码WebSocket掩码负载
客户端发送的WebSocket帧会用4字节的掩码密钥对负载进行异或加密,解码规则很直接:
- 提取掩码密钥:你的帧里是
435cfdf7,转成字节数组就是[0x43, 0x5C, 0xFD, 0xF7] - 提取掩码后的负载字节:把Wireshark里的
2*(\312OJ\005\000转成原始字节(比如\312是八进制,对应十六进制0xCA,\005是0x05,\000是0x00,最终字节数组是b'2*(\xcaOJ\x05\x00') - 逐字节异或:对于负载的第
i个字节,解码后的字节 = 掩码字节 XOR 掩码密钥的第i%4个字节
你可以用这段Python代码快速完成这一步:
mask_key = bytes.fromhex('435cfdf7') masked_payload = bytes(b'2*(\xcaOJ\x05\x00') decoded_compressed = bytearray() for i, b in enumerate(masked_payload): decoded_compressed.append(b ^ mask_key[i % 4])
2. 处理permessage-deflate压缩
注意到你的WebSocket帧里Reserved: 0x4,这表示启用了permessage-deflate扩展(WebSocket的压缩机制),所以第一步解码后的字节是压缩过的,需要解压缩才能得到原始数据。
用zlib库处理就行,注意要设置wbits=-15(因为permessage-deflate的压缩数据不带zlib头):
import zlib try: decoded_uncompressed = zlib.decompress(decoded_compressed, wbits=-15) decoded_str = decoded_uncompressed.decode('utf-8') print("原始Socket.io数据:", decoded_str) except Exception as e: print("解压缩失败,可能是压缩参数不匹配:", str(e))
3. 解析Socket.io数据包格式
Socket.io在WebSocket之上定义了自己的协议,解码后的字符串格式很清晰:
- 第一个字符是数据包类型(数字):
0: 连接握手数据(包含sid、pingInterval等)1: 断开连接2: 事件(最常见,格式为2["事件名", 参数1, 参数2...])3: 确认响应4: 错误信息5/6: 二进制事件/确认
比如如果解码后得到2["chat message", "Hello Socket.io"],就表示这是一个chat message事件,参数是Hello Socket.io。你可以用JSON解析后面的内容:
import json if decoded_str.startswith('2'): event_data = json.loads(decoded_str[1:]) print(f"事件名称:{event_data[0]}") print(f"事件参数:{event_data[1:]}")
总结
你的情况因为启用了permessage-deflate压缩,所以比普通的WebSocket解码多了一步解压缩。按照上面的步骤,你就能得到客户端发送给Socket.io服务器的原始数据了。
内容的提问来源于stack exchange,提问作者Haoxi Tan
相关产品推荐
相关产品推荐

