前言:在测试过程中抓了一些包,里面的tcp流太多了,手动分离出来太慢,就写了一个脚本
ps:只适用于分离单条tcp流的情况,像ftp这种有控制流数据流的情况不适用
思路:
1、 首先需要将pcap包里的每条tcp流找出来,由于代码没办法像在wireshark里直接通过tcp.stream eq 1 过滤条件追踪流,所以想了个其他办法,通过syn包的源端口来区分,源或目的端口和syn包端口一致的,视为同一条流。将syn包的的源端口组成port列表,列表的长度就是pcap里流的数量
2、创建一个长度与port列表一致的空的二维数组data_list,其他包的源或目的端口在port列表的,以源或目的端口在port列表为索引,将该pcap包append到对应列表位置
3、遍历完pcap包后,二维数组data_list,每个元素就是一个pcap包
代码如下:
# -*- coding: utf-8 -*-
from scapy.all import *
def read_pcap(file_name):
print '开始读取pcap'
file_data = rdpcap(file_name)
print '读取完成'
return file_data
def fenliu(file_data):
port = []
l = len(file_data)
for i in range(0,l):
try:
# syn包的tcp标志位为0x02,跟据syn包先将源端口组成列表,返回port列表
if file_data[i]['TCP'].flags == 0x02:
port.append(file_data[i]['TCP'].sport)
except:
pass
return port
def fenbao(file_data):
port = fenliu(file_data)
l1 = len(port)
data_list=[[] for _ in range(l1)]
#data_list=[[]]*l1 不能这样创建多维列表,会出问题,应该用上面的方式
l = len(file_data)
for i in range(0, l):
try:
#源端口在port列表里,则端口获取在列表中的索引,放入对应的data_list中
if file_data[i]['TCP'].sport in port :
j = port.index(file_data[i]['TCP'].sport)
data_list[j].append(file_data[i])
# 目的端口在port列表里,则端口获取在列表中的索引,放入对应的data_list中
elif file_data[i]['TCP'].dport in port:
j = port.index(file_data[i]['TCP'].dport)
data_list[j].append(file_data[i])
except:
pass
return data_list
def save_file(data_list):
l = len(data_list)
print '开始保存pcap,共有'+str(l)+'个pcap包'
for i in range(0,l):
name = 'ips'+str(i)+'.pcap'
wrpcap(name, data_list[i])
print '保存完成'
if __name__ =="__main__":
file_name = "E:\\IPS.pcap"
file_data = read_pcap(file_name)
data=fenbao(file_data)
save_file(data)
遇到的问题:
1、使用查看pcap包字段语句时file_data[i]['TCP'].flags,没有加try,因为不是所以包都有tcp字段的,所以需要加try抛出异常继续遍历
2、使用这种方式创建的数组data_list=[[]]*l1,结果生成的pcap全部都一样,并没有按照流分离。原因:data_list=[[]]*l1,这样创建的二维数组,列表里每个列表指向的内存空间是一样的,所以列表中每个元素的值都是相同的
如:
list=[[0]*3]*2
print(list)
list[0][0]=1
print(list)
结果: