Scapy-添加具有动态长度的新字段 [英] Scapy - adding a new field with a dynamic length
问题描述
我正在为Scapy添加新协议,但在具体领域遇到困难。该字段指定包裹有效载荷的长度。该字段的长度可以为1、2、3或4个字节,具体取决于有效负载的长度。此外,它被编码。我发现确定字段大小是1、2、3或4个字节的方法是采用值的第一个字节,如果小于127,则该字段由1个字节表示,如果大于127并且小于x,它由2个字节表示,依此类推(这是因为编码算法)。
I am adding a new protocol to Scapy and I am having difficulties with a concrete field. This field specifies the length of a package payload. The field can be 1, 2, 3 or 4 bytes long depending on the length of the payload. Additionally, it is encoded. The way I found to determine if the size of the field is 1, 2, 3 or 4 bytes, is taking the first byte of the value and if it is less than 127 the field is represented by 1 byte, if it is more than 127 and less than x it is represented by 2 bytes and so on (this is because the encoding algorithm).
因此,问题是我无法定义此字段长度根据第一个字节的值动态变化。
我尝试的第一件事是使用 ConditionalFields
处理此问题,但是这感觉是错误的路径。
So, the problem is that I can't define this field length dynamically based on the value of the first byte.
The first thing I tried is handling this problem with ConditionalFields
, but this feels like the wrong path.
ConditionalField(ByteField("length",1), lambda pkt:pkt.length <= 127),
ConditionalField(ShortField("length",None), lambda pkt:pkt.length > 127),]
我认为解决方案是定义一个新的Scapy字段,但是我不知道如何访问第一个字节并根据该长度设置长度。任何建议将不胜感激。
I think the solution is to define a new Scapy Field, but I don't know how to access the first byte and setup the length based on that. Any proposal will be appreciated. Thanks in advance.
解码算法:
def test(encoded_byte):
if((encoded_byte & 128) != 0):
return True
else:
return False
def decoding(bytes):
multiplier = 1
value = 0
offset = 0
condition = True
while condition:
encoded_byte = bytes[offset]
value += (encoded_byte & 127) * multiplier
multiplier *= 128
if multiplier > 128 ** 3:
raise Exception('Malformed Remaining Length')
offset += 1
condition = test(encoded_byte)
return value
推荐答案
您需要实现自己的 field
,使用特定的 .addfield()
和 .getfield()
方法。根据您的示例,这是一个应该起作用的示例:
You need to implement your own field
here, with specific .addfield()
and .getfield()
methods. Based on your example, here is an example that should work:
class VariableFieldLenField(FieldLenField):
def addfield(self, pkt, s, val):
val = self.i2m(pkt, val)
data = []
while val:
if val > 127:
data.append(val & 127)
val /= 127
else:
data.append(val)
lastoffset = len(data) - 1
data = "".join(chr(val | (0 if i == lastoffset else 128))
for i, val in enumerate(data))
return s + data
if len(data) > 3:
raise Scapy_Exception("%s: malformed length field" %
self.__class__.__name__)
def getfield(self, pkt, s):
value = 0
for offset, curbyte in enumerate(s):
curbyte = ord(curbyte)
value += (curbyte & 127) * (128 ** offset)
if curbyte & 128 == 0:
return s[offset + 1:], value
if offset > 2:
raise Scapy_Exception("%s: malformed length field" %
self.__class__.__name__)
现在完成了最困难的工作,您只需要创建一个使用 VariableFieldLenField
字段的图层:
Now the hardest part of the job has been done, you just need to create a layer that uses VariableFieldLenField
field:
class NewLayer(Packet):
fields_desc = [
VariableFieldLenField("length", None, length_of="data"),
StrLenField("data", "", length_from=lambda pkt: pkt.length),
]
现在,一些检查所有功能的测试均按预期进行:
And now, some tests to check everything works as expected:
NewLayer('\x01x')
str(_)
NewLayer(_)
NewLayer(data='x')
str(_)
NewLayer(_)
NewLayer(data='x' * 128)
str(_)
NewLayer(_)
str(NewLayer(data='x' * 16385))[:10]
NewLayer(str(NewLayer(data='x' * 16385))).length
这篇关于Scapy-添加具有动态长度的新字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!