目录
流量处理工具
-
SplitCap
- 官方链接:https://www.netresec.com/index.ashx?page=SplitCap
- 平台:win平台工具,需要下载,下载后直接在命令行执行即可。
- 功能:可将pcap按流、会话、主机对、MAC等方式切分为若干个小pcap。
- 示例:
SplitCap.exe -r test.pcap -s session -o ./split_pcaps -r: 读取pcap -s: 切分方式,session为按会话切分 -o: 输出文件夹路径
-
EditCap
-
官方链接:editcap(1)
- 平台:win,同wireshark一起安装,一般在同目录下。
- 功能:切割pcap,按包数、包长等。
- 示例:
editcap.exe -F pcap -c 1000 src.pcap dst.pcap editcap.exe -F pcap -i 10 src.pcap dst.pcap -F: 输出格式,默认为pcapng -c: 按n个包切分 -i: 按n秒间隙分割 src.pcap: 源pcap包 dst.pcap: 输出pcap包名,会按此格式生成切分后的若干个pcap包
-
-
tshark
- 官方连接:tshark(1)
- 平台:win,linux;win下同wireshark一起安装,一般在同目录下。
- 功能:提取pcap中每个数据包的指定字段。
- 示例:
tshark -r src.pcap -T fields -e frame.len -e ip.proto -e tcp.srcport -E header=y > dst.csv -e 指明需要提取的字段 -e frame.time_relative 包的相对时间 -e ip.src 源IP -e ip.dst 目的IP -e ip.proto 协议名 -e tcp.srcport 源Port -e tcp.dstport 目的Port -e frame.len 包大小 -E header=n 是否输出表头
-
tcpreplay
- 官方连接:Tcpreplay - Pcap editing and replaying utilities
- 平台:Linux
- 功能:回放pcap包
- 详细参数参考:https://www.cnblogs.com/lizhaoxian/p/11260396.html
- 示例:
tcpreplay -i ens33 -l 1 -t test.pcap
-i:网卡名
-t:最高速度回放
-l:循环次数
-p:以每秒多少包的速度回放
-x:以捕获速度的倍数重放
PYTHON库
以下各个库功能主要以读取、处理pcap文件或实时监听网卡并抓包为主。
-
Scapy
官方文档:介绍 — Scapy 2.4.4. 文档
优点:简单易上手
缺点:速度非常慢,执行rdpcap时会将整个pcap读入内存,因此读取超大pcap时需配合splitcap、editcap等工具共同使用。
from scapy.all import *
# 读取pcap文件
packets = rdpcap('test.pcap') # packets = rdpcap('test.pcap', 200)
# 遍历数据包
for packet in packets:
# 若当前包不包含DNS协议,跳过
if 'DNS' not in packet:
continue
# 若当前DNS报文不包含DNS问题记录,跳过
if 'DNS Question Record' not in packet['DNS']:
continue
# 若DNS报文的qr字段为1(响应报文),则打印该报文需要回复的域名
if packet['DNS'].qr == 1:
print(packet['DNS']['DNS Question Record'].qname)
注:
1. rdpcap方法可传入第二个参数(int),指定读取数据条数,若设置较小,可极大提升读取速度。
2. 执行packet.show()会输出当前packet所有可访问字段和值,可为程序读取提供参考。
使用scapy处理超大PCAP包时,可使用以下方法:
from scapy.all import *
load_layer("tls")
class PCAPProcessor:
def __init__(self):
pass
# 依次读取超大pcap中的每个packet
def yield_packet(self, src_file_path):
with PcapReader(src_file_path) as pcap_reader: # 返回一个迭代器
for pkt in pcap_reader: # for循环进行遍历
yield pkt
# 写入pcap
def write_pkt(self, pkt, dst_file_path):
wrpcap(dst_file_path, pkt, append=True)
if __name__ == '__main__':
p = PCAPProcessor()
g = p.yield_packet('./test.pcap')
while True:
try:
pkt = next(g)
# 此处调用处理每个packet的函数
except Exception as e:
break
参考:python3使用scapy分析修改pcap大文件(1G)_scapy切分大的pcap文件-CSDN博客
Scapy也可以实时监听网卡,使用callback来处理监听到的每个包:
from scapy.all import *
def callback(packet):
if packet.haslayer('HTTP'):
http = packet.payload.payload.payload
print(http.show())
sniff(prn=callback, iface='ens33', count=0)
-
DPKT
官方文档:dpkt — dpkt 1.9.2 documentation
优点:pcap读取速度远快于scapy。
缺点:使用相比scapy更繁琐,实时抓包的功能需要配合pcap-ct库使用。
import dpkt
# 读取pcap文件
with open('test.pcap', 'rb') as f:
pcap = dpkt.pcap.Reader(f)
# 遍历数据包
for timestamp, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
# 获取IP层,若当前包不存在IP层则continue
if not isinstance(eth.data, dpkt.ip.IP):
continue
ip = eth.data
# 获取UDP层,若当前包不存在UDP层则continue
if not isinstance(ip.data, dpkt.udp.UDP):
continue
udp = ip.data
# 将udp载荷读取为DNS报文
try:
dns = dpkt.dns.DNS(udp.data)
except Exception as e:
continue
# 若DNS报文的qr字段为1(响应报文),则打印该报文需要回复的域名
if dns.qr == 1:
if len(dns.qd) > 0:
print(dns.qd[0].name)
-
pcap-ct
可用于实时抓包,配合dpkt分析。
import dpkt
import pcap # pcap-ct
sniffer = pcap.pcap(name='ens33', promisc=True, immediate=True, timeout_ms=50)
for ts, pkt in sniffer:
eth = dpkt.ethernet.Ethernet(pkt)
if not isinstance(eth.data, dpkt.ip.IP):
continue
ip = eth.data
if not isinstance(ip.data, dpkt.tcp.TCP):
continue
tcp = ip.data
# process the data
print(tcp.flags)
-
flowcontainer
文档:GitHub - jmhIcoding/flowcontainer: 从pcap获取流的基本信息工具
功能:按流的粒度处理pcap
参考:flowcontainer: 基于python3的pcap网络流量特征信息提取库_Icoding_F2014的博客-CSDN博客
from flowcontainer.extractor import extract
result = extract(r"test.pcap",filter='',extension=["tls.handshake.extensions_server_name","tls.handshake.ciphersuite"])
for key in result:
### The return vlaue result is a dict, the key is a tuple (filename,procotol,stream_id)
### and the value is an Flow object, user can access Flow object as flowcontainer.flows.Flow's attributes refer.
value = result[key]
print('Flow {0} info:'.format(key))
print('src ip:',value.src)
print('dst ip:',value.dst)
## access payload packet lengths
print('payload lengths :',value.payload_lengths)
## access payload packet timestamps sequence:
print('payload timestamps:',value.payload_timestamps)