我需要腌制一scapy
包。大多数情况下这是可行的,但有时pickler会抱怨一个函数对象。根据经验:ARP 数据包腌制得很好。一些 UDP 数据包有问题。
6 回答
我的解决方案(受 scapy 邮件列表的启发)如下:
class PicklablePacket:
"""A container for scapy packets that can be pickled (in contrast
to scapy packets themselves)."""
def __init__(self, pkt):
self.contents = bytes(pkt)
self.time = pkt.time
def __call__(self):
"""Get the original scapy packet."""
pkt = scapy.Ether(self.contents)
pkt.time = self.time
return pkt
任何我希望通过 ascapy
Packet
的地方,Queue
我只需将其包裹在 a 中PicklablePacket
,__call__
然后再将其包裹起来。我不知道没有以这种方式保留的数据。然而,这种方法仅适用于Ethernet
数据包。(在常规 NIC(不是 WLAN)上嗅探的所有数据包都是以太网。)它可能也可以扩展为适用于其他类型。
如果通过 pickle 您的意思是一般序列化,您始终可以使用 pcap 导入/导出方法:rdpcap 和 wrpcap。
wrpcap("pkt.pcap",pkt)
pkt = rdpcap("pkt.pcap")
或者您可以启动您的进程并在另一个进程中获取数据包。如果有一些你可以匹配的模式,比如说一个已知的端口或源 IP tcpdump 将起作用:
tcpdump -i eth0 -w FOO.pcap host 172.20.33.12 and \(udp or arp\)
然后,您可以读取生成的 pcap,如上所示:
pkts = rdpcap('FOO.pcap')
(这更多是为了参考,所以没有票数)
Scapy 列表 scapy.ml@secdev.org 受到良好监控,并且往往反应迅速。如果您在这里没有得到答案,也可以在那里尝试。
受这个问题的启发,可以使用dill库(或其他类似 sPickle 等 - 请参阅pypi search pickle)来保存 scapy 数据包。sudo easy_install dill
例如使用或安装莳萝sudo pip install dill
。这是一个基本的使用场景:
import dill as pickle
# E.g. Dump an array of packets stored in variable mypackets to a file
pickle.dump(mypackets, open('mypackets.dill-pickle', 'w'))
# Restore them from the file
mypackets = pickle.load(open('mypackets.dill-pickle', 'rb'))
当然也可以只使用 scapy 的本机函数将数据包转储到 pcap 文件(可由 tcpdump/wireshark 等读取) - 如果一个只有一组数据包:
wrpcap("packets_array.pcap",packets_array)
您可以对Packet
类和注入__getstate__
以及__setstate__
将对象中的函数从可提取表示形式转换为可提取表示形式的方法进行修补。有关详细信息,请参见此处。
def packet_getstate(self):
# todo
def packet_setstate(self, state):
# todo
from scapy.packet import Packet
Packet.__getstate__ = packet_getstate
Packet.__setstate__ = packet_setstate
要让 PicklabePacket 类与 scapy 3.0.0 一起使用,您可以使用此类定义:
class PicklablePacket:
"""A container for scapy packets that can be pickled (in contrast
to scapy packets themselves).
This works for python 3.5.1 and scapy 3.0.0 """
def __init__(self, pkt):
self.__contents = pkt.__bytes__()
self.__time = pkt.time
def __call__(self):
"""Get the original scapy packet."""
pkt = scapy.all.Ether(self.__contents)
pkt.time = self.__time
return pkt