坚持使用Scapy文档中的VarLenQField示例

2024-10-04 09:18:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在看Adding new protocols的Scapy例子,我被卡住了。页面上显示的旧代码在Python3中抛出了一个错误,因为string->bytes转换,但这是一个小问题。我已经编写了自己的vlenq2str()str2vlenq()的实现。我分别称之为vlenq2m()m2vlenq()vlenq2m将整数值转换为字节(用于数据包的原始数据),并且m2vlenq将这些字节从数据包的原始数据转换回整数(作为一种内部表示)

我的实际问题是,在调用数据包的show2方法之后,scapy抛出了一个TypeError,我不知道为什么

下面是我的最简单的示例(scapy文档中代码的现代化版本):

#!/usr/bin/env python


from scapy.fields import Field, StrLenField
from scapy.packet import Packet, ls
from scapy.compat import raw


def vlenq2m(val: int) -> bytes:
    s = list()
    s.append(val & 0x7F)
    val = val >> 7
    while val:
        s.append(0x80 | (val & 0x7F))
        val = val >> 7
    s.reverse()
    return bytes(s)


def m2vlenq(m: bytes=b"") -> tuple[bytes, int]:
    i = l = 0
    for n in m:
        l = l << 7
        l = l + (n & 0x7F)
        i = i + 1
        if not n & 0x80:
            break
    return m[i + 1:], l


class VarLenQField(Field):
    """variable length quantities"""
    __slots__ = ["fld"]
    def __init__(self, name, default, fld):
        Field.__init__(self, name, default)
        self.fld = fld
    def i2m(self, pkt, x):
        if x is None:
            f = pkt.get_field(self.fld)
            x = f.i2len(pkt, pkt.getfieldval(self.fld))
            x = vlenq2m(x)
        return raw(x)
    def m2i(self, pkt, x):
        if s is None:
            return None, 0
        return m2vlenq(x)[1]
    def addfield(self, pkt, s, val):
        return s + self.i2m(pkt, val)
    def getfield(self, pkt, s):
        return m2vlenq(s)


class Foo(Packet):
    name = "Foo"
    fields_desc = [
            VarLenQField("len", None, "data"),
            StrLenField("data", "", "len"),
            ]


if __name__ == "__main__":
    f = Foo(data="test data")
    breakpoint()
    f.show2()

以下是错误堆栈:

$ python -i sominimal.py
Traceback (most recent call last):
  File "D:\Python\mlp-monitor\src\mlptc\sominimal.py", line 64, in <module>
    f.show2()
  File "C:\ProgramData\Anaconda3\envs\mmon\lib\site-packages\scapy\packet.py", line 1289, in show2
    return self.__class__(raw(self)).show(dump, indent, lvl, label_lvl)
  File "C:\ProgramData\Anaconda3\envs\mmon\lib\site-packages\scapy\base_classes.py", line 266, in __call__
    i.__init__(*args, **kargs)
  File "C:\ProgramData\Anaconda3\envs\mmon\lib\site-packages\scapy\packet.py", line 158, in __init__
    self.dissect(_pkt)
  File "C:\ProgramData\Anaconda3\envs\mmon\lib\site-packages\scapy\packet.py", line 875, in dissect
    s = self.do_dissect(s)
  File "C:\ProgramData\Anaconda3\envs\mmon\lib\site-packages\scapy\packet.py", line 839, in do_dissect
    s, fval = f.getfield(self, s)
  File "C:\ProgramData\Anaconda3\envs\mmon\lib\site-packages\scapy\fields.py", line 1380, in getfield
    len_pkt = self.length_from(pkt)
TypeError: 'NoneType' object is not callable

下面是我对调试程序的仔细检查,直到出现错误为止

$ python -i sominimal.py
> d:\python\mlp-monitor\src\mlptc\sominimal.py(65)<module>()
-> f.show2()
(Pdb) s
--Call--
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\packet.py(1277)show2()
-> def show2(self, dump=False, indent=3, lvl="", label_lvl=""):
(Pdb) n
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\packet.py(1289)show2()
-> return self.__class__(raw(self)).show(dump, indent, lvl, label_lvl)
(Pdb) s
--Call--
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\compat.py(50)raw()
-> def raw(x):
(Pdb) n
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\compat.py(53)raw()
-> return bytes(x)
(Pdb) n
--Return--
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\compat.py(53)raw()->b'\ttest data'
-> return bytes(x)
(Pdb) n
--Call--
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\base_classes.py(256)__call__()
-> def __call__(cls, *args, **kargs):
(Pdb) n
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\base_classes.py(257)__call__()
-> if "dispatch_hook" in cls.__dict__:
(Pdb) n
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\base_classes.py(265)__call__()
-> i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
(Pdb) s
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\base_classes.py(266)__call__()
-> i.__init__(*args, **kargs)
(Pdb) type(i)
<class '__main__.Foo'>
(Pdb) type(i.__init__)
<class 'method'>
(Pdb) n
TypeError: 'NoneType' object is not callable
> c:\programdata\anaconda3\envs\mmon\lib\site-packages\scapy\base_classes.py(266)__call__()
-> i.__init__(*args, **kargs)

Tags: pyselfreturnlibpackagesdefsiteval
1条回答
网友
1楼 · 发布于 2024-10-04 09:18:20

你非常接近。您只错过了一个小而奇怪的怪癖:在StrLenField中使用函数而不是字符串

class Foo(Packet):
    name = "Foo"
    fields_desc = [
        VarLenQField("len", None, "data"),
        StrLenField("data", "", length_from=lambda pkt: pkt.len)
    ]

还有,哇,页面上有一个使用字符串的错误示例。我会把它修好的

相关问题 更多 >