python - Scapy 可变长度字段

标签 python scapy

我试图理解 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/

相关文章:

python - [ :] mean in the context of "for nm in namesList[:]:" 是什么意思

python - 矢量化代码与 numpy 中标准循环的不同结果

python - 在 scapy 中仅过滤 TCP SYN 段

python-3.x - Scapy 和 Python 3.2

python - 使用 nfqueue/scapy 更改 TCP 负载

python - Django - 手动构建 HttpResponse,但也想使用模板

python - 如何向 python 控制台提供输入并以编程方式验证输出?

python - 将巨大的 Keras 模型加载到 Flask 应用程序中

python - 无法使用 Scapy sendp() 发送 MPTCP 数据包

python - 使用 Scapy 更改数据包 - 在编辑数据包的有效负载后自动更新属性(长度、校验和等)