How to pickle a scapy packet?

匿名 (未验证) 提交于 2019-12-03 08:35:02

问题:

I need to pickle a scapy packet. Most of the time this works, but sometimes the pickler complains about a function object. As a rule of thumb: ARP packets pickle fine. Some UDP packets are problematic.

回答1:

My solution (as inspired by the scapy mailing list) is as follows:

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

Anywhere I wish to pass a scapy Packet through a Queue I simply wrap it in a PicklablePacket and __call__ it afterwards. I am not aware of data that is not retained this way. However this approach only works with Ethernet packets. (All packets sniffed on a regular NIC (not WLAN) are Ethernet.) It could probably be extended to work for other types, too.



回答2:

If by pickle you mean generically serialize you can always use the pcap import/export methods: rdpcap and wrpcap.

wrpcap("pkt.pcap",pkt) pkt = rdpcap("pkt.pcap")

Or you could start up your process and grab the packets in another process. If there is some pattern you can match, say a known port or source IP tcpdump will work:

tcpdump -i eth0 -w FOO.pcap host 172.20.33.12 and \(udp or arp\)

You can then read the generated pcap in as above:

pkts = rdpcap('FOO.pcap')


回答3:

(This is more for reference, so no votes expected)

The Scapy list scapy.ml@secdev.org is well-monitored and tends to be very responsive. If you don't get answers here, try there as well.



回答4:

As inspired by this question one can use the dill library (or others like sPickle etc - see pypi search pickle) to save scapy packets. E.g. Install dill using sudo easy_install dill or sudo pip install dill. Here's a basic usage scenario:

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'))

Also one can of course just use scapy's native functions to dump the packets to a pcap file (readable by tcpdump/wireshark etc) - if one just has an array of packets:

wrpcap("packets_array.pcap",packets_array)


回答5:

You can monkeypatch the Packet class and inject __getstate__ and __setstate__ methods that convert the function in the object from and to a picklable representation. See here for details.

def packet_getstate(self):     # todo  def packet_setstate(self, state):     # todo  from scapy.packet import Packet Packet.__getstate__ = packet_getstate Packet.__setstate__ = packet_setstate


回答6:

To get the PicklabePacket class to work with scapy 3.0.0 you can use this class definition:

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


转载请标明出处:How to pickle a scapy packet?
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!