Scapy - 添加动态长度为

时间:2017-04-30 20:53:42

标签: python field conditional-statements scapy

我正在为Scapy添加一个新协议,我在具体领域遇到了困难。此字段指定包有效负载的长度。字段长度可以是1,2,3或4个字节,具体取决于有效负载的长度。另外,它是编码的。我发现确定字段大小是1,2,3或4字节的方式是取值的第一个字节,如果小于127,则字段由1个字节表示,如果大于127和小于x它由2个字节表示,依此类推(这是因为编码算法)。

所以,问题是我无法根据第一个字节的值动态定义这个字段长度。 我尝试的第一件事是使用ConditionalFields处理这个问题,但这感觉就像错误的路径。

    ConditionalField(ByteField("length",1), lambda pkt:pkt.length <= 127),
    ConditionalField(ShortField("length",None), lambda pkt:pkt.length > 127),]

我认为解决方案是定义一个新的Scapy Field,但我不知道如何访问第一个字节并根据它设置长度。任何提案将不胜感激。提前谢谢。

解码算法:

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

1 个答案:

答案 0 :(得分:1)

您需要在此处使用特定的field.addfield()方法实现自己的.getfield()。根据您的示例,以下是一个应该有效的示例:

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字段的图层:

class NewLayer(Packet):
    fields_desc = [
        VariableFieldLenField("length", None, length_of="data"),
        StrLenField("data", "", length_from=lambda pkt: pkt.length),
    ]

现在,检查一切的一些测试按预期工作:

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