SMB共享取pcap流量包:攻击溯源与恶意载荷提取修复实战
2026/9/16 6:29:40 网站建设 项目流程

如果你在靶场考核或者应急演练里遇到过这种开局:一台被控主机开着 SMB 共享,里面躺着一个 pcap 流量包,任务描述只有一句话——“还原攻击者做了什么”。别急着用 Wireshark 从头翻包,这不是一道简单的“打开文件看流量”的题。真正要走的链路其实是:通过 SMB 共享把流量包取回来,确认 pcap 的完整性和捕获位置,再从噪声极大的协议洪流里定位攻击会话,最后把攻击者藏在流量里的传输载荷完整地抠出来——甚至修复成可以直接做样本分析的二进制文件。这套路径我在实际项目里反复用过,也在好几套靶场题里见过同款套路,这篇文章就把完整过程拆开讲,从挂载共享、校验 pcap,到 Wireshark 会话筛选、攻击时间线还原,再到分片、编码、截断三类载荷修复场景,每一步都会给出能直接复现的命令和过滤器,适合正在刷靶场、准备应急响应考核,或者刚转向安全分析方向、想系统掌握流量取证的同学。

1. 从靶场 SMB 共享取包:挂载、校验与概况摸底

1.1 连接 SMB 共享这一步的常见卡点

靶场里通常会给一台“已经被攻陷”的 Windows 主机,攻击者为了传文件,开了 SMB 共享,pcap 就在共享目录下。我在 Linux 分析机上一般先探测共享列表,不会直接蒙路径:

smbclient -L //192.168.31.100 -U hacker

如果靶场只给了 guest 或者空口令,可以显式加-U guest%或者-U hacker%密码。看到共享名之后,再进入目录下载文件:

smbclient //192.168.31.100/shared -U hacker -W WORKGROUP smb: \> dir smb: \> get capture_2024.pcap smb: \> exit

我这里拿到的 pcap 是一个 180MB 左右的抓包文件,文件名带着抓取日期,明显是攻击者自己抓的或者靶场设计者模拟的“受害主机视角流量”。除了 smbclient,也可以直接把共享挂载到本地,适合后面还要从共享里继续翻其他文件的情况:

sudo mkdir -p /mnt/evidence sudo mount -t cifs //192.168.31.100/shared /mnt/evidence -o username=hacker,password=123456,vers=2.0

实际测试中两个问题最常见:一是mount error(112): Host is down,优先检查是否禁用了 SMB1,以及防火墙 445 端口是否可达;二是在靶场里密码带特殊字符时 shell 容易转义出错,建议把密码写进credentials=/root/.smbcred文件。如果平时用 impacket 更多,也可以直接用impacket-smbclient,它能指定本地端口,在某些 NAT 环境下比挂载更省事:

impacket-smbclient 'hacker:123456@192.168.31.100'

取包这一步看起来简单,但它决定了后续分析质量。我之前见过有人直接在 Windows 分析机上用\\ip\share打开共享,再把 pcap 拖到桌面,结果文件因为 SMB 缓存问题只有 0 字节。所以只要条件允许,我都会用命令行工具下载,然后立刻做哈希校验。

1.2 拿到 pcap 后先别急着打开

Wireshark 直接双击打开大文件确实流畅,但分析前先做三个基础校验,能省掉后面大量返工。

首先是文件类型和哈希:

file capture_2024.pcap sha256sum capture_2024.pcap

拿到哈希有两个作用:一是确认下载过程没有截断,二是后面如果从流量里提取出样本,可以和原始哈希对比,判断提取是否完整。其次是看包的数量和时间跨度,用 capinfos 一眼就能看完:

capinfos capture_2024.pcap

我这次跑出来的几个关键字段列在下面:

字段分析意义
File size180 MB属于中大型流量,需要明确阶段再深挖
Capture duration06:32:11跨度较长,攻击可能分多个阶段
Number of packets1,284,556百万级包,手动翻页不现实
Data byte rate65 kbps流量不大,低频 C2 特征明显
EncapsulationEthernet可以解析二层 MAC 和 VLAN 标签

看到这个时间跨度我基本就有底了:拿到的不是某个瞬间的抓包,而是主机被控后一段完整的“带外通信记录”。这样的 pcap 里大概率同时存在横向扫描、凭据尝试、载荷投递、C2 心跳几类行为,分析重点就应该放在“时间阶段划分”上,而不是漫无目的地看协议列表。

提示:有些靶场拿到的 pcap 文件名很随意,比如1.pcaptrace.pcap,不要被误导,先看 capinfos 输出的封装类型和丢包信息。如果封装类型是 Linux cooked capture,说明这个包是在 Linux 主机上抓的,和题面里“受害机是 Windows”矛盾时,就要警惕流量是镜像过来的。

1.3 用协议统计给流量先做一次“CT 扫描”

打开 Wireshark 后,我做的第一件事不是看包列表,而是看Statistics -> Protocol Hierarchy。这个面板能按协议树展示流量占比,几秒钟就能确定哪些协议值得跟:

  • 如果看到 HTTP 占比超过 20%,说明攻击者很可能直接用了明文 HTTP 做载荷传输,提取样本会非常顺利;
  • 如果 TLS 占比很高但 HTTP 几乎为零,那后门通信十有八九是加密的,后面要考虑从进程内存里找 keylog,或者在受害机上抓执行时的环境变量;
  • 如果 SMB 占比很高,则要重点关注文件共享行为里是否存在通过admin$IPC$进行的横向移动。

我这次的结果里,TCP 占绝对大头,HTTP 只占很小比例,但 SMB2 有 400 多个包,一下子把矛盾点引到了文件共享上。再打开Statistics -> Endpoints,看 IPv4 标签页,很快就能排出一个可疑的外部 IP:45.143.xx.xx,和内部 192.168.31.100 之间建立了大量长连接,而这些连接里最活跃的端口不是 80,而是 8443。到这里就已经可以从“流量概况”阶段切入到“会话筛选”阶段了。

2. 用 Wireshark 把攻击链从流量里挑出来

2.1 先看会话矩阵,定位“谁在跟谁说话”

流量分析最容易犯的错就是一上来就盯着数据包列表看,看到哪个包可疑就点哪个,结果被各种 ARP、广播和 TCP 重传干扰。正确做法是先建立会话矩阵:Statistics -> Conversations,把 TCP 和 UDP 标签页都看一遍。

这个矩阵里最有价值的信息是三个维度:会话总时长、上下行字节比、包数量。比如内部主机和外网 IP 之间有 4000 多个包,但单方向流量很小,这就是典型的 C2 心跳;而如果内网两台主机之间有大量 SMB 写请求,那大概率是横向移动中的文件投递。

我当时在 TCP Conversations 里按“Packets”排序,发现 192.168.31.100 和外网 45.143.xx.xx 的 8443 端口会话包数排第三,但持续时间最长,单个包平均只有 65 字节,符合低频心跳特征。再用过滤器把它固定下来:

ip.addr == 192.168.31.100 && tcp.port == 8443

此时包列表就干净多了,能看到每过 30 秒左右客户端就会发一个长度极其接近的 TCP 数据包,服务端很快回一个 40 字节左右的 ACK。这种规律性单包交互,正是后门通信的典型画像。

2.2 把攻击链拆成四个阶段

有了 IP 和端口的“主线”,再从时间维度把流量拆成阶段。我的习惯是把Statistics -> IO Graph打开,纵轴用数据包数量,横轴按 5 分钟粒度统计,能明显看到几个“脉冲式”的峰值:

  • 第一阶段是扫描探测,集中在最开始的 15 分钟,SYN 包大量出现;
  • 第二阶段是漏洞利用和载荷投放,表现为短暂但集中几个大包;
  • 第三阶段是 C2 心跳,整个时间段内低频稳定存在;
  • 第四阶段可能还有一次横向移动,表现为 SMB 会话突然活跃。

这里要特别熟悉几个过滤器,它们比手动翻包快得多:

分析目标显示过滤器
定位扫描源tcp.flags.syn == 1 && tcp.flags.ack == 0
定位 HTTP 明文请求http.request
定位 DNS 查询行为dns.flags.response == 0
定位 TLS 握手阶段tls.handshake.type == 1
定位 SMB 写文件行为smb2.cmd == 9
只看包含数据载荷的包tcp.len > 0

我注意到扫描阶段源 IP 集中在 192.168.31.50,而后面建立 8443 连接的又是 192.168.31.100,说明攻击者从某一台跳板机打进了受害主机,然后又从受害主机回连外部 C2。这个时间顺序放在最终报告里,本身就是一条完整入侵链。

2.3 加密流量不是死路:TLS 会话的合法解密思路

当 pcap 里大量流量是 TLS 加密时,很多人会直接放弃。但靶场和真实应急里,只要条件合适,加密流量是可以解开的。Wireshark 支持预主密钥日志文件,也就是浏览器或其他 TLS 客户端把每个会话的随机数和主密钥记录下来。实际操作中,如果靶场给了一个keylog.log文件(很多时候放在受害主机的临时目录或 SMB 共享里),只需要在Edit -> Preferences -> Protocols -> TLS中把(Pre)-Master-Secret log filename指向它,Wireshark 会自动解密后续的所有 TLS 流量。

我这里没有直接拿到 keylog,但观察到 TLS 握手里的 Server Name Indication 字段反复出现一个域名的子域:update.microsoft-helper[.]com。这个域名一看就不是微软官方,先用过滤器把所有 SNI 提出来:

tls.handshake.extensions_server_name

然后看 DNS 解析历史,发现这个域名解析结果多次变化,典型的恶意域名随机解析行为。即使看不到加密内容,仅凭 SNI、证书、握手时间间隔,也能把“加密通道”标记为恶意行为的证据。在最终报告里,我把 SNI、证书签发者、TLS 版本三项作为“加密通信指纹”单独列出,证明攻击者通过 TLS 通道隐蔽回连。

3. 溯源攻击者的证据链:时间线、IP 与行为指纹

3.1 用时间线把独立事件串成攻击故事

流量包里每个包单独看都没有意义,但把时间戳串起来,就能成为攻击者作案全过程的一条时间线。Wireshark 的 IO Graph 再加过滤器,可以分段还原:

第一阶段我筛出了 192.168.31.50 对目标网段发起 SYN 扫描,扫描目标是 192.168.31.0/24 全段常见端口。用下面的命令统计源 IP 和目的端口,确认扫描行为来自哪台机器:

tshark -r capture_2024.pcap -Y "tcp.flags.syn == 1 && tcp.flags.ack == 0" -T fields -e ip.src -e ip.dst -e tcp.dstport | sort | uniq -c | sort -rn | head -20

第二阶段是漏洞利用。流量里出现大量指向 192.168.31.100 的 HTTP 请求,路径集中在/index.php/upload/,并且有几次请求体积明显偏大。在 Wireshark 里直接定位http.request && ip.dst == 192.168.31.100,可以看到请求体中包含 base64 编码字符串,长度在 2KB 以上。这个特征配合当时的环境,基本可以判断是 Web 层面的漏洞利用加文件上传。

第三阶段是权限维持。攻击者成功上传后,受害主机开始向外网 45.143.xx.xx 的 8443 端口发起连接,并且之后每小时都有固定间隔的小包产生。这里重点看 TCP 会话的持续时间和包间隔:

tcp.port == 8443 && tcp.len > 0

3.2 攻击者的微特征:UA、频率与命令特征

流量取证里最容易被忽略的,是攻击者 HTTP 请求头和心跳包里的“微特征”。比如这个靶场里,攻击者请求恶意文件时使用的 User-Agent 是Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36,看起来和正常浏览器无差别,但它的 Accept-Language 头永远排在最后,而且从未加载过页面里的图片资源。这个差异说明了自动化工具调用,而不是真实浏览器行为。

另一个微特征是心跳包的数据载荷长度。正常情况下,TCP 会分段传输数据,但 C2 心跳通常由客户端单次 write 发出,长度固定。我提取了 8443 端口所有 TSL/应用数据段长度,发现大多数落在 45~55 字节区间,少数达到 1200 字节左右——后者很可能就是攻击者下发指令的“命令包”或者回传的“结果包”。从这里能反推攻击者的指令频率和被控端的响应节奏。

再用 tshark 输出每个 TCP 流的元信息:

tshark -r capture_2024.pcap -q -z conv,tcp

会话矩阵里能看出 45.143.xx.xx 与 192.168.31.100 的连接持续了 6 小时 17 分钟,期间上下行包数比接近 1:1,说明交互式 shell 或轮询型后门。如果只发生一次文件下载,上下行比例往往差距悬殊,不会这样均匀。

3.3 溯源报告怎么组织证据

对这次分析的结论,我在输出报告时没有把所有流量头尾不拉地贴出来,而是按“攻击源头 → 攻击路径 → 后门会话 → 载荷落盘”四条线组织证据:

  1. 攻击源头:192.168.31.50(内网跳板机)发起扫描和 Web 利用,对应 pcap 前 3000 个包;
  2. 攻击路径:通过 HTTP 上传脚本到/upload/,随后执行并回连;
  3. 后门会话:45.143.xx.xx:8443 的长连接,心跳间隔约 30 秒,SNI 为恶意域名;
  4. 载荷落盘:受害主机通过 SMB 共享拉取了后续文件(或者攻击者上传了文件),这部分流量在 SMB2 写请求中体现。

每一条证据都要对应 pcap 中具体时间戳和数据包编号,这样复盘的人和评审专家都能快速定位原始数据。流量分析报告的最终价值不是“我找到了一个可疑 IP”,而是“我证明了从哪台机器、在什么时间、用什么方法、完成了哪些操作”。

4. 从混杂流量中抠出恶意传输载荷并修复

4.1 追踪 TCP 流提取原始字节

最直接的提取方式是 Wireshark 的Follow TCP Stream。在包含 HTTP 上传或下载的包上右键,选择Follow -> TCP Stream,然后在弹窗里把 Show data 设置为 Raw,另存为即可。但要提醒一句:大部分情况下,直接保存出来的文件并不是那个干净的可执行文件,而是“HTTP 响应头 + 文件数据”的混合体,甚至还会带上 chunked 分块的长度标记。

所以我通常用 tshark 直接把 HTTP 响应里的http.file_data字段单独导出。这个字段是 Wireshark 解复用 TCP 流之后重组出的 HTTP body,理论上拿到的就是载荷主体:

tshark -r capture_2024.pcap -Y "http.response" -T fields -e http.file_data | xxd -r -p > payload.bin

这里的关键是xxd -r -p,因为http.file_data默认以十六进制字符串输出,需要转回二进制。如果文件是 Web 上传请求里的二进制内容,过滤器就换成http.request,字段同样用http.file_data。做完这步,再用file payload.bin看文件类型。我这次提取出的文件头是MZ,也就是说“直接得到了一个 Windows 可执行文件”,但这只是最理想的情况,更多时候还需要修复。

4.2 SMB 对象导出与文件段重组

如果 pcap 里载荷是通过 SMB 共享传输的,那就不能用 HTTP 那套办法了。Wireshark 在File -> Export Objects菜单下其实有 SMB/SMB2 两个选项,它们可以把共享会话中传输的完整文件直接导出,省去手动按偏移量重组数据的步骤。

实际操作中我遇到过导出的文件可以打开,但文件内容中间有大段00填充,说明抓包过程中有报文丢失,或者 SMB 写请求和读请求没有配对完整。这时候可以手工按smb2.cmd == 8(读)或smb2.cmd == 9(写)过滤,把关注的 TCP 流二进制数据用 tshark 导出:

tshark -r capture_2024.pcap -Y "tcp.stream eq 7" -w stream7.pcap

然后还在 Wireshark 里看这个流的 Follow TCP Stream,按 Raw 保存。保存下来的文件往往带着 SMB2 头部字段,需要用 010 Editor 或者 HxD 手动切掉各个 SMB 头,保留 payload 区段。更省事的方法是直接在 Export Objects 里保存,Wireshark 重组这些头部的正确率比较高。

提示:SMB 会话中同名文件如果被覆盖写,Export Objects 里可能只导出最后一个版本。取证时务必先看smb2.cmd == 9写请求的次数、写入偏移和文件大小,判断是否存在多次写入覆盖,否则你修好的样本可能不是攻击者最初投递的那一版。

4.3 载荷修复的三类常见情况

修载荷没有统一标准,核心思路是“找回原始文件在传输中被破坏和编码掉的字节”。我用一个表把最常见的情况和修复手段列清楚:

损坏/编码场景特征修复方案
文件前带 HTTP 响应头文件头不是 MZ/ELF,而是HTTP/1.1 200 OK用 010 Editor 或 xxd 查找真实文件头偏移,再从该偏移截取数据
chunked 分块传输文件内容里穿插十六进制长度行和\r\n用 tshark 的http.file_data字段直接取重组 body;或写脚本去除分块标记
Base64 编码文件内容全是字母数字和+/=file识别为 ASCII textbase64 -d payload.b64 > payload.bin,如果带 URL 编码,先替换%2B+
SMB 写入偏移错乱导出的文件中间有超大段00,文件大小与真实不符FileOffset重排多个 Write Request 的 payload

我那次提取的是一个“带 HTTP 响应头 + chunked 分块”的复合情况。Follow TCP Stream存下来的 stream.bin 前 900 字节是 HTTP 头,后面每隔一段就出现\r\n\r\n和数字长度行。先用 hexdump 定位到第一个真实文件头偏移,再把数据截出来,接着用一段 Python 按 CRLF 分隔解析 chunk 长度,把有效数据拼接后写入新的 bin 文件。

import re data = open('stream.bin', 'rb').read() # 假设已完成文件头偏移裁剪,得到 chunks_raw chunks_raw = data[offset:] body = b'' pos = 0 while pos < len(chunks_raw): # 读取 chunk-size 行,直到遇到 line_end = chunks_raw.index(b'\r\n', pos) chunk_size = int(chunks_raw[pos:line_end], 16) pos = line_end + 2 if chunk_size == 0: break body += chunks_raw[pos:pos + chunk_size] pos += chunk_size + 2 with open('payload_fixed.bin', 'wb') as f: f.write(body)

注意,在 HTTP/1.1 的 chunked 编码里,每块数据之后还会跟一个\r\n,所以 pos 的偏移要跳过。用这个脚本修完后,file payload_fixed.bin终于输出PE32 executable (GUI) Intel 80386,整个提取修复流程才算是闭环。

4.4 修复后的载荷识别与验证

载荷修好不代表结束,还要验证它是不是完整的原文件。验证分三层:

第一层是哈希比对。下载原始 pcap 时我们已经有了sha256sum,但那个哈希是针对 pcap 文件的,不是针对载荷的。所以修复后的样本要单独算一次哈希,看是否和流量中另一段文件比对值一致(有些恶意软件会在 C2 协议里下发文件的 MD5/SHA1)。如果 pcap 里没有现成哈希,就去 VirusTotal 或者本地病毒库查,确认这个样本是已知家族还是未知样本。

第二层是字符串和导入表分析。对修复出的 PE 文件跑一次strings,重点过滤 IP、域名、URL、注册表、互斥体名:

strings payload_fixed.bin | grep -E "(45\.143|http|\.com|Mutex|Run)" | head -50

如果修复正确,C2 地址和 pcap 里看到的 45.143.xx.xx、恶意域名会对上,说明“pcap 里的回连流量”和“被投放的载荷”形成了完整的证据闭环。

第三层是动态验证。在隔离虚拟机里运行样本,观察是否回连相同地址。这个步骤在靶场里可能超纲,但对真实应急响应来说最关键,因为只有验证了样本行为,才能确认 pcap 中观察到的 TLS 长连接确实是由该样本产生的。跑沙箱时记得先给虚拟机打快照,避免样本破坏分析环境。

5. 实战排错与工具链收尾技巧

5.1 Wireshark 常见“显示异常”背后的真实原因

很多初学者在分析 pcap 时会遇到一个疑问:“为什么我只能看到 520 字节的数据,明明应用层文件很大?”这个问题我在热词里也看到了,说明不是个例。根本原因通常有两种:

第一种是抓包时的 snaplen(抓包长度)被设置得太小。比如抓包工具默认每个包捕获 65535 字节,但如果为了节省空间设置了-s 520,那么每个超过 520 字节的包都会被截断。这种 pcap 里的包,Wireshark 只能看到前 520 字节,后面的载荷永远无法恢复。判断方法是在包列表里看Frame的 “Frame length on wire” 和 “Captured length” 是否一致,如果 wire 长度远大于 captured length,就是抓包阶段截断了。

第二种是 TCP 分段问题。一个 8KB 的 HTTP 响应被拆成 6 个 TCP 段,每个段大约 1460 字节,在包列表里看起来“数据只有 1460 字节”是正常的。必须开启 TCP 重组才能看到完整应用层数据。如果发现Follow TCP Stream显示的数据不完整,检查Edit -> Preferences -> Protocols -> TCP里的Allow subdissector to reassemble TCP streamsReassemble out-of-order segments两个选项是否勾选。默认是勾选的,但有些精简配置文件会把它关掉。

5.2 tshark 命令行与批处理提升效率

到分析后期,尤其是 pcap 很大、需要反复试过滤器时,我会从 Wireshark 切到 tshark,因为命令行能快速输出统计结果,还能把数据导入 Python 做进一步处理。下面几个命令是我每次流量取证都要用的:

# 查看协议统计,快速判断重点 tshark -r capture_2024.pcap -q -z io,stat,60 # 统计端口会话数,找出热点端口 tshark -r capture_2024.pcap -q -z conv,tcp # 导出所有 HTTP 请求 URI tshark -r capture_2024.pcap -Y "http.request" -T fields -e http.host -e http.request.uri | sort -u # 筛选出不符合常规的 DNS 查询名 tshark -r capture_2024.pcap -Y "dns.flags.response == 0" -T fields -e dns.qry.name | sort | uniq -c | sort -rn | head -50 # 导出特定 TCP 流的原始数据 tshark -r capture_2024.pcap -q -z follow,tcp,raw,7

follow,tcp,raw,7里的7是 TCP stream 编号,根据 Wireshark 窗口左下角或者tcp.stream eq 7过滤器确定。这个命令在网络取证里相当于一键导出流内容,省去了 Wireshark 图形界面里反复右键另存为的时间。

另一个比较实用的批处理思路是:把 pcap 按 IP 对拆分成多个小文件,避免单个 pcap 太大导致 Wireshark 卡顿。比如针对某个 C2 地址:

tshark -r capture_2024.pcap -Y "ip.addr == 45.143.xx.xx" -w c2_only.pcap

拆分之后再打开,响应速度会快很多。

5.3 安全收尾和后续扩展方向

靶场和真实应急里的流量取证,最后一步往往是“清场”。pcap 里可能有大量受害主机真实 IP、账号口令、内网地址,写报告前要脱敏,尤其是对外分享时不能直接粘贴原始包。恶意样本更不能放在共享目录里随便传播,分析完最好在隔离虚拟机里压缩加密存档,或者直接上传到沙箱平台做检测,不要在宿主机留副本。我自己习惯的做法是单独建一个带密码的压缩包,文件名里标注时间和样本哈希,方便日后回溯。

如果你想把这次流量取证的能力再往上推一层,后续可以朝两个方向扩展:一是自动化,把 tshark 的输出接进 Python 的pysharkdpkt,批量提取 IOCs 并生成威胁情报格式;二是从单包分析走向“全流量留存系统”,在一个长期运行的网络出口上做持续性的 pcap 留存,再配合定期任务扫描 C2 心跳特征,这样即使攻击者行为只在某个时段出现,也能被流量平台捞出来。

我在实际做这类题时最大的体会是:Wireshark 过滤器语法只是工具,真正的分析能力是“把流量里的时间、IP、协议特征、文件内容组合成一条可验证的故事线”。从 SMB 共享里取出 pcap 只是起点,之后每一步都在追问:攻击者为什么用了这个协议、为什么在这个时间点发这个包、这个载荷修复后长什么样。顺着这三个问题一步步走,无论靶场题怎么变,最后都能落到一个能被证据支撑的结论上。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询