Files
reverse-skill/skills/field-journal/seed-011_pcap-protocol-reverse.md
T
2026-08-08 18:32:33 +08:00

4.5 KiB
Raw Blame History

[种子] PCAP 自定义二进制协议逆向

场景分类

抓包分析 / 协议逆向

目标概述

某 IoT 设备/桌面客户端走 TCP 自定义二进制协议(非 HTTP),抓到一段 PCAP,需要还原帧结构、字段含义、加密层(如有),并写一个本地 client/server 复现。

完整执行链路

  1. Wireshark 打开 PCAP,先做基础统计
    • Statistics → Conversations 看 IP/端口对
    • Statistics → I/O Graphs 看数据节奏
  2. 找出真正的应用层流(剥掉 TLS 之类标准层)
  3. 在某条 TCP 流上 → Follow → TCP Stream → 切到 RAW 模式 → 导出
  4. 二进制级观察:每帧前几字节是不是固定 magic / 长度字段?
    xxd dump.bin | head -20
    
  5. 用 hex 模式找规律:固定头、长度、TLV、CRC
  6. 写 Python 解析器(struct + scapy)一帧一帧解
  7. 同步从二进制反编译反查协议字段(IDA / Ghidra 看 send/recv 周围 struct)
  8. 验证:自己起 client 发一帧 → 服务端响应一致

踩坑记录

问题 原因 解决方案 耗时
Wireshark 不识别协议,只显示 "Data" 是私有协议,没有解析器 写 Wireshark Lua dissector 或 直接 Python 离线分析 30min
看起来无规律,每帧都不同 有压缩或加密层 用熵分析(ent dump.bin)判断是否加密;找 nonce/IV 字段 1h
长度字段算不对 长度可能是 little-endian / big-endian / 含/不含自身 找几条不同长度的帧,列方程组解出来 40min
TLS 抓到但解不了 客户端不留 SSLKEYLOGFILE 在客户端进程层 hook(Frida 抓 ssl_read/ssl_write)抓明文 1.5h
数据正确但服务端不响应 协议带递增的 seq / nonce,重放被拒 搞清楚 seq 计算方式(通常前一帧的 hash 或递增计数器) 50min

工具链发现

  • Wireshark Lua Dissector 用 < 100 行就能把私有协议变成 Wireshark 可视化
  • scapy 写 Python parser 时定义 Packet 子类即可
  • Kaitai Struct 用 YAML 描述协议结构,能生成多语言 parser(Python/Java/C++/JS),适合长期复用
  • NetworkMiner 比 Wireshark 更适合"事后取证"(自动重组文件、识别凭证)
  • ent / binwalk -E 看熵,>7.5 几乎肯定加密

关键代码/命令

scapy 自定义协议示例(TLV):

from scapy.all import *

class MyMsg(Packet):
    name = "MyProto"
    fields_desc = [
        StrFixedLenField("magic", b"\xab\xcd", 2),
        ByteField("version", 1),
        ByteField("type", 0),
        LenField("length", None, fmt="H"),     # H = uint16 BE
        XIntField("seq", 0),
        StrLenField("payload", "", length_from=lambda p: p.length - 8),
        XShortField("crc", 0),
    ]

# 解析 PCAP
pkts = rdpcap('dump.pcap')
for p in pkts:
    if TCP in p and p[TCP].dport == 9527 and p.payload:
        msg = MyMsg(bytes(p[TCP].payload))
        msg.show()

Kaitai Struct YAML(长期项目首选):

# myproto.ksy
meta:
  id: myproto
  endian: be
seq:
  - id: magic
    contents: [0xab, 0xcd]
  - id: version
    type: u1
  - id: type
    type: u1
  - id: length
    type: u2
  - id: seq_no
    type: u4
  - id: payload
    size: length - 8
  - id: crc
    type: u2

熵分析:

binwalk -E dump.bin             # 熵图
ent dump.bin                    # 数值

对本包的改进建议

  • reverse-engineering/platforms.md 增加"自定义协议逆向 4 步法"章节
  • 新增 reverse-engineering/references/kaitai-cheatsheet.md 速查
  • bootstrap manifest 增加 scapy(pip)和 binwalk

可复用的模式/脚本片段

自定义协议逆向 4 步法:

1. 看节奏(I/O 图 + Conversations 找出会话边界)
2. 找帧界(magic / length / 终止符)
3. 拆字段(固定头、长度、payload、校验)
4. 验加密(熵 + 找 nonce + 二进制反查 send 函数)

找帧长度的小技巧:

把同流的所有 PSH 包导出 → 看每个 TCP segment 的总长度,看长度字段(位置 i, i+1, i+2 都试)是否能推出 segment 长度。

进化动作

  • reverse-engineering/platforms.md 增加协议逆向章节
  • bootstrap-manifest 加 scapy / binwalk
  • 增加 Kaitai Struct 速查

环境信息

  • Kali / Ubuntu,Wireshark 4.x, Python 3.10+, scapy 2.5
  • 目标协议: 自定义 TCP 二进制(含 TLV / 长度前缀)
  • 加密层: 视情况而定(常见 AES-CTR / ChaCha20)

脱敏要求

本条目为种子数据,基于公开协议逆向方法编写,不涉及真实产品。