| name | performing-network-packet-capture-analysis |
| description | 使用 Wireshark、tshark 和 tcpdump 对网络数据包捕获(PCAP/PCAPNG)进行取证分析,重建网络通信、提取传输文件、识别恶意流量,并建立数据渗出或命令与控制活动的证据。 |
| domain | cybersecurity |
| subdomain | digital-forensics |
| tags | ["pcap","wireshark","tshark","tcpdump","network-forensics","packet-capture","protocol-analysis","traffic-analysis","pcapng","network-evidence"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
执行网络数据包捕获分析
概述
网络数据包捕获(PCAP/PCAPNG 文件)是关于网络活动的终极真相来源,为主机间通信提供无可辩驳的证据。PCAP 文件记录了网络段上传输的每一个数据包,对于涉及数据渗出、命令与控制通信、横向移动、恶意软件投递和未授权访问的取证调查至关重要。Wireshark 是交互式分析的主要工具,而 tshark 提供命令行能力以支持自动化处理和脚本编写。现代 PCAPNG 格式支持附加元数据,包括接口描述、捕获注释、精确时间戳和每数据包注释。
前置条件
- Wireshark 4.x,含协议解析器
- tshark 命令行工具(随 Wireshark 一起安装)
- tcpdump,用于捕获和基本过滤
- Python 3.8+,含 scapy 和 pyshark 库
- 充足的磁盘空间用于 PCAP 文件(可能为多 GB)
捕获技术
tcpdump
tcpdump -i eth0 -w capture.pcap
tcpdump -i eth0 -w capture_%Y%m%d_%H%M%S.pcap -C 100 -W 10
tcpdump -i eth0 host 192.168.1.100 -w host_traffic.pcap
tcpdump -i eth0 port 443 -w https_traffic.pcap
tcpdump -i eth0 'port 4444 or port 8080 or port 1337' -w suspicious.pcap
Wireshark 显示过滤器
# HTTP 流量
http
# DNS 查询
dns
# SMB 文件传输
smb2
# 特定 IP 通信
ip.addr == 192.168.1.100
# 失败的 TCP 连接
tcp.flags.syn == 1 && tcp.flags.ack == 0
# 大数据传输(潜在的数据渗出)
tcp.len > 1000
# 按端口过滤特定协议
tcp.port == 4444
# TLS 握手(提取 SNI)
tls.handshake.type == 1
# HTTP POST 请求
http.request.method == "POST"
# 到可疑 TLD 的 DNS 查询
dns.qry.name contains ".xyz" or dns.qry.name contains ".top"
# 信标检测(定时间隔)
frame.time_delta_displayed > 55 && frame.time_delta_displayed < 65
tshark 分析命令
tshark -r capture.pcap -Y "http.request" -T fields -e http.host -e http.request.uri
tshark -r capture.pcap -Y "dns.flags.response == 0" -T fields -e dns.qry.name | sort -u
tshark -r capture.pcap --export-objects http,exported_files/
tshark -r capture.pcap --export-objects smb,smb_files/
tshark -r capture.pcap -z io,phs
tshark -r capture.pcap -z conv,tcp
tshark -r capture.pcap -Y "tls.handshake.type == 1" -T fields -e tls.handshake.extensions_server_name
tshark -r capture.pcap -z endpoints,ip -q
tshark -r capture.pcap -Y "ftp.request.command == USER || ftp.request.command == PASS || http.authorization" -T fields -e ftp.request.arg -e http.authorization
Python PCAP 分析
from scapy.all import rdpcap, IP, TCP, UDP, DNS, DNSQR, Raw
import os
import sys
import json
from collections import defaultdict, Counter
from datetime import datetime
class PCAPForensicAnalyzer:
"""使用 Scapy 对 PCAP 文件进行取证分析。"""
def __init__(self, pcap_path: str, output_dir: str):
self.pcap_path = pcap_path
self.output_dir = output_dir
os.makedirs(output_dir, exist_ok=True)
self.packets = rdpcap(pcap_path)
def get_conversations(self) -> list:
"""提取包含字节计数的唯一 IP 会话。"""
convos = defaultdict(lambda: {"packets": 0, "bytes": 0})
for pkt in self.packets:
if IP in pkt:
key = tuple(sorted([pkt[IP].src, pkt[IP].dst]))
convos[key]["packets"] += 1
convos[key]["bytes"] += len(pkt)
return [
{"src": k[0], "dst": k[], : v[], : v[]}
k, v (convos.items(), key= x: x[][], reverse=)
]
() -> :
queries = []
pkt .packets:
DNS pkt pkt[DNS].qr == DNSQR pkt:
queries.append({
: pkt[DNSQR].qname.decode(errors=).rstrip(),
: pkt[DNSQR].qtype,
: pkt[IP].src IP pkt
})
queries
() -> :
ip_timestamps = defaultdict()
pkt .packets:
IP pkt TCP pkt:
key = (pkt[IP].src, pkt[IP].dst, pkt[TCP].dport)
ip_timestamps[key].append((pkt.time))
beacons = []
key, times ip_timestamps.items():
(times) < :
deltas = [times[i+] - times[i] i ((times)-)]
deltas:
avg_delta = (deltas) / (deltas)
variance = ((d - avg_delta) ** d deltas) / (deltas)
variance < threshold_seconds avg_delta > :
beacons.append({
: key[], : key[], : key[],
: (avg_delta, ),
: (variance, ),
: (times)
})
(beacons, key= x: x[])
() -> :
protocols = Counter()
pkt .packets:
TCP pkt:
protocols[] +=
UDP pkt:
protocols[] +=
(protocols.most_common())
() -> :
report = {
: datetime.now().isoformat(),
: .pcap_path,
: (.packets),
: .get_conversations()[:],
: .extract_dns_queries()[:],
: .detect_beaconing(),
: .get_protocol_distribution()
}
report_path = os.path.join(.output_dir, )
(report_path, ) f:
json.dump(report, f, indent=)
()
()
()
()
report_path
():
(sys.argv) < :
()
sys.exit()
analyzer = PCAPForensicAnalyzer(sys.argv[], sys.argv[])
analyzer.generate_report()
__name__ == :
main()
参考资料