坚持使用 Scapy 文档中的 VarLenQField 示例
Stuck with VarLenQField example from Scapy's documentation
我正在查看 Adding new protocols 的 Scapy 示例,但我被卡住了。由于 string->bytes
转换,他们页面上显示的旧代码在 Python 3 中抛出错误,但这是小事。我已经编写了自己的 vlenq2str()
和 str2vlenq()
实现。我分别称它们为 vlenq2m()
和 m2vlenq()
。 vlenq2m
将整数值转换为字节(用于数据包的原始数据),m2vlenq
将这些字节从数据包的原始数据转换回整数(作为 scapy 内部表示)。
我的实际问题是,在调用数据包的 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)
你非常接近。您只错过了一个小而奇怪的怪癖:在 StrLenField
中使用函数而不是字符串
class Foo(Packet):
name = "Foo"
fields_desc = [
VarLenQField("len", None, "data"),
StrLenField("data", "", length_from=lambda pkt: pkt.len)
]
还哇,页面上有一个使用字符串的错误示例。我会修好的
我正在查看 Adding new protocols 的 Scapy 示例,但我被卡住了。由于 string->bytes
转换,他们页面上显示的旧代码在 Python 3 中抛出错误,但这是小事。我已经编写了自己的 vlenq2str()
和 str2vlenq()
实现。我分别称它们为 vlenq2m()
和 m2vlenq()
。 vlenq2m
将整数值转换为字节(用于数据包的原始数据),m2vlenq
将这些字节从数据包的原始数据转换回整数(作为 scapy 内部表示)。
我的实际问题是,在调用数据包的 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)
你非常接近。您只错过了一个小而奇怪的怪癖:在 StrLenField
class Foo(Packet):
name = "Foo"
fields_desc = [
VarLenQField("len", None, "data"),
StrLenField("data", "", length_from=lambda pkt: pkt.len)
]
还哇,页面上有一个使用字符串的错误示例。我会修好的