Scapy - 从 FieldLenField 引用多个字段

Scapy - Referencing multiple fields from a FieldLenField

我遇到了下一种情况,我需要在 Scapy 中定义一个新的协议层,其中一个字段的大小可变(1、2、3 或 4 字节),这取决于其他特定层的大小.是这样的情况:

class newLayer(Packet):
      name = "newLayer fixed header"
      fields_desc = [
          ByteField("msgtype",0),
              # Some other fields ...
          FieldLenField("length", XXX), # length of newLayer_specific layer
                        # This field can be 1,2,3 or 4 bytes long depending
                        # on the length of the variable header
        ]

class newLayer_specific(Packet):
      name = "variable header"
      fields_desc = [
              FieldLenField("length2","field1"), # This field is always 2 bytes long
              StrLenField("field1","",length_from = lambda pkt:pkt.length2),
              StrLenField("field2","", length_from = lambda pkt:pkt.underlayer.length - pkt.length - 2)
              # 2 is because the length of the length2 field 

bind_layers(newLayer, newLayer_specific, msgtype=1)

我不知道如何从 newLayer 层的字段 length 中引用 newLayer_specific 层的大小 有什么建议吗?提前致谢。

由于您在 newLayernewLayerSpecific 之间使用了无条件层绑定,也许我们可以使用一个层。在那种情况下,我会使用 adjust 参数来处理此处的长度:

class NewLayer(Packet):
    name = "NewLayer"
    fields_desc = [
        FieldLenField("length", None, length_of="field2",
                      adjust=lambda pkt, val: val + 2 + len(pkt.field1)),
        FieldLenField("length_field1", None, length_of="field1"),
        StrLenField("field1", "", length_from=lambda pkt: pkt.length_field1),
        StrLenField("field2", "",
                    length_from=lambda pkt: pkt.length - pkt.length_field1 - 2),
    ]

现在,我们可以通过运行来测试结果:

NewLayer(field1="test", field2="tototiti")
str(_)
NewLayer(_)

如果您的第一个长度字段的大小可变,您只需将 FieldLenField 替换为您必须实施的 VariableFieldLenField(可以在 中找到示例)。

如果出于某种原因,您不能或不想只使用一层,我的建议是:您可以 "cheat" 加上 length_of 参数,并使用 adjust 参数来完成工作:

class NewLayer(Packet):
    name = "NewLayer"
    fields_desc = [
        FieldLenField("length", None, length_of="length",
                      adjust=lambda pkt, x: len(pkt.payload)),
    ]

class NewLayerSpecific(Packet):
    name = "NewLayer Specific"
    fields_desc = [
        FieldLenField("length_field1", None, length_of="field1"),
        StrLenField("field1", "", length_from=lambda pkt: pkt.length_field1),
        StrLenField("field2", "",
                    length_from=lambda pkt: (pkt.underlayer.length
                                             - pkt.length_field1 - 2),
        ),
    ]

bind_layers(NewLayer, NewLayerSpecific)

再次,我们可以测试:

NewLayer()/NewLayerSpecific(field1="test", field2="tototiti")
str(_)
NewLayer(_)