scapy的导出linux熟模式捕获并没有在wireshark中打开

时间:2015-01-08 01:09:18

标签: python wireshark pcap scapy

这是一个简单的例子:

from scapy.all import *
pkts = rdpcap('/tmp/sample.pcap')
wireshark(pkts)

然后wireshark发出了这个错误:

The capture file appears to be damaged or corrupt.
(libpcap: IrDA capture has a packet with an invalid sll_protocol field)

我使用的是wireshark 1.8,python 2.7.3和scapy 2.2.0。

注意:我可以直接使用wireshark打开smaple.pcap文件。

如何让scapy生成的pcap文件在wireshark中打开?

修改 我尝试了其他pcap文件(来自wireshark捕获样本)并且它有效。似乎问题出在我的数据包中。这是第一个数据包(也不起作用):

###[ cooked linux ]###
  pkttype   = unicast
  lladdrtype= 0x1
  lladdrlen = 6
  src       = '\x00\x04\xed\xcb\x9b0'
  proto     = 0x800
###[ IP ]###
     version   = 4L
     ihl       = 5L
     tos       = 0xb8
     len       = 165
     id        = 47433
     flags     = 
     frag      = 0L
     ttl       = 49
     proto     = udp
     chksum    = 0x50c9
     src       = 22.31.32.55
     dst       = 192.168.1.102
     \options   \
###[ UDP ]###
        sport     = 4566
        dport     = 4566
        len       = 145
        chksum    = 0x0
###[ Raw ]###
           load      = 'H\x84\x80\x80\x80\x80\x80\x8c\x80\x80\x86\x81\x8b\x82\x80\x82\x81\x98\xb1\xb9\xb2\xae\xb1\xb6\xb8\xae\xb1\xae\xb2\xb5\xad\xb0\xb1\xb2\xb2\xb6\xb6\xb5\xb7\xb4\xb9\xb4\xad\x81\xca\x82\x89\xb9\xb9\xb5\xb0\xb6\xb1\xb0\xb3\xb3\xa6\x81\x80\xa7\x81\x80\xa8\x82\x80\x80\x84\x89\xb9\xb9\xb5\xb0\xb6\xb1\xb0\xb3\xb3\x8a\x82\xe5\xee\x86\x88\xe3\xe3\xec\xe9\xe5\xee\xf4\xb2\x89\x84\x80\x80\x81\x80\xb8\x89\x80\x80\x80\x80\x80\x80\x80\x81\x80\x88\x84\x80\x80\x81\x80\xb7\x89\x80\x80\x80\x80\x80\x80\x80\x81\x80\x8c\x82\x80\x82\x9f\x84\x9e\xa7 \xe2\xb6\x80'

注意:更改了IP地址,因此校验和可能不正确。

2 个答案:

答案 0 :(得分:4)

我不知道看起来是什么问题,但可以通过以下方式解决:

wireshark(pkt for pkt in pkts) # don't supply a list but rather a generator

这也会输出以下消息:

  

警告:PcapWriter:发电机的未知LL类型。使用类型1(以太网)

显然,wireshark功能并不能很好地处理Linux cooked-mode capture。这种奇怪的情况可能与scapy's wiki的以下摘录有关:

  

请记住,Wireshark使用第2层数据包(通常称为"帧")。所以我们必须在ICMP数据包中添加Ether()标头。将IP数据包(第3层)传递给Wireshark会产生奇怪的结果。

如果我们不关心第2层帧,我们也可以通过创建虚拟以太网层来解决这个问题:

pkts = [Ether(src=pkt[0].src)/pkt[1:] for pkt in pkts]

编辑 - 在进一步研究和分析scapy的源代码后,我想出了为什么传递生成器对象似乎可以解决这个问题。

wireshark函数创建一个包含数据包的临时文件,并使用该文件启动Wireshark。要在该文件的标题中指定的链接类型按以下方式提取:

if self.linktype == None:
    if type(pkt) is list or type(pkt) is tuple or isinstance(pkt,BasePacketList):
        pkt = pkt[0]
    try:
        self.linktype = conf.l2types[pkt.__class__]
    except KeyError:
        warning("PcapWriter: unknown LL type for %s. Using type 1 (Ethernet)" % pkt.__class__.__name__)
        self.linktype = 1

传递生成器对象时,第一个if语句的计算结果为False(这显然是一个错误),从{{1}开始尝试访问conf.l2types[pkt.__class__]时会引发异常是pkt.__class__。因此,执行<type 'generator'>代码块的except子句,并将链接类型指定为1。

但是,在传递真实列表时,第一个try-except语句的计算结果为if,并且提取列表的第一个数据包并用于访问True,这是:

conf.l2types

由于In [2]: conf.l2types Out[2]: 0x1 <- Dot3 (802.3) 0x1 <-> Ether (Ethernet) 0xc -> IP (IP) 0x17 -> Ether (Ethernet) 0x1f <-> IPv6 (IPv6) 0x65 <-> IP (IP) 0x69 <-> Dot11 (802.11) 0x71 -> CookedLinux (cooked linux) 0x77 <-> PrismHeader (Prism header) 0x7f <-> RadioTap (RadioTap dummy) 0x90 <-> CookedLinux (cooked linux) 0xc0 <-> PPI (Per-Packet Information header (partial)) 0x304 -> Ether (Ethernet) 0x321 -> Dot11 (802.11) 0x322 -> PrismHeader (Prism header) 0x323 -> RadioTap (RadioTap dummy) pkts[0].__class__,因此链接类型设置为scapy.layers.l2.CookedLinux而不是0x90(似乎是另一个错误),这导致Wireshark无法解析文件。


因此,我认为最好的方法是模仿scapy的0x71函数,允许用户明确指定链接类型的微妙变化:

wireshark

编辑 - 我现在已经注意到secdev的链接类型映射问题已经reported and fixed了。但是,它还没有达到def wireshark(*args, **kwargs): """Run wireshark on a list of packets""" f = scapy.all.get_temp_file() scapy.all.wrpcap(f, *args, **kwargs) subprocess.Popen([scapy.all.conf.prog.wireshark, "-r", f]) wireshark(pkts, linktype=0x71) 。我还在python-scapy中对生成器对象的无效处理创建了a new issue

答案 1 :(得分:0)

  

(libpcap:IrDA捕获的数据包包含无效的sll_protocol字段)

Linux IrDA使用之类的 Linux熟模式标题,但它不一样:

我不知道是什么导致你的程序选择144而不是113;你的输入文件是Linux IrDA文件而不是Linux熟的捕获文件吗?