如何腌制一个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 dillsudo 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 at 0x8bb2bc4>: it's not found as scapy.layers.inet.【参考方案6】:

要让 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 警告消息?

如何验证 Scapy 中的数据包是不是具有 TCP 层

如何将UDP数据包发送到scapy中的特定UDP dst端口?

Python-Scapy 之类的-如何在数据包级别创建 HTTP GET 请求

Scapy如何获取ping时间?

Python Scapy wrpcap - 如何将数据包附加到 pcap 文件?