我试图理解 PacketListField 和 FieldListField 之间的区别。有人可以让我知道在添加新协议(protocol)时如何使用它们吗?
我也不清楚StrLenField、FieldLenField和PacketLenField。我正在尝试制作一条 BGP 更新消息,以便我能够了解它是如何工作的。我看到这就是 BGPUpdate 消息的定义方式。当我尝试制作 BGP 数据包时,我不确定如何传递“撤回路由”字段和 nlri 字段的值。我也不确定如何传递路径属性的值。
>>> pkt=BGPUpdate()
>>> pkt.show()
###[ BGP Update fields ]###
withdrawn_len= None
withdrawn= []
tp_len= None
\total_path\
nlri= []
>>>
class BGPPathAttribute(Packet):
"the attribute of total path"
name = "BGP Attribute fields"
fields_desc = [
FlagsField("flags", 0x40, 8, ["NA0","NA1","NA2","NA3","Extended-Length","Partial","Transitive","Optional"]), #Extened leght may not work
ByteEnumField("type", 1, {1:"ORIGIN", 2:"AS_PATH", 3:"NEXT_HOP", 4:"MULTI_EXIT_DISC", 5:"LOCAL_PREF", 6:"ATOMIC_AGGREGATE", 7:"AGGREGATOR"}),
ByteField("attr_len", None),
StrLenField("value", "", length_from = lambda p: p.attr_len),
]
def post_build(self, p, pay):
if self.attr_len is None:
l = len(p) - 3 # 3 is regular length with no additional options
p = p[:2] + struct.pack("!B",l) +p[3:]
return p+pay
def extract_padding(self, p):
"""any thing after this packet is extracted is padding"""
return "",p
class BGPUpdate(Packet):
"""Update the routes WithdrawnRoutes = UnfeasiableRoutes"""
name = "BGP Update fields"
fields_desc = [
ShortField("withdrawn_len", None),
FieldListField("withdrawn",[], BGPIPField("","0.0.0.0/0"), length_from=lambda p:p.withdrawn_len),
ShortField("tp_len", None),
PacketListField("total_path", [], BGPPathAttribute, length_from = lambda p: p.tp_len),
FieldListField("nlri",[], BGPIPField("","0.0.0.0/0"), length_from=lambda p:p.underlayer.len - 23 - p.tp_len - p.withdrawn_len), # len should be BGPHeader.len
]
def post_build(self,p,pay):
wl = self.withdrawn_len
subpacklen = lambda p: len ( str( p ))
subfieldlen = lambda p: BGPIPField("", "0.0.0.0/0").i2len(self, p )
if wl is None:
wl = sum ( map ( subfieldlen , self.withdrawn))
p = p[:0]+struct.pack("!H", wl)+p[2:]
if self.tp_len is None:
l = sum ( map ( subpacklen , self.total_path))
p = p[:2+wl]+struct.pack("!H", l)+p[4+wl:]
return p+pay
最佳答案
它们只是对不同类型的对象进行操作。请参阅scapy build dissect
数据包列表字段
描述相同类型的PacketFields列表,而一个PacketField表示放入另一个数据包字段的Packet类型对象。它采用数据包原型(prototype)作为第三个参数 cls __init__(self, name, default, cls, count_from=None, length_from=None)
。 PacketListField 的构造函数需要设置 count_from (对象数量)或 lengt_from (字节)参数,以便了解要传递到数据包列表的字节数或要解析的对象数。(例如,您可以将 BGPUpdate
作为PacketField 或 PacketListField 的原型(prototype))。
例如:
PacketListField("total_path", [], BGPPathAttribute, length_from = lambda p: p.tp_len),
创建一个名为“total_path”的字段,默认值为空列表 [],并尝试将 raw_bytestream 的 length_from 字节解析为 BGPPathAttribute(Packet)。
FieldListField
相比之下,FieldListField 采用 Field 作为原型(prototype),并尝试将 raw_bytestream 剖析为原型(prototype)字段列表 __init__(self, name, default, field, length_from=None, count_from=None):
FieldListField("withdrawn",[], BGPIPField("","0.0.0.0/0"), length_from=lambda p:p.withdrawn_len),
StrLenField
数据字段通常最多可容纳 length_from 字节 __init__(self, name, default, fld=None, length_from=None):
.
FieldLenField
保存同一数据包中另一个字段长度的数字字段 __init__(self, name, default, length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None):
class SomePacket(Packet):
name = "SomePacket"
fields_desc = [ByteEnumField("type", 0x00, {0x00:"SomeType"}),
FieldLenField("length", None, length_of="data"), # hold length of data
StrLenField("data", "", length_from=lambda x:x.length), # holds data
]
在解剖时,scapy 会将第一个字节放入“type”,接下来的 2 个字节(默认 fmt="H"表示短整型“length”,直到“length” '字节到'数据'
构建时,scapy 将自动用 len(data) 填充“length”。
PacketLenField
是一个将length_from字节解析为一个原型(prototype)数据包__init__(self, name, default, cls, length_from=None):
的字段
class AnotherPacket(Packet):
name = "AnotherPacket"
fields_desc = [
BLenField("length", None, length_of="data"),
PacketLenField("data", None, SomePacket, length_from=lambda x:x.length),]
]
解析时,scapy 会将第一个字节放入 ByteLengthField 'length' 中,并将最多 'length' 个字节解析为 'SomePacket' 放入 'data'
构建时,scapy 将自动使用序列化 SomePacket 的大小填充“长度”。
关于python - Scapy 可变长度字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27163340/