【发布时间】:2011-05-08 13:34:41
【问题描述】:
我需要腌制一个scapy 数据包。大多数情况下这是可行的,但有时pickler会抱怨一个函数对象。根据经验:ARP 数据包腌制得很好。有些 UDP 数据包有问题。
【问题讨论】:
-
背景是与
multiprocessing模块一起使用。如果您想通过Queue传输对象,它要求对象是可腌制的。 -
有人可以回答这个问题,以便我奖励赏金吗?
我需要腌制一个scapy 数据包。大多数情况下这是可行的,但有时pickler会抱怨一个函数对象。根据经验:ARP 数据包腌制得很好。有些 UDP 数据包有问题。
【问题讨论】:
multiprocessing 模块一起使用。如果您想通过Queue 传输对象,它要求对象是可腌制的。
我的解决方案(受 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
任何我想通过Queue 传递scapy Packet 的地方我只需将它包装在PicklablePacket 和__call__ 之后。我不知道没有以这种方式保留的数据。然而,这种方法仅适用于Ethernet 数据包。 (在常规 NIC(不是 WLAN)上嗅探的所有数据包都是以太网。)它可能也可以扩展为适用于其他类型。
【讨论】:
如果你所说的 pickle 是指一般序列化,你总是可以使用 pcap 导入/导出方法:rdpcap and 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 受到良好监控,并且往往反应迅速。如果您在此处没有得到答案,也请在此处尝试。
【讨论】:
受question 的启发,可以使用dill 库(或其他类似sPickle 等-参见pypi search pickle)来保存scapy 数据包。例如。使用 sudo easy_install dill 或 sudo pip install dill 安装 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 类进行monkeypatch 并注入__getstate__ 和__setstate__ 方法,将对象中的函数从和转换为可提取表示。详情请见here。
def packet_getstate(self):
# todo
def packet_setstate(self, state):
# todo
from scapy.packet import Packet
Packet.__getstate__ = packet_getstate
Packet.__setstate__ = packet_setstate
【讨论】:
Packet 对象 (pprint.pprint(packet.__dict__)) 可以轻松显示函数是什么,如果它是 lambda、函数或实例方法。你知道什么是函数吗?
要让 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
【讨论】: