首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Python修改PCAP

用Python修改PCAP
EN

Stack Overflow用户
提问于 2015-08-27 13:39:46
回答 2查看 5.1K关注 0票数 1

我需要读取一个PCAP文件,修改一些字段(实际上是IPv4源和目标以及以太网源和目标)。PCAP是预先过滤的,仅包括以太网数据包上的IPv4 .

到目前为止,我试着用替罪羊来做这件事,但是这有一个严重的记忆问题。当读取~350 My的PCAP文件时,我的16 My内存已完全填满。实际上,只是在看书。我对这份文件还没做任何其他的事。我也有找到了这个答案,随着这些变化,阅读速度非常快。一旦我开始修改数据包,内存就会再次膨胀。在这种情况下,Scapy实际上是不可用的。

我还考虑过使用其他工具,如tcprewrite,但它不能满足我的目的。源MAC对于每个数据包总是相同的,这也可以用tcprewrite来完成。源IP在给定的子网范围内应该是随机的,例如在10.0.0.0/16中均匀分布。更复杂的是目的地IP,它需要根据给定的流量矩阵进行计算。

所以问题是:我如何读取一个PCAP文件,用自定义函数修改四个基本字段(以太网src+dst,IP src+dst),并将其写回(另一个) PCAP文件?

实际上,我的框架的其余部分是用Python编写的,所以我更喜欢基于python的解决方案。但是,由于我可以简单地调用其他脚本,这不是强制性的。谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-27 14:30:37

我不知道是否有一种方法可以用替罪羊来实现,但您也可以使用非常简单的PcapFile.py库,它允许您逐包读取/写入pcap (免责声明:我是作者之一)。如果您的需求不太复杂(例如,您不需要重新生成校验和),您可以使用Python切片和Python的struct模块简单地修改框架的字节串。

但我认为,使用p = Ether(packet_bytes)分析框架并使用str(p)将其转换回用于PcapFile.py的字节流也是可能的。这样你就可以让替罪羊为你重新计算一个有效的校验和。

票数 0
EN

Stack Overflow用户

发布于 2015-08-30 15:35:19

正如您所述,Scapy似乎存在“严重的内存问题”,这可能是因为您用rdpcap()在内存中读取整个PCAP文件,然后修改它(仍然在内存中),然后使用wrpcap()立即将其写回另一个文件。

但是最"Pythonic“和"Scapyist”的方法是使用生成器(PcapReaderPcapWriter)。下面是一个示例:

代码语言:javascript
复制
from scapy.all import *

ETHER_ADDR_TRANSLATION = {
    "orig_mac_1": "new_mac_1",
    # [...]
}

IP_ADDR_TRANSLATION = {
    "orig_ip_1": "new_ip_1",
    # [...]
}

def addr_translation_pcap(source, destination):
    out = PcapWriter(destination)
    for pkt in PcapReader(source):
        # In case we have complex encapsulations, like IP-in-IP, etc.,
        # we have to do something like this. If we know for sure that's
        # not the case, there's no need for such a (time-consuming) code.
        layer = pkt
        while not isinstance(layer, NoPayload):
            if isinstance(layer, Ether):
                for field in ['src', 'dst']:
                    fval = getattr(layer, field)
                    if fval in ETHER_ADDR_TRANSLATION:
                        setattr(layer, field, ETHER_ADDR_TRANSLATION[fval])
            # Let's not forget IP-in-ICMP-error
            elif isinstance(layer, (IP, IPerror)):
                for field in ['src', 'dst']:
                    fval = getattr(layer, field)
                    if fval in IP_ADDR_TRANSLATION:
                        setattr(layer, field, IP_ADDR_TRANSLATION[fval])
            elif isinstance(layer, ARP):
                fields = {}
                if layer.hwtype == 1:
                    fields.update({'hwsrc': ETHER_ADDR_TRANSLATION,
                                   'hwdst': ETHER_ADDR_TRANSLATION})
                if layer.ptype == 2048:
                    fields.update({'psrc': IP_ADDR_TRANSLATION,
                                   'pdst': IP_ADDR_TRANSLATION})
                for field, translator in fields.iteritems():
                    fval = getattr(layer, field)
                    if fval in translator:
                        setattr(layer, field, translator[fval])
            layer = layer.payload
        out.write(pkt)
    out.close()
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32250981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档