You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:55:24