Scapy: добавление нового протокола со сложными группировками полей

#python #scapy

#python #scapy

Вопрос:

Я пытаюсь указать новый формат пакета, используя scapy . В пакете есть список элементов, и элементы состоят из «сгруппированных полей». Под «сгруппированными полями» я подразумеваю подпоследовательность полей разных типов. Единственный известный мне способ создания «сгруппированных полей» в scapy — это использование Packet class и использование FieldLenField / PacketListField для указания длины последовательности и типа элементов списка. Это правильный путь? Что-то, что выглядит примерно так:

 from scapy.packet import Packet
from scapy.fields import *

class RepeatingGroupedSequence(Packet):
    name = "Simple group of two fields"

    fields_desc = [IntField('field1', 1), 
                   IntField('field2', 2)]

class TopLayer(Packet):
    name = "Storage for Repeating Sequence"

    fields_desc = [FieldLenField("length", None, count_of='rep_seq'),
                   PacketListField('rep_seq', None, RepeatingGroupedSequence, 
                                   count_from = lambda pkt: pkt.length),
                  ]

#Now here is the problem that I have with assembling PacketListField: 

#craft TopLayer packet
p = TopLayer()

#add two "repeated sequences"
p.rep_seq = [ RepeatingGroupedSequence(), RepeatingGroupedSequence() ]

#both sequences can observed
p.show()

#but the underlying structure of the repeated sequence is #Raw# at this stage
p.show2()

#length is 2
print p.rep_seq, 'length:', len(p.rep_seq)

#but the cloned packet has only one "repeated sequence", the rest is raw
clone = TopLayer(str(p))
clone.show()

#length is 1
print clone.rep_seq, 'length:', len(clone.rep_seq)
  

Проблема с этим подходом заключается в том, что структура группировки не сохраняется при повторной сборке пакета. При сборке второй экземпляр RepeatedSequence обрабатывается как исходное тело, даже если поле count равно 2. Как вы добавляете RepeatingSequences подобное, чтобы структура сохранялась при повторной сборке? Есть ли способ группировать поля, не прибегая к Packet в качестве типа хранения списков?

Комментарии:

1. Если кто-то использует FieldListField() для полей того же типа, проблема не проявляется сама по себе.

2. Также возможно добавлять Packet классы непосредственно в fields_desc

3. Достаточно безумно, если вместо IP class используется RepeatingGroupedSequence , все работает!

Ответ №1:

Классу RepeatingGroupedSequence необходимо перезаписать extract_padding метод:

 def extract_padding(self, s):
    return '', s
  

По умолчанию каждый подпакет рассматривает все как принадлежащее своему собственному уровню, т.Е.:

 def extract_padding(self, s):
    return s, None
  

И это не то, что используется для целей группировки. Может кто-нибудь подробнее рассказать о разнице между заполнением и разделением слоев?