繁体   English   中英

使用Python修改PCAP

[英]PCAP modification with Python

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

到目前为止,我尝试使用Scapy进行此操作,但是Scapy存在严重的内存问题。 读取〜350MB PCAP文件时,我的16GB RAM已满。 实际上,只是阅读。 我对此文件没有做任何其他事情。 我也找到了这个答案 ,并且有了这些更改,阅读速度很快。 一旦我开始修改数据包,内存就会再次膨胀。 Scapy实际上在这种情况下不可用

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

所以问题是:如何读取PCAP文件,使用自定义功能修改四个基本字段(以太网src + dst,IP src + dst),然后将其写回到(另一个)PCAP文件中?

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

正如您所说,Scapy似乎存在“严重的内存问题”,可能是因为您使用rdpcap()读取了整个PCAP文件在内存中,然后对其进行了修改(仍在内存中),然后将其写回到另一个文件中,全部从您的内存中一次使用wrpcap()

但是,做这种事情的最“ Pythonic”和“ Scapyist”方式是使用生成器( PcapReaderPcapWriter )。 这是一个例子:

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

我不知道是否有办法用scapy做到这一点,但是您也可以使用非常简单的PcapFile.py库,该库允许您逐包读取/写入pcap文件(免责声明:我是作者之一) 。 如果您的需求不太复杂(例如,您不需要重新生成校验和),则可以使用Python切片和Python的struct模块简单地修改帧的字节串。

但是我认为也有可能使p = Ether(packet_bytes)使用p = Ether(packet_bytes)分析帧,并使用str(p)转换回PcapFile.py的字节流。 这样,您就可以让scapy重新为您计算有效的校验和。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM