绕过Python Scapy中的一些数据包层

时间:2014-04-13 20:08:05

标签: python python-2.7 packet scapy

我想用Vlan部分构建一个IP数据包。 Scapy很容易做到:

from scapy import inet
newpkt = inet.Ether()/inet.Dot1Q()/inet.IP()

有时候我希望在数据包中有inet.Dot1Q(),有时候没有。 inet.Dot1Q()的默认值应该是什么,因此只需在操作符中绕过' /&#39 ;? 我尝试了''None - 他们不能工作。

from scapy import inet
myDot1Q = SOME DEFAULT VALUE
newpkt = inet.Ether()/myDot1Q/inet.IP()
#new packet is a valid IP packet here

编辑:对我的问题的不同解释

1)我可以使用VLAN标记

创建数据包
inet.Ether()/inet.Dot1Q/inet.IP()

2)我可以创建一个带有双VLAN标记的数据包

inet.Ether()/inet.Dot1Q/inet.Dot1Q/inet.IP()

3)如何构建可能是未标记数据包,VLAN标记数据包或双VLAN标记数据包的数据包?有这样的东西会很棒:

#No VLAN
myVlan = ???
myDoubleVlan = ???

#VLAN
myVlan = inet.Dot1Q()
myDoubleVlan = ???

#Double VLAN
myVlan = inet.Dot1Q()
myDoubleVlan = inet.Dot1Q()

#In any case the packet structure should remain the same
inet.Ether()/myVlan/myDoubleVlan/inet.IP()

我无法弄清楚默认值???应该能够正确构建数据包。

2 个答案:

答案 0 :(得分:4)

首先,我无法想出为什么你不会使用这样一个简单的解决方案:

# example for single Vlan
# myVlan = Dot1Q()
# myDoubleVlan = None

# generate the package
package = Ether()
if myVlan: package /= myVlan
if myDoubleVlan: package /= myDoubleVlan
package /= IP()

但无论如何,如果这种方法出于任何不可接受的原因,还有另一种可能性......
您可以覆盖Packet类并创建属于除法运算符中立的类。您唯一需要的是覆盖__div__方法并添加一些括号以保留正确的优先级。

这是你实现它的方式:

from scapy.all import *

class NeutralPacket(Packet):
    def __init__(self,  _pkt="", _internal=0, **fields):
        super(NeutralPacket, self).__init__(_pkt, _internal, **fields)
    def __div__(self, other):
        return other

#No VLAN
myVlan = NeutralPacket()
myDoubleVlan = NeutralPacket()

#VLAN
myVlan = Dot1Q()
myDoubleVlan = NeutralPacket()

#Double VLAN
myVlan = Dot1Q()
myDoubleVlan = Dot1Q()

# this part doesn't need to change, but you need to have two
# additional parenthesis for proper precedence
Ether()/(myVlan/(myDoubleVlan/IP()))

补充说明:

__div__()方法是分区operator实施。解释器将a/b作为a.__div__(b)执行,Packet类具有自己的此运算符实现。如果您查看其code,可以看到它基本上将payload包裹b附加到a包。 我们在这里所做的只是返回other包,在这种情况下为b,有效地完全忽略a
请注意,当NeutralPacket是左侧操作员时,这仅适用于一个方向,因为否则它会影响其他一些类别的操作。正在执行的__div__()方法。为了解决这个问题,我们必须添加括号,以便优先级使我们的NeutralPacket类始终是左侧运算符。由于Packet的实现不会对整体结果产生影响,因此适用于您的情况。唯一不起作用的是NeutralPacket是最右手边(即最后一个)算子,从那时起你就不能强制执行正确的优先权。但是对于VLAN来说这不是问题,因为它上面总是有层......

答案 1 :(得分:1)

我完全忘记了Raw()

Raw图层就是您想要的。

Raw(),如果没有放置数据,则不会对构建的数据包添加任何内容。您可以将其用作myDot1Q变量的默认值。

>>> b = Raw() / ICMP()
>>> a = Raw() / ICMP()
>>> b = ICMP()
>>> a.show()
###[ Raw ]###
  load= ''
###[ ICMP ]###
     type= echo-request
     code= 0
     chksum= None
     id= 0x0
     seq= 0x0
>>> b.show()
###[ ICMP ]###
  type= echo-request
  code= 0
  chksum= None
  id= 0x0
  seq= 0x0
>>> a.build()
'\x08\x00\xf7\xff\x00\x00\x00\x00'
>>> b.build()
'\x08\x00\xf7\xff\x00\x00\x00\x00'
>>> a.build() == b.build()
True