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, но я не знаю, как получить доступ к первому байту и настроить длину на основе этого. Любое предложение будет оценено. Заранее спасибо.
Алгоритм декодирования:
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 ответ
Вы должны реализовать свой собственный 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