PCAP modification with Python

早过忘川 提交于 2019-12-02 04:26:12

I don't know if there is a way to do that with scapy, but you could also use the very simple PcapFile.py library that lets you read/write pcap files packet by packet (disclaimer: I'm one of the authors). If your needs aren't too complicated (e.g. you don't need to re-generate checksums) you could simply modify the frame's bytestring using Python slicing and Python's struct module.

But I think it should also be possible to get scapy to analyze the frame using p = Ether(packet_bytes) and convert back to a bytestream for PcapFile.py using str(p). This way you can let scapy re-calculate a valid checksum for you.

Scapy seems to have "a severe memory problem", as you state, probably because you read the whole PCAP file in memory with rdpcap() and then modify it (still in memory), and then write it back to another file, all at once, from your memory, with wrpcap().

But the most "Pythonic" and "Scapyist" way to do such a thing would be to use generators (PcapReader and PcapWriter). Here is an example:

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()
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!