研发协作
分析未知网络协议时如何抓包、识别结构并编写解析器与文档
当你需要分析网络流量、理解私有协议或调试网络通信时,用抓包、协议识别、二进制解析、加密分析与主动测试来逆向并记录协议。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
分析未知网络协议时如何抓包、识别结构并编通用
解决思路
- 用 Wireshark 抓包:指定网卡 `wireshark -i eth0 -k`,带过滤 `wireshark -i eth0 -k -f "port 443"`;用 tshark 写文件 `tshark -i eth0 -w capture.pcap`,环形缓冲 `tshark -i eth0 -b filesize:100000 -b files:10 -w capture.pcap`。
- 用 tcpdump 抓包:`tcpdump -i eth0 -w capture.pcap`,带过滤 `tcpdump -i eth0 port 8080 -w capture.pcap`,抓完整包 `tcpdump -i eth0 -s 0 -w capture.pcap`,实时显示 `tcpdump -i eth0 -X port 80`。
- 用中间人方式抓包:`mitmproxy --mode transparent -p 8080`,SSL/TLS 拦截 `mitmproxy --mode transparent --ssl-insecure`,导出 `mitmdump -w traffic.mitm`;Burp Suite 将浏览器代理设为 127.0.0.1:8080。
- 用 Wireshark 显示过滤器分析:如 `tcp.port == 8080`、`http.request.method == "POST"`、`ip.addr == 192.168.1.1`、`tcp.flags.syn == 1 && tcp.flags.ack == 0`、`frame contains "password"`;右键 Follow TCP/HTTP Stream 跟踪流;File > Export Objects > HTTP 导出对象;在 Preferences > Protocols > TLS 配置 (Pre)-Master-Secret log 或 RSA keys 解密。
- 用 tshark 提取字段与统计:`tshark -r capture.pcap -T fields -e ip.src -e ip.dst -e tcp.port`;统计 `tshark -r capture.pcap -q -z conv,tcp`、`tshark -r capture.pcap -q -z endpoints,ip`;过滤导出 `tshark -r capture.pcap -Y "http" -T json > http_traffic.json`;协议层级 `tshark -r capture.pcap -q -z io,phs`。
- 用 Scapy 做自定义分析:`rdpcap("capture.pcap")` 读取,遍历包检查 `haslayer(TCP)`、打印 IP/TCP 源目的与 `Raw` 载荷,按端口过滤 HTTP 包,构造并发送自定义包 `IP(dst="target")/TCP(dport=80)/Raw(load="GET / HTTP/1.1\r\n")`。
- 根据协议签名识别协议:HTTP 以 "HTTP/1." 或 "GET "/"POST " 开头,TLS/SSL 为 0x16 0x03,DNS 为 UDP 53 特定头,SMB 为 0xFF 0x53 0x4D 0x42,SSH 为 "SSH-2.0" banner,FTP 为 "220 " 响应与 "USER " 命令,SMTP 为 "220 " banner 与 "EHLO",MySQL 为 0x00 长度前缀与协议版本,PostgreSQL 为 0x00 0x00 0x00 启动长度,Redis 为 "*" RESP 数组前缀,MongoDB 为带特定头的 BSON 文档。
- 按常见头部模式推断结构:魔数/签名、版本、标志、长度、消息类型、序列号/会话 ID、载荷依次排列。
- 识别二进制协议常见结构:长度前缀消息(uint32 length、uint16 msg_type、uint8 flags、uint8 reserved、变长 payload)、TLV(uint8 type、uint16 length、value)、固定头+变长载荷(magic[4]、version、payload_len、checksum、payload)。
- 用 Python 编写协议解析器:用 `struct.unpack(">4sHHI", data[:12])` 解析头部,循环按 `12 + header.length` 偏移切分消息,按 `type/length` 循环解析 TLV 字段。
- 用 hexdump 辅助分析:按 16 字节一行输出偏移、十六进制与 ASCII 可打印字符,便于观察结构。
- 做熵分析判断加密/压缩:计算字节熵,< 6.0 可能为明文或结构化数据,6.0–7.5 可能为压缩,> 7.5 可能为加密或随机;加密特征还包括高且均匀的熵、无明显结构、长度常为块大小(AES 为 16)倍数、开头可能有 16 字节 IV。
- 分析 TLS:用 tshark 提取握手元数据 `-Y "ssl.handshake" -T fields -e ip.src -e ssl.handshake.ciphersuite`,JA3 客户端指纹 `-Y "ssl.handshake.type == 1" -T fields -e ssl.handshake.ja3`,JA3S 服务端指纹 `-Y "ssl.handshake.type == 2" -T fields -e ssl.handshake.ja3s`,证书提取 `-Y "ssl.handshake.certificate" -T fields -e x509sat.printableString`。
- 解密流量:浏览器设置 `export SSLKEYLOGFILE=/tmp/keys.log` 并在 Wireshark TLS 首选项中填入该日志;若有私钥且为 RSA 密钥交换,在 TLS > RSA keys list 中配置。
- 按模板编写自定义协议文档:包含概述、传输层(TCP/UDP、端口、加密)、消息格式(头部字段表:偏移/大小/字段/描述)、消息类型表、各类型字段表、状态机图与交互示例。
- 编写 Wireshark Lua 解析器:用 `Proto("custom", "Custom Protocol")` 定义协议,用 `ProtoField` 定义 magic/version/type/length/payload 字段,在 `dissector` 中解析头部、映射消息类型名、按长度取载荷,并用 `DissectorTable.get("tcp.port"):add(8888, proto)` 注册端口。
- 用 Boofuzz 做主动模糊测试:建立 `Session` 与 `TCPSocketConnection`,用 `s_initialize`、`s_static`、`s_word`、`s_size`、`s_block_start/end` 定义协议结构,`session.connect(s_get("HELLO"))` 后 `session.fuzz()`。
- 重放与修改流量:用 Scapy `rdpcap` 读取后按条件 `send(pkt)` 重放;修改 `pkt[Raw].load` 后删除 `pkt[IP].chksum` 与 `pkt[TCP].chksum` 以重算校验和再发送。
- 遵循分析工作流:抓取多会话多场景流量 → 识别消息起止边界 → 映射固定头与变长载荷结构 → 对比多样本识别字段 → 编写协议规范 → 实现解析器/生成器验证理解 → 用模糊测试与边界条件测试边缘情况。
- 重点寻找常见模式:消息起始魔数/签名、版本字段、长度字段(常在变长数据前)、类型/操作码字段、序列号、校验和/CRC、时间戳、会话/连接标识符。
适用边界 · 注意事项
- 目标协议使用强加密且无法获取密钥或 pre-master secret 日志时,无法解密载荷内容。
- 仅凭单个流量样本难以可靠推断字段含义,需要多会话、多场景样本对比。
- 对生产系统进行主动模糊测试或重放可能造成破坏,需在授权和隔离环境中进行。