个人公众号“代码就是生产力”,发布更多有用的工具
对于UDP来说,如果发现数据过大,那么 IP 层会自动对数据进行切割,分片,但是通常应用层我们不会发现有什么影响,因为已经自动合并了分片数据,但是如果是使用 wireshark 录制的数据,就会出现数据分片了,但是没有重组的情况,这个时候,需要我们手动对数据进行一个重组,类似如下的情况:
可以看到,一个数据被分成了8个数据分片,但是他们的ID是一样的,然后有不同的offset,那么我们就可以根据这两个特性,把每组的分片重组起来。
仅仅使用 dpkt 工具即可,代码如下。
#coding:utf-8
import dpkt
def main(file_path):
# f = open(file_path) # 此写法为python2之下,
f = open(file_path, mode='rb') #python3
try:
pcap = dpkt.pcap.Reader(f) # 先按.pcap格式解析,若解析不了,则按pcapng格式解析
except:
print("it is not pcap ... format, pcapng format...")
pcap = dpkt.pcapng.Reader(f)
# 接下来就可以对pcap做进一步解析了,记住在使用结束后最好使用f.close()关掉打开的文件,虽然程序运行结束后,
# 系统会自己关掉,但是养成好习惯是必不可少的。当前变量pcap中是按照“间戳:单包”的格式存储着各个单包
first_flag = 1
raw_data = []
# 将时间戳和包数据分开,一层一层解析,其中ts是时间戳,buf存放对应的包
for (ts, buf) in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf) # 解包,物理层
if not isinstance(eth.data, dpkt.ip.IP): # 解包,网络层,判断网络层是否存在,
continue
ip = eth.data
print(ip.id, ip.offset)
# if not isinstance(ip.data, dpkt.tcp.TCP): # 解包,判断传输层协议是否是TCP,即当你只需要TCP时,可用来过滤
# continue
# if not isinstance(ip.data, dpkt.udp.UDP):#解包,判断传输层协议是否是UDP ; 分片的节点是ip.data.data 不然是 ip.data
# continue
if first_flag:
raw_data.append(ip.data.data)
else:
# if (id_flag != ip.id and ip.offset == 0):
if (ip.offset == 0):
# 可以在这里对每次UDP分片的数量做更严格的限制,因为基本上同一个数据来源的分片数量是固定的,比如每次发送3000byte,那么每次都是分成2个片段
# 比如我这里每个数据被分成了9个片段,那么我就只要9个片段的数据,不是9个片段的数据就丢弃
# if len(raw_data) != 9:
# raw_data.clear()
# raw_data.append(ip.data.data)
# continue
result = b""
for i in raw_data:
result += i
tempeth.data.data = result
writer.writepkt(tempeth, ts=ts) # 如果不加ts参数的话,这个数据包的时间戳默认是当前时间!
newpacpfile.flush()
raw_data.clear()
if not isinstance(ip.data.data, bytes): # 可能存在其他类型数据
continue
raw_data.append(ip.data.data)
else:
# print(len(raw_data), "len(raw_data)", type(ip.data))
if not isinstance(ip.data, bytes): # 可能存在其他类型数据
continue
raw_data.append(ip.data)
tempeth = eth
first_flag = 0
except Exception as err:
print( "[error] %s" % err)
f.close()
if name == ‘main’:
path = “0325_1024.pcap”
newpacpfile = open(“new.pcap”, “wb”)
writer = dpkt.pcap.Writer(newpacpfile)
main(path)
newpacpfile.close()
最后效果如下:
从数据的容量可以看到,多个分片的数据已经被组合在一起了,但是其实还有缺点,每个分片的tag还是分片的标签。