如何用Python实现Wireshark的数据包字节层含义解析功能?
实现点击十六进制字节显示协议层含义的方案
核心思路
要实现类似Wireshark的字节映射功能,核心是完成两个关键环节:
- 让解析工具正确识别所有协议层(而非将后续层当作Raw负载)
- 建立全局字节位置到协议层字段含义的映射关系
解决Scapy协议识别问题
Scapy默认仅解析常见协议,遇到自定义/小众协议时会将后续数据标记为Raw层。解决方法是手动绑定协议或自定义解析层:
自定义协议层示例
如果是基于TCP/UDP的自定义协议,可编写Scapy Layer子类并绑定到对应端口:
from scapy.all import Packet, bind_layers, TCP, ByteField, ShortField, StrField class CustomAppProtocol(Packet): name = "CustomAppProtocol" # 按协议定义字段,需与实际字节结构匹配 fields_desc = [ ByteField("protocol_version", 0x02), ByteField("message_type", 0x00), ShortField("payload_len", None), StrField("payload", "") ] # 绑定到TCP的目标/源端口(示例为8080) bind_layers(TCP, CustomAppProtocol, dport=8080) bind_layers(TCP, CustomAppProtocol, sport=8080)
完成绑定后,Scapy解析时会自动将对应端口的TCP负载识别为自定义协议层,而非Raw。
字节位置到协议字段的映射实现
基于你已有的层信息数组(layer_name/layer_len/layer_start)和高亮字节数组,可按以下步骤实现映射:
1. 预存各层字段的偏移与含义
解析数据包时,遍历每个协议层,记录层内每个字段的起始偏移、长度、含义。例如Eth层的dst字段起始偏移0、长度6,含义为目的MAC地址。
2. 字节位置匹配逻辑
当点击某个全局字节位置时:
- 通过层信息数组判断该字节所属的协议层(对比
layer_start和layer_len) - 计算字节在层内的偏移:
层内偏移 = 全局位置 - layer_start - 遍历该层的字段列表,找到包含该偏移的字段,返回字段含义
映射函数示例
def get_byte_field_detail(packet, global_byte_pos, layer_info_list): # 定位字节所属的协议层 target_layer_info = None for info in layer_info_list: start = info["layer_start"] end = start + info["layer_len"] if start <= global_byte_pos < end: target_layer_info = info break if not target_layer_info: return "字节不属于已识别的协议层" # 获取Scapy解析后的对应层对象 target_layer = None for layer in packet.layers(): if layer.name == target_layer_info["layer_name"]: target_layer = layer break if not target_layer: return "未找到对应协议层的解析结果" # 匹配层内字段 layer_offset = global_byte_pos - target_layer_info["layer_start"] current_offset = 0 for field in target_layer.fields_desc: field_size = field.get_size(target_layer) if current_offset <= layer_offset < current_offset + field_size: field_value = getattr(target_layer, field.name) return (f"层: {target_layer_info['layer_name']}\n" f"字段: {field.name}\n" f"含义: {field.name}(值: {field_value})\n" f"层内偏移: {layer_offset}(字段内偏移: {layer_offset - current_offset})") current_offset += field_size return "该字节为层内填充/未定义扩展字段"
跨语言备选方案
如果Python库无法满足需求,可采用以下方案:
- C++ + libpcap:直接基于libpcap解析数据包,自定义协议解析逻辑,精准控制字段偏移与含义映射
- TShark命令行解析:通过
tshark -r input.pcap -T pdml导出包含字段偏移、长度、含义的PDML格式数据,再解析XML内容完成字节映射。示例代码:
import subprocess import xml.etree.ElementTree as ET def get_field_info_from_tshark(pcap_path, packet_num, global_byte_pos): # 导出指定数据包的PDML格式数据 cmd = [ "tshark", "-r", pcap_path, "-T", "pdml", "-c", "1", "-J", "*", f"-Y", f"frame.number == {packet_num}" ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: return "解析失败" root = ET.fromstring(result.stdout) for field in root.findall(".//field"): pos = field.get("pos") size = field.get("size") if not (pos and size): continue field_start = int(pos) field_end = field_start + int(size) if field_start <= global_byte_pos < field_end: layer = field.get("showname").split(":")[0] name = field.get("name") desc = field.get("showname") return f"层: {layer}\n字段: {name}\n含义: {desc}\n字节范围: {field_start}-{field_end-1}" return "未找到对应字段"
内容的提问来源于stack exchange,提问作者Ayah Abdel-Ghani
相关产品推荐
相关产品推荐

