使用 scapy 数据包字段
Using scapy packetfields
我正在 scapy 中构建一个新的协议层。我正在使用数据包字段来表示协议中的 len-value 对。我可以获得该层来构建数据包。 .show()
和 hexdump()
按预期显示数据包字段。 .show2()
然而又是另外一回事了。
我也有类似的东西:
class bar(Packet):
name="Bar Packet"
fields_desc = [
FieldLenField("len", None, length_of="val", fmt="!H"),
StrLenField("val", "", length_from=lambda p:p.len)
]
class foo(Packet):
name="Foo Packet"
fields_desc = [
XByteField("fld1", 0x00),
XByteField("fld2", 0x00),
PacketField("fld3", '', bar),
PacketField("fld4", '', bar),
PacketField("fld5", '', bar),
XByteField("fld6", 0x00),
XByteField("fld7", 0x00)
]
如果我这样构建数据包:
p = foo()
p.fld3 = bar(val="one")
p.fld4 = bar(val="two")
p.fld5 = bar(val="three")
p.show()
和 hexdump(p)
按预期工作。
然而,p.show2()
可以很好地构建数据包,但无法解析数据包字符串。字段 1 - 3 按预期剖析(fld3.len
甚至得到正确计算)。解剖到此为止。剩余字节成为 fld3 的原始有效负载,字段 4 - 7 什么也没有。
我已经尝试 bind_layers(foo, bar)
并得到相同的结果。基于阅读此处、scapy 文档和各种 scapy 协议文件,我认为 bar.post_dissect()
中需要做一些事情,但我不确定是什么。
如何让 bar
将其剩余的原始有效载荷交还给 foo
以供进一步剖析?
我已经解决了,我只是在 class 栏中添加了一个 extract_padding 函数,代码如下:
class Bar(Packet):
name = "Bar Packet"
fields_desc = [
FieldLenField("len", None, length_of="val", fmt="!H"),
StrLenField("val", 0, length_from=lambda pkt:pkt.len)
]
def extract_padding(self, p):
return "", p
class Foo(Packet):
name = "Foo Packet"
fields_desc = [
XByteField("fld1", 0x00),
XByteField("fld2", 0x00),
PacketField("fld3", "", Bar),
PacketField("fld4", "", Bar),
PacketField("fld5", "", Bar),
XByteField("fld6", 0x00),
XByteField("fld7", 0x00)
]
如果您查看 Scapy 文档,它会告诉您:
- extract_padding() 是一个重要的函数,每个包含自己大小的层都应该调用它,这样它就可以在有效负载中区分什么与该层真正相关,什么将被视为额外的填充字节。
我运行这个代码,这是结果:
###[ Foo Packet ]###
fld1 = 0x0
fld2 = 0x0
\fld3 \
|###[ Bar Packet ]###
| len = 3
| val = 'one'
\fld4 \
|###[ Bar Packet ]###
| len = 3
| val = 'two'
\fld5 \
|###[ Bar Packet ]###
| len = 5
| val = 'three'
fld6 = 0x0
fld7 = 0x0
进程已完成,退出代码为 0
我正在 scapy 中构建一个新的协议层。我正在使用数据包字段来表示协议中的 len-value 对。我可以获得该层来构建数据包。 .show()
和 hexdump()
按预期显示数据包字段。 .show2()
然而又是另外一回事了。
我也有类似的东西:
class bar(Packet):
name="Bar Packet"
fields_desc = [
FieldLenField("len", None, length_of="val", fmt="!H"),
StrLenField("val", "", length_from=lambda p:p.len)
]
class foo(Packet):
name="Foo Packet"
fields_desc = [
XByteField("fld1", 0x00),
XByteField("fld2", 0x00),
PacketField("fld3", '', bar),
PacketField("fld4", '', bar),
PacketField("fld5", '', bar),
XByteField("fld6", 0x00),
XByteField("fld7", 0x00)
]
如果我这样构建数据包:
p = foo()
p.fld3 = bar(val="one")
p.fld4 = bar(val="two")
p.fld5 = bar(val="three")
p.show()
和 hexdump(p)
按预期工作。
然而,p.show2()
可以很好地构建数据包,但无法解析数据包字符串。字段 1 - 3 按预期剖析(fld3.len
甚至得到正确计算)。解剖到此为止。剩余字节成为 fld3 的原始有效负载,字段 4 - 7 什么也没有。
我已经尝试 bind_layers(foo, bar)
并得到相同的结果。基于阅读此处、scapy 文档和各种 scapy 协议文件,我认为 bar.post_dissect()
中需要做一些事情,但我不确定是什么。
如何让 bar
将其剩余的原始有效载荷交还给 foo
以供进一步剖析?
我已经解决了,我只是在 class 栏中添加了一个 extract_padding 函数,代码如下:
class Bar(Packet):
name = "Bar Packet"
fields_desc = [
FieldLenField("len", None, length_of="val", fmt="!H"),
StrLenField("val", 0, length_from=lambda pkt:pkt.len)
]
def extract_padding(self, p):
return "", p
class Foo(Packet):
name = "Foo Packet"
fields_desc = [
XByteField("fld1", 0x00),
XByteField("fld2", 0x00),
PacketField("fld3", "", Bar),
PacketField("fld4", "", Bar),
PacketField("fld5", "", Bar),
XByteField("fld6", 0x00),
XByteField("fld7", 0x00)
]
如果您查看 Scapy 文档,它会告诉您:
- extract_padding() 是一个重要的函数,每个包含自己大小的层都应该调用它,这样它就可以在有效负载中区分什么与该层真正相关,什么将被视为额外的填充字节。
我运行这个代码,这是结果:
###[ Foo Packet ]###
fld1 = 0x0
fld2 = 0x0
\fld3 \
|###[ Bar Packet ]###
| len = 3
| val = 'one'
\fld4 \
|###[ Bar Packet ]###
| len = 3
| val = 'two'
\fld5 \
|###[ Bar Packet ]###
| len = 5
| val = 'three'
fld6 = 0x0
fld7 = 0x0
进程已完成,退出代码为 0