常见技术问题:在分析DDCTF2018流量包(如`misc100.pcapng`)时,Wireshark过滤`http || tcp.stream eq 0`可见HTTP响应中夹带异常二进制数据,但直接导出对象(Export Objects → HTTP)无法识别PNG——因图片被分片嵌入多个TCP流、头部被截断或混淆(如PNG魔数`\x89PNG\r\n\x1a\n`被拆分跨包),且部分数据段混杂在非HTTP协议(如DNS TXT记录或ICMP载荷)中。此外,使用`tshark -r misc100.pcapng -T fields -e data.text`提取ASCII十六进制时易丢失原始字节顺序;而盲目拼接TCP流易引入冗余控制字符或错位偏移。关键难点在于:如何准确定位所有含PNG有效载荷的数据包、自动对齐字节边界、修复缺失的文件头/尾,并验证CRC与IHDR结构完整性?这要求结合协议解析、流重组、熵值分析与PNG规范校验,而非依赖单一GUI功能。
1条回答 默认 最新
Airbnb爱彼迎 2026-05-17 09:16关注```html一、现象层:Wireshark GUI导出失效的典型表现
- 在
misc100.pcapng中应用过滤器http || tcp.stream eq 0,可见 HTTP 响应体含高熵二进制数据(如连续0x89 0x50 0x4e 0x47片段但不连续); - 右键 → Export Objects → HTTP 导出所有对象,无一被识别为 PNG(
file命令返回data或cannot open); - DNS 查询中出现异常长的 TXT 记录(如 Base64 编码的 256 字节字符串),ICMP Echo Reply 载荷含非零填充字节;
tshark -r misc100.pcapng -T fields -e data.text输出大量DATA TEXT字段,但因自动 ASCII 解码/截断导致原始字节丢失(如\x89→?)。
二、协议层:多协议载荷混杂与TCP流边界错位
DDCTF2018 misc100 的隐写设计刻意规避传统提取路径:
协议类型 载荷特征 常见陷阱 HTTP 响应体含 PNG 数据块(IDAT),但首包缺失 IHDR,末包缺失 IEND TCP 重传/乱序导致流重组后头部偏移 +3 字节 DNS TXT Base64 编码的 PNG 数据段(每条记录 ≤ 255 字节,RFC 1035 限制) Base64 补齐字符 =被丢弃,解码后长度校验失败ICMP ICMP Echo Reply 的 Data 字段含 PNG 校验字节(CRC32 of IHDR) Wireshark 默认解析为 ASCII,需手动设置 Raw视图查看十六进制三、分析层:熵值驱动+协议感知的载荷定位策略
采用多维启发式扫描替代盲目拼接:
- 熵值初筛:对每个 TCP 流/UDP 载荷计算 Shannon 熵(阈值 > 7.2 bit/byte),快速排除文本型流量;
- 魔数滑动匹配:在原始字节流中以 1-byte 步进搜索
\x89PNG\r\n\x1a\n(8 字节)及IDAT/IHDR/IEND四字节签名; - 协议上下文绑定:若某 DNS TXT 记录熵值高且含 Base64 字符集(A-Za-z0-9+/=),则提取并批量 base64 -d 验证输出是否含 PNG 签名;
- 流级偏移对齐:使用
tshark -r misc100.pcapng -qz follow,tcp,raw,0获取未解析原始流,再用 Pythonscapy按 IP/TCP 五元组聚合并去重 ACK/PSH 标志干扰。
四、修复层:PNG 结构完整性自动化重建流程
graph TD A[原始PCAP] --> B{按协议分流} B --> B1[HTTP 流:提取 raw payload] B --> B2[DNS TXT:Base64 decode] B --> B3[ICMP Data:hexdump -C] B1 --> C[滑动窗口搜索 PNG 签名位置] B2 --> C B3 --> C C --> D[按 PNG chunk 结构对齐:IHDR→IDAT×n→IEND] D --> E[补全缺失头尾:
• 插入标准 IHDR(宽/高从 IDAT 推断)
• 计算并追加合法 CRC32] E --> F[验证:pngcheck -v reconstructed.png]五、验证层:超越文件头的深度结构校验
仅恢复魔数不足以保证可渲染性,必须校验:
- IHDR 完整性:检查宽度/高度是否为非零整数、bit depth ∈ {1,2,4,8,16}、color type ∈ {0,2,3,4,6};
- IDAT 合法性:ZLIB 头部
0x78 0x9c或0x78 0xda存在,且 zlib.decompress() 不抛异常; - CRC32 重算:对每个 chunk type + data 字段执行
zlib.crc32(b'IHDR' + ihdr_data) & 0xffffffff,比对原始 chunk CRC 字段; - 像素一致性:用
PIL.Image.open()加载后检查img.size与 IHDR 是否一致,避免“假 PNG”(如伪造头但 IDAT 解压失败)。
六、工具链:生产级自动化脚本核心逻辑(Python + Scapy)
```from scapy.all import * import zlib, base64, binascii from PIL import Image from io import BytesIO def extract_png_chunks(pcap_file): pkts = rdpcap(pcap_file) candidates = [] # Step 1: HTTP payload extraction (raw, no reassembly) for pkt in pkts: if TCP in pkt and Raw in pkt[TCP]: if pkt[TCP].dport == 80 or pkt[TCP].sport == 80: payload = bytes(pkt[TCP][Raw]) if b'\x89PNG' in payload[:16]: # partial header match candidates.append(('http', payload)) # Step 2: DNS TXT decode for pkt in pkts: if DNS in pkt and pkt[DNS].ancount > 0: for rr in pkt[DNS].an: if rr.type == 16 and hasattr(rr, 'rdata') and isinstance(rr.rdata, str): try: decoded = base64.b64decode(rr.rdata.replace(' ', '')) if decoded.startswith(b'\x89PNG') or b'IDAT' in decoded: candidates.append(('dns', decoded)) except Exception: pass # Step 3: Stitch & validate full_data = b''.join([cand[1] for cand in candidates]) # ... then IHDR repair, CRC fix, pngcheck call return full_data解决 无用评论 打赏 举报- 在