除了Pyshark,如何更快速地读取.cap文件而不是使用Scapy的rdpcap()?

7 投票
6 回答
15368 浏览
提问于 2025-04-18 18:23

我一直在寻找一种方法,把802.11数据包从.cap文件中提取到一个数组里。目前我发现了以下几种工具:

  • Scapy:这个工具还不错,有文档可以参考,但速度太慢了。当我尝试打开一个超过40MB的文件时,它会一直卡住,直到把我所有的内存(16GB)都用完,这样我的电脑就会死机,我不得不重启。

  • Pyshark:这个工具没有Scapy的问题,但文档太少,我找不到处理和获取802.11数据包属性的方法。

所以我在想,可能还有更好的解决方案,或者有人对pyshark有经验吗?

from scapy.all import *
import pyshark
from collections import defaultdict
import sys
import math
import numpy as np
counter=0
Stats = np.zeros((14))
filename='cap.cap'

a = rdpcap(filename)
print len(a)
for p in a:
        pkt = p.payload
        #Management packets
        if p.haslayer(Dot11) and p.type == 0:
                ipcounter = ipcounter +1
                Stats[p.subtype] = Stats[p.subtype] + 1

print Stats

注意:当我用一个10MB的输入文件启动程序时,大约需要20秒左右,但它确实能工作。我在想这是为什么,为什么和pyshark差别这么大,它到底在做什么计算?

6 个回答

2

你试过 dpkt 吗?它有一个很不错的读取器接口,似乎可以懒加载数据包(我用它加载过超过100MB的pcap文件,没问题)。

示例:

from dpkt.pcap import Reader

with open(...) as f:
    for pkt in Reader(f):
        ...
3
with PcapReader('filename.pcapng') as pcap_reader:
    for pkt in pcap_reader:
        #do something with the packet
        ...

这个效果很好!

PcapReader就像把xrange()替换成range()一样

3

如果pyshark满足你的需求,你可以这样使用它:

cap = pyshark.FileCapture('/tmp/mycap.cap')
for packet in cap:
    my_layer = packet.layer_name # or packet['layer name'] or packet[layer_index]

想要查看有哪些可用的层和它们的属性,只需打印出来(或者使用layer/packet.pretty_print()),或者使用自动补全功能,或者查看packet.layer._all_fields。例如,你可以使用packet.udp.srcport。

文档中缺少了什么呢?

请注意,你还可以在FileCapture实例中添加一个过滤器作为参数(可以是显示过滤器或BPF过滤器,具体可以查看文档)。

3

Scapy会把所有的数据包加载到你的内存中,并创建一个packetList的实例。我觉得你可以通过两种方法来解决这个问题。

  1. 使用过滤器来捕获数据包。在我的工作中,我从来没有捕获过超过2MB的数据包,因为我只在一个无线频道上捕获一次。
  2. 把大的数据包文件分成几个小部分,然后再处理它们。

希望这些建议对你有帮助。

11

你可以对一个叫做 utils.py 的 scapy 文件进行修改,这样它就不会把所有东西都加载到内存里。

把:

def read_all(self,count=-1):
    """return a list of all packets in the pcap file
    """
    res=[]
    while count != 0:
        count -= 1
        p = self.read_packet()
        if p is None:
            break
        res.append(p)
    return res

改成

def read_all(self,count=-1):
    """return an iterable of all packets in the pcap file
    """
    while count != 0:
        count -= 1
        p = self.read_packet()
        if p is None:
            break
        yield p
    return

感谢来源于: http://comments.gmane.org/gmane.comp.security.scapy.general/4462

不过这个链接现在已经失效了。

撰写回答