Scapy可变长度字段

时间:2014-11-27 04:57:35

标签: python scapy

我试图理解PacketListField和FieldListField之间的区别。有人可以在添加新协议时告诉我如何使用它们。

我也不清楚StrLenField,FieldLenField和PacketLenField。我正在尝试制作BGP更新消息,以便我可以理解它是如何工作的。我看到这是BGPUpdate消息的定义方式。当我尝试制作BGP数据包时,我不知道如何传递Withdrawn Routes字段和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

1 个答案:

答案 0 :(得分:3)

他们只对不同类型的物体进行操作。见scapy build dissect

PacketListField

描述了相同类型的 PacketFields 列表,而一个 PacketField 表示放入另一个数据包字段的 Packet 类型对象。它将Packet原型作为第三个参数 cls __init__(self, name, default, cls, count_from=None, length_from=None)。 PacketListField的构造函数要求设置count_from(对象数)或lengt_from(字节)参数,以便知道要传递给数据包列表的字节数或要解析的对象数(例如,您可以{{1} }作为PacketField或PacketListField的原型)。

例如:

BGPUpdate

创建一个名为" total_path"的字段,默认值为空列表[],并尝试将raw_bytestream的length_from字节解析为BGPPathAttribute(Packet)。

<强> FieldListField

相反, FieldListField 将Field作为原型,并尝试将raw_bytestream剖析为原型字段列表PacketListField("total_path", [], BGPPathAttribute, length_from = lambda p: p.tp_len),

__init__(self, name, default, field, length_from=None, count_from=None):

<强> StrLenField

DataField通常最多支持length_from bytes FieldListField("withdrawn",[], BGPIPField("","0.0.0.0/0"), length_from=lambda p:p.withdrawn_len),

<强> FieldLenField

保存同一数据包__init__(self, name, default, fld=None, length_from=None):

中另一个字段长度的数字字段
__init__(self, name, default,  length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None):

在剖析上,scapy会将第一个字节放入&#39;输入&#39;,接下来的2个字节(默认fmt =&#34; H&#34;简称为短?整数&#34;长度&#34;,以及长达&#39;字节到&#39;数据&#39;

在构建时,scapy会自动填充&#39;长度&#39;与len(数据)。

<强> PacketLenField

是一个将length_from bytes解析为一个原型包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 ]

的字段
__init__(self, name, default, cls, length_from=None):

在剖析上,scapy会将第一个字节放入ByteLengthField&#39;长度&#39;最长的&#39;长度&#39;字节被解剖为&#39; SomePacket&#39;进入&#39;数据&#39;

在构建时,scapy会自动填充&#39;长度&#39;与序列化的SomePacket的大小。