多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

CTF流量分析实战:从pcap文件到flag提取的完整指南

CTF流量分析实战:从pcap文件到flag提取的完整指南 简介这份文档面向中职学校网络安全技能竞赛的备赛选手与指导教师聚焦网络空间安全方向的数据流量分析实战。内容围绕 B.pcapng 数据包展开涵盖数据库 flag 提取、黑客扫描主机 IP 定位、服务器内核版本识别、扫描网段命令还原、一句话木马上传文件追踪以及服务器下载文件内容还原等典型取证任务帮助读者掌握从流量包中定位关键证据的完整思路。资源包共 1 个 docx 文件大小约 3.27MB以图文解析形式呈现便于对照赛题逐步复盘。目前已有 744 人学习下载适合需要系统训练数据安全取证与流量分析技能的中职竞赛选手也可作为日常教学与赛前查漏补缺的参考材料。1. 从一个 pcap 文件说起流量分析到底在找什么手里拿到一个B.pcap双击打不开用记事本打开全是乱码这是很多人第一次接触流量分析时的真实场景。pcap 是抓包工具按时间戳逐帧落盘的二进制格式里面混着 TCP 握手、DNS 查询、HTTP 请求、TLS 握手等几十种协议的数据。流量分析要干的事就是从这个二进制黑匣子里把「谁在什么时候、跟谁、传了什么」还原出来。CTF 里常见的 flag 就藏在某条 HTTP 响应体、某个 DNS 查询域名、某段 TCP 流或者某个文件传输的载荷里。这篇笔记围绕B.pcap这类文件讲清楚用什么工具打开、按什么顺序排查、flag 可能藏在哪几类位置、以及 Windows 7 这类老环境上跑分析工具会踩什么坑。适合刚接触 CTF 流量题的新手也适合需要做日常排障的运维和开发。2. 工具选型与 pcap 文件结构为什么 Wireshark 是第一入口2.1 为什么先上 Wireshark 而不是直接写脚本拿到 pcap 的第一反应不该是写 Python 脚本去解析而是先用 Wireshark 把文件打开看一眼。原因很直接Wireshark 自带协议解析器能把二进制帧翻译成可读的协议树你不需要知道 TCP 头部第 13 个字节是什么含义它已经帮你标好了。对于B.pcap这种来源不明的文件先用 Wireshark 建立全局印象——总共多少包、涉及哪些协议、有没有明显的 HTTP 明文流量——比上来就写代码高效得多。Wireshark 的显示过滤器是核心生产力工具。几个必须记住的过滤器作用典型场景http只看 HTTP 流量找明文传输的 flagdns只看 DNS 查询flag 藏在域名里tcp.stream eq N追踪第 N 条 TCP 流还原完整会话ip.addr x.x.x.x按 IP 过滤锁定可疑主机frame contains flag载荷含关键词快速定位http.request.method POST只看 POST 请求找提交的数据frame contains flag这条过滤器值得单独说。CTF 流量题里 flag 格式通常是flag{...}直接搜字节内容能跳过大量人工翻包的时间。但要注意如果流量经过压缩或编码这条过滤器就失效了得先解码再搜。2.2 pcap 文件的字节布局与常见封装格式pcap 文件有一个 24 字节的全局头记录了魔数、版本号、时区、时间戳精度和最大帧长。魔数决定字节序0xa1b2c3d4是大端0xd4c3b2a1是小端。全局头之后是若干个包记录每个包记录有 16 字节的包头时间戳秒、微秒、抓到的长度、实际长度紧接着是链路层帧数据。链路层类型决定了帧的解析方式。最常见的两种LINKTYPE_ETHERNET值为 1以太网帧14 字节头部目的 MAC 6 字节 源 MAC 6 字节 类型 2 字节之后是 IP 包。LINKTYPE_LINUX_SLL值为 113Linux cooked capture16 字节头部常见于tcpdump在any接口抓的包。如果你用脚本解析时发现偏移对不上八成是链路层类型判断错了。Wireshark 的「统计 → 捕获文件属性」里能看到链路层类型。2.3 用 Python 做批量解析的最小代码当 pcap 文件很大、或者需要批量处理多个文件时Wireshark 的 GUI 就不够用了。Python 的scapy库是最常用的选择from scapy.all import rdpcap, TCP, Raw # 读取 pcap 文件返回包列表 packets rdpcap(B.pcap) # 遍历所有包提取 TCP 载荷中的文本 for pkt in packets: if pkt.haslayer(TCP) and pkt.haslayer(Raw): payload pkt[Raw].load # 尝试按 UTF-8 解码失败则跳过 try: text payload.decode(utf-8) if flag in text: print(f[] 发现 flag 关键词: {text[:200]}) except UnicodeDecodeError: pass这段代码的逻辑是rdpcap把整个文件读进内存返回一个包列表然后逐包检查是否有 TCP 层和 Raw 载荷层有载荷就尝试解码搜到flag就打印前 200 个字符。参数说明rdpcap的路径参数支持相对和绝对路径如果文件超过几百 MBrdpcap会吃光内存这时候要改用PcapReader做流式读取from scapy.all import PcapReader, TCP, Raw # 流式读取适合大文件 with PcapReader(B.pcap) as reader: for pkt in reader: if pkt.haslayer(Raw): data bytes(pkt[Raw].load) if bflag{ in data: print(data[:300])PcapReader是迭代器每次只加载一个包内存占用恒定。代价是不能随机访问只能顺序扫一遍。对于「找 flag」这种一次扫描的任务流式读取完全够用。注意scapy 在 Windows 7 上安装需要先装 Npcap 或 WinPcap 驱动否则rdpcap会报No libpcap provider available。Npcap 的安装包要选支持 Win7 的版本新版 Npcap 已经不支持 Win7 了。3. 按协议分层排查从 HTTP 到 DNS 再到 TCP 流还原3.1 HTTP 流量最直白的 flag 藏身处HTTP 是明文协议flag 最常出现在三个位置请求 URL、请求体、响应体。在 Wireshark 里用http过滤器筛出所有 HTTP 包然后逐个看请求行里的 URL 路径比如GET /flag_is_here.txt。POST 请求的application/x-www-form-urlencoded体比如keyflag{...}。响应体里的 HTML 或 JSONflag 可能嵌在页面内容里。如果响应体是 gzip 压缩的Wireshark 会自动解压但你要在「首选项 → Protocols → HTTP」里确认「Uncompress entity bodies」是勾选的。没勾的话看到的是乱码。导出 HTTP 对象是更快的办法Wireshark 菜单「文件 → 导出对象 → HTTP」会列出所有通过 HTTP 传输的文件包括图片、HTML、脚本。flag 可能藏在一张图片的 EXIF 里或者一个被下载的文本文件里。导出后逐个检查比在包列表里翻要快。3.2 DNS 流量flag 藏在域名里的经典套路DNS 查询是明文的查询域名和响应记录都能直接看到。CTF 里常见的套路是把 flag 拆成多段编码后作为子域名发起 DNS 查询。比如flag_part1.example.com flag_part2.example.com ...在 Wireshark 里用dns过滤器看Queries列。如果域名看起来像 Base64 或十六进制字符串就提取出来解码。用 Python 批量提取 DNS 查询名from scapy.all import rdpcap, DNS, DNSQR packets rdpcap(B.pcap) domains [] for pkt in packets: if pkt.haslayer(DNSQR): qname pkt[DNSQR].qname.decode(utf-8).rstrip(.) domains.append(qname) # 去重后打印 for d in sorted(set(domains)): print(d)DNSQR是 DNS 查询记录层qname是查询的域名。rstrip(.)去掉末尾的点因为 DNS 域名在协议里以点结尾。拿到域名列表后观察有没有异常长的子域名或者编码特征明显的字符串。还有一种变体是 DNS 隧道flag 被编码在 DNS 查询的 TXT 记录响应里。这时候要看DNSRR资源记录层而不是DNSQR。用dns.qry.type 16过滤器筛 TXT 查询。3.3 TCP 流还原处理非标准端口和分片传输有些流量不走 80 端口或者用了非标准协议HTTP 过滤器抓不到。这时候要回到 TCP 层用「追踪 TCP 流」功能手动还原会话。在 Wireshark 里右键任意一个 TCP 包选「追踪 → TCP 流」会弹出一个窗口显示这条流的完整双向数据。如果数据是分片传输的Wireshark 会自动重组但重组有超时限制。默认 TCP 重组超时是 5 秒如果分片间隔超过这个值重组会失败。可以在「首选项 → Protocols → TCP」里把「Reassemble out-of-order segments」和超时参数调大。用 Python 做 TCP 流重组的基本思路是按四元组源 IP、源端口、目的 IP、目的端口分组然后按序列号排序拼接from scapy.all import rdpcap, TCP, IP, Raw from collections import defaultdict packets rdpcap(B.pcap) streams defaultdict(list) for pkt in packets: if pkt.haslayer(TCP) and pkt.haslayer(Raw): key (pkt[IP].src, pkt[TCP].sport, pkt[IP].dst, pkt[TCP].dport) streams[key].append((pkt[TCP].seq, bytes(pkt[Raw].load))) # 按序列号排序后拼接 for key, segments in streams.items(): segments.sort(keylambda x: x[0]) data b.join(seg[1] for seg in segments) if bflag in data: print(f流 {key}: {data[:500]})这段代码用四元组做键把同一条流的所有载荷按 TCP 序列号排序后拼接。注意这里没有处理重传和重叠分片实际场景中如果存在重传拼接结果会有重复数据。更严谨的做法是维护一个按序列号索引的缓冲区遇到重叠时以先到的为准。3.4 文件传输协议从 FTP 和 SMB 里提取文件FTP 的控制通道是明文数据通道可能是明文也可能是加密的。在 Wireshark 里用ftp过滤器看控制命令ftp-data过滤器看数据通道。如果看到RETR filename命令说明有文件下载对应的数据流里就是文件内容。SMB 协议更复杂但 Wireshark 能解析。用smb2过滤器看Create Request和Read Response。导出 SMB 对象「文件 → 导出对象 → SMB」能直接拿到传输的文件。对于B.pcap这种题目如果 HTTP 和 DNS 都没找到 flag就要考虑是不是通过 FTP 或 SMB 传了一个文件flag 在文件内容里。导出文件后用file命令看类型再决定怎么打开。4. 避坑与排查Windows 7 环境下的五个血泪教训4.1 Wireshark 装不上提示缺少 kb2999226 补丁现象在 Windows 7 上安装新版 Wireshark安装程序提示需要先安装 KB2999226 更新否则无法继续。原因KB2999226 是 Windows 7 的通用 C 运行时更新新版 Wireshark 依赖的 Visual C 运行库需要这个补丁。Windows 7 默认没有集成。解决去微软官方更新目录下载对应系统架构x86 或 x64的 KB2999226 补丁安装后重启再装 Wireshark。如果系统是 Windows 7 SP1 且已经装了 KB3125574 汇总包可能已经包含这个补丁直接装 Wireshark 即可。4.2 scapy 报 No libpcap provider available现象Python 里from scapy.all import rdpcap能导入但调用rdpcap时报No libpcap provider available。原因scapy 在 Windows 上依赖 Npcap 或 WinPcap 提供底层抓包能力。只装了 Wireshark 不够Wireshark 自带的 Npcap 可能没被 scapy 识别到。解决单独安装 Npcap安装时勾选「Install Npcap in WinPcap API-compatible Mode」。如果已经装了 Wireshark 自带的 Npcap重新运行 Npcap 安装程序修复一次。Windows 7 上要用 Npcap 0.9984 或更早版本新版 Npcap 已经不支持 Win7。4.3 大文件读取时内存爆掉现象用rdpcap读一个 500MB 的 pcap 文件Python 进程内存飙到几个 GB最后被系统杀掉。原因rdpcap把整个文件的所有包一次性加载到内存每个包都被解析成 Python 对象内存占用是文件大小的 10 到 20 倍。解决改用PcapReader流式读取或者用tcpdump先按条件过滤出小文件再分析。命令行过滤# 只保留 HTTP 流量输出到新文件 tcpdump -r B.pcap -w B_http.pcap tcp port 80Windows 上没有 tcpdump 的话用 Wireshark 的editcap或tshark# 用 tshark 过滤并输出新 pcap tshark -r B.pcap -Y http -w B_http.pcap-Y是显示过滤器-w是输出文件。这样先把无关流量剔掉再用 scapy 处理小文件。4.4 时间戳乱序导致 TCP 流重组错乱现象用脚本按序列号拼接 TCP 流结果数据顺序不对flag 被截断。原因pcap 文件里的包是按抓包时间排序的不是按 TCP 序列号排序的。如果网络存在乱序抓包顺序和序列号顺序不一致。解决拼接前必须按 TCP 序列号排序不能依赖文件里的顺序。另外要注意序列号回绕超过 2^32 后归零大流量场景下需要处理回绕。简单场景下按序列号排序就够了回绕概率极低。4.5 编码问题导致 flag 搜不到现象明明在 Wireshark 里能看到类似 flag 的字符串但 Python 脚本搜flag搜不到。原因载荷不是 UTF-8 编码可能是 UTF-16、GBK 或者经过 Base64 编码。Python 默认按 UTF-8 解码遇到其他编码会抛异常或产生乱码。解决先按字节搜索不解码if bflag in payload: print(payload)字节搜索不受编码影响。如果字节搜索也找不到考虑是不是经过了 Base64 或十六进制编码。用正则匹配 Base64 特征import re # 匹配长度超过 20 的 Base64 字符串 b64_pattern re.compile(rb[A-Za-z0-9/]{20,}{0,2}) matches b64_pattern.findall(payload) for m in matches: try: decoded __import__(base64).b64decode(m) if bflag in decoded: print(decoded) except Exception: pass5. 进阶技巧用 tshark 命令行一把梭与自动化验证5.1 tshark 的批量提取能力Wireshark 的 GUI 适合交互式分析但批量处理要靠tshark。它是 Wireshark 的命令行版本安装 Wireshark 时自带。几个实用命令# 列出所有 HTTP 请求的 URL tshark -r B.pcap -Y http.request -T fields -e http.host -e http.request.uri # 提取所有 DNS 查询域名 tshark -r B.pcap -Y dns.flags.response 0 -T fields -e dns.qry.name # 导出所有 HTTP 对象到当前目录 tshark -r B.pcap --export-objects http,./output # 搜索载荷中包含 flag 的包 tshark -r B.pcap -Y frame contains flag -T fields -e frame.number -e data.text-T fields -e指定输出字段适合做管道处理。--export-objects直接导出文件比在 GUI 里点菜单快。frame contains flag是字节级搜索不受协议解析限制。5.2 用 tshark 做初步筛选再用 scapy 精处理实际工作中我一般分两步先用 tshark 按条件过滤出小文件再用 scapy 做精细解析。这样既避免了 scapy 读大文件的内存问题又保留了 Python 的灵活性。# 第一步筛出所有 TCP 载荷非空的包 tshark -r B.pcap -Y tcp.len 0 -w B_tcp_payload.pcap # 第二步用 scapy 做深度分析 python3 analyze.py B_tcp_payload.pcaptcp.len 0过滤掉纯 ACK 包只保留有数据的包。这样文件能缩小 60% 到 80%。5.3 验证 flag 是否完整的三个检查点找到疑似 flag 后别急着提交先做三个检查第一检查 flag 格式是否完整。flag{和}是否配对中间有没有被截断。如果只有前半段说明还有后续包没拼进来。第二检查是否有多个 flag 片段。有些题目把 flag 拆成多段分别放在不同的流或不同的协议层里。用tshark -r B.pcap -Y frame contains flag{ -T fields -e frame.number看有多少个包命中了开头标记。第三检查编码层数。如果 flag 内容是 Base64解码后可能还有一层十六进制。用file命令或者binwalk看解码后的数据有没有文件头特征。5.4 我自己的习惯先跑一遍自动化脚本再人工复核每次拿到新的 pcap 文件我会先跑一个固定的检查脚本把 HTTP URL、DNS 域名、TCP 载荷里的可打印字符串全部 dump 出来然后 grep 关键词。这个脚本不追求一步到位找到 flag而是把搜索空间从「几万个包」缩小到「几十行文本」。之后人工看这几十行比在 Wireshark 里翻包快得多。脚本的核心逻辑就三行遍历包、提取载荷、按可打印字符过滤。但就是这三行帮我省掉了大量重复劳动。工具是死的排查思路是活的——先广撒网把可疑数据捞出来再针对性地深挖这个习惯比记住多少条过滤器都管用。希望帮到你。本文还有配套的精品资源点击获取
返回列表