如何腌制一个scapy包?
Posted
技术标签:
【中文标题】如何腌制一个scapy包?【英文标题】:How to pickle a scapy packet? 【发布时间】:2011-05-08 13:34:41 【问题描述】:我需要腌制一个scapy
数据包。大多数情况下这是可行的,但有时pickler会抱怨一个函数对象。根据经验:ARP 数据包腌制得很好。有些 UDP 数据包有问题。
【问题讨论】:
背景是与multiprocessing
模块一起使用。如果您想通过Queue
传输对象,它要求对象是可腌制的。
有人可以回答这个问题,以便我奖励赏金吗?
【参考方案1】:
我的解决方案(受 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)上嗅探的所有数据包都是以太网。)它可能也可以扩展为适用于其他类型。
【讨论】:
感谢您的回帖。虽然我不需要你的确切解决方案,但它帮助我找到了自己的解决方案。【参考方案2】:如果你所说的 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')
【讨论】:
1) 我说的是每秒 500 个数据包。 2) 这种方法实际上会丢失数据。例如时间戳是四舍五入的。这不一定是问题,但必须考虑在内。 scapy 每秒可以推送 500 个数据包吗?我发现在发送数据包时,它比这要少得多。您总是可以在另一个终端中运行 tcpdump。 Scapy 可以。请参阅对其他答案的评论。 您可以传递对队列中文件的引用。字符串是可腌制的。【参考方案3】:(这是更多的参考,所以不希望投票)
Scapy 列表 scapy.ml@secdev.org 受到良好监控,并且往往反应迅速。如果您在此处没有得到答案,也请在此处尝试。
【讨论】:
哦,这就是通信进行的地方?问题跟踪器似乎非常不活跃。至少我的一个 bug 在那里呆了半年没有任何反应。 附带说明一下,每秒 500 个数据包可能也超过 Scapy 的句柄。它是为灵活性而不是速度而设计的 :) 在列表中询问。我并没有真正使用它,所以我不是专家。 其实我可以确认,scapy 每秒处理 500 个数据包非常好。当然,我使用了多个线程和(在这个问题之后)多个进程。【参考方案4】:受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)
【讨论】:
【参考方案5】:您可以对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、函数或实例方法。你知道什么是函数吗?
完整的回溯对于评论来说太长了,但是您可以自己轻松地复制它。最后一行是:pickle.PicklingError: Can't pickle 要让 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
【讨论】:
以上是关于如何腌制一个scapy包?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Scapy 生成数据包的 PDF 时如何抑制 PyX 警告消息?
如何将UDP数据包发送到scapy中的特定UDP dst端口?