2

我使用 Scapy 的功能send发送数据包,这些数据包将在路由器上生成 ICMP 数据包,并将这些 ICMP 数据包转储为tcpdump,作为子进程启动。

然后,我将使用 scapy 的内置rdpcap函数将这些 ICMP 数据包读回我的程序。

好吧,事实证明rdpcap有时会搞砸一些事情,只要我想查看我捕获的数据包,它就会返回以下内容:

(InteractiveConsole)
>>> icmpPackets
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/scapy/plist.py", line 57, in __repr__
    if self._elt2pkt(r).haslayer(p):
AttributeError: 'NoneType' object has no attribute 'haslayer'

然后,我只需要rdpcap再次调用相同的参数,一切都会恢复正常:

>>> icmpPackets = rdpcap(tcpdumpFileName)
>>> icmpPackets
<icmpPackets.cap: TCP:0 UDP:0 ICMP:1428 Other:1>

这是一些错误,对吧?

编辑:好的,在我得到那个错误之前我做的一件事是以下,这可能不是太正统,但是当我伪造数据包时我不需要以太网层。如果我删除这两行,我不会收到任何此类错误:

for i in range(len(icmpPackets)):
        icmpPackets[i] = icmpPackets[i].getlayer(IP)

我以前在其他地方做过这个,从来没有遇到过问题。这里发生了什么事?

4

1 回答 1

1

你好,

我真的不明白为什么你用 tcpdump 而不是 scapy 来嗅探流量,但无论如何......你的问题不是 Scapy 中的错误,而是你的代码中的错误。如果数据包没有层(例如,数据包),您将用.getlayer(IP)返回的每个数据包替换每个数据包。因此,你得到后者的例外。NoneIPARP

我认为你应该更换

icmpPackets = rdpcap(tcpdumpFileName)
for i in range(len(icmpPackets)):
    icmpPackets[i] = icmpPackets[i].getlayer(IP)

icmpPackets = PacketList([p[IP] for p in PcapReader(tcpdumpFileName) if IP in p])

首先,我认为它更“Pythonic”,而且它通过删除没有IP层的数据包来解决问题。或者,如果您想让所有数据包都没有Ether层,您也可以使用:

icmpPackets = PacketList([p.payload for p in PcapReader(tcpdumpFileName)])

另外,您可以在 tcpdump 中使用 BPF 过滤器进行过滤(icmp如果您只想要ICMP数据包)。

于 2014-01-22T21:19:53.290 回答