虚拟PacketField:如何处理多态协议?

2024-09-29 19:34:22 发布

您现在位置:Python中文网/ 问答频道 /正文

今天请新用户帮忙。在

我正试着在斯卡比增加一个新的协议。这个原型有点特别,因为他是一个非常多形的人。我的意思是,他的结构和长度与某些场有关。通常,有一个'function'ByteField,更改此值将更改所有下一个字段。在

所以,让我们看看这段代码,它说明了我想做什么。有一个简单的多态数据包,其主常量结构为//header//parameter//data//。变量在参数和数据结构内部。在

### VIRTUAL PARAMETER PACKET
class myPacketParam(Packet):
    name = "Virtual Param Packet"

### REAL PARAMETER PACKET ONE
class myPacketParamOne(myPacketParam):
    name = "Parameter Type One"
    fields_desc = [
        ByteField("paramOne", 0x0),
        ByteField("paramTwo", 0x0)
    ]

### REAL PARAMETER PACKET TWO
class myPacketParamTwo(myPacketParam):
    name = "Parameter Type Two"
    fields_desc = [
        FieldLenField("length", None, length_of="stringOpt"),
        StrLenField("stringOpt", "BAGUETTE", # Random default value
                    length_from=lambda pkt: pkt.length)
    ]

### VIRTUAL DATA PACKET
class myPacketData(Packet):
    name = "Virtual Data Packet"

### REAL DATA PACKET ONE
class myPacketDataOne(myPacketData):
    name = "Data Type One"
    fields_desc = [
        ByteField("length", 2),
        ByteField("dataOne", 0x0),
        ByteField("dataTwo", 0x0)
    ]

### REAL DATA PACKET TWO
class myPacketDataTwo(myPacketData):
    name = "Data Type Two"
    fields_desc = [
        FieldLenField("length", None, length_of="data"),
        StrLenField("data", "SAUCISSON", length_from=lambda pkt: pkt.length) # Random default value
    ]

### MAIN PACKET
class myPacket(Packet):
    name = "myPacket"

    def changeFunction(self, value, data):
        if value == 0x1:
            self.param = myPacketParamOne()
            self.data = myPacketDataOne()
        else:
            self.param = myPacketParamTwo()
            self.data = myPacketDataTwo()

    fields_desc = [
        ByteField("version", 0x15),
        ActionField(ByteField("function", 0x1), "changeFunction"),
        FieldLenField("lengthParam", None, length_of="param"),
        FieldLenField("lengthData", None, length_of="data"),
        PacketField("param", myPacketParamOne(), myPacketParam),
        PacketField("data", myPacketDataOne(), myPacketData)
    ]

重点是主包myPacket中的“param”和“data”字段。例如,“param”packetfield正在询问myPacketParam包。但我希望这个包是虚拟的:后面真正的包可以是myPacketParamOne或myPacketParamTwo。数据也是一样。在

构建这个包看起来不错。在

^{pr2}$

但我想解剖是不能正常工作的。在

p.show2()

###[ myPacket ]###
  version   = 21
  function  = 2
  lengthParam= 10
  lengthData= 11
  \param     \
   |###[ Virtual Param Packet ]###
   |###[ Raw ]###
   |     load      = 'BAGUETTE\x00\tSAUCISSON'
  \data      \
   |###[ Data Type One ]###
   |  length    = 2
   |  dataOne   = 0
   |  dataTwo   = 0

这是完全错误的。在

我找到了一些解决办法。通过示例使用conditionalField。但在我真正的原型里,在同一个包里有很多形态。因为字段不能有相同的名称,所以在主数据包中没有一个简单的param字段,而是每个案例的新名称。所以,我的scapy实现的真正使用是非常无聊和不简单的。在

第二种解决方案是取消header、param和data的链接。所以可以使用这样的协议:p=myPacket()/myPacketParamOne()/myPacketDataOne()。但这对我来说并不是一个好的解决方案,因为我真正的协议在每个部分之间都有依赖关系,对于我的scapy实现的用户来说,它仍然很复杂。在

所以,如果可能的话,我正在寻找解决方案: -关于主要结构(标题/参数/数据) -这个协议的简单使用(myPacket.param.想要什么获取param而不考虑它是什么类型的param包(当然,在这种param packe中存在什么样的字段))

我觉得解决的办法可以是重新定义每个“虚拟包”中的do_dissect函数,或者专门为虚拟包编写一个新的域,但是我尝试了很多东西,都没有成功。在

我希望我是可以理解的。在

提前感谢:)

内森


Tags: nameselffieldsdataparampackettypelength
1条回答
网友
1楼 · 发布于 2024-09-29 19:34:22

(这有点老了^^)

自从Scapy的最新版本(为了安全起见,使用2.4.3rc+),我们有了一个新的MultipleTypeField,它似乎在做你想要的。下面是回归测试中的一个示例:

class DebugPacket(Packet):
    fields_desc = [
        ByteEnumField("atyp", 0x1, {0x1: "IPv4", 0x3: "DNS", 0x4: "IPv6"}),
        MultipleTypeField(
            [
                # IPv4
                (IPField("addr", "0.0.0.0"), lambda pkt: pkt.atyp == 0x1),
                # DNS
                (DNSStrField("addr", ""), lambda pkt: pkt.atyp == 0x3),
                # IPv6
                (IP6Field("addr", "::"), lambda pkt: pkt.atyp == 0x4),
            ],
            StrField("addr", "")  # By default
        ),
    ]

它允许您根据条件将同一字段具有多种类型

相关问题 更多 >

    热门问题