Расширенные поля при создании слоя Scapy (цепочка байтов) - PullRequest
1 голос
/ 12 марта 2019

Я пытаюсь создать слой в Scapy для протокола, который имеет тип настраиваемого поля, называемый «Расширенное поле».

Принцип довольно прост, но я борюсь с реализацией.

Принцип:

  • Первый байт поля находится в известной позиции, за которой следует переменное число байтов.
  • Количество байтов не определено нигде в кадре.
  • Если младший бит байта равен "1", то следующий байт является частью поля
  • Если младший бит байта равен "0", то это конец поля.
  • Результатом является битовое поле с сцепленными 7 битами MSB каждого байта

Я сделал картинку, чтобы сделать ее проще:

Расширенное описание поля

Я много читал о полях переменной длины в Scapy, но, насколько я понимаю, это не относится к этому случаю.

Как вы думаете, это может быть реализовано в Scapy Layer? Любая помощь будет оценена.

1 Ответ

0 голосов
/ 20 марта 2019

Хорошо, я отвечаю себе после небольшого количества копаний в Scapy.

Вот решение, которое работает (возможно, не оптимально, но достаточно для меня):

from scapy.all import *

class LSBExtendedField(Field):
    """
    LSB Extended Field
    ------------------

    This type of field has a variable number of bytes. Each byte is defined as follows:
    - The 7 MSB bits are data
    - The LSB is an extenesion bit
        * 0 means it is last byte of the field ("stopping bit")
        * 1 means there is another byte after this one ("forwarding bit")

    To get the actual data, it is necessary to navigate the binary data byte per byte and to check if LSB until 0
    """

    """
    Converts bytes to field
    """
    def str2extended(self, l=""):
        s = []
        # First bit is the stopping bit at zero
        bits = 0b0
        # Then we retrieve 7 bits. If "forwarding bit" is 1, then we continue on another byte
        i = 0
        for c in l:
            s.append(hex(c & 0xfe))
            bits = bits << 7 | (int(c) >> 1)
            if not int(c)&0b1:
                end = l[i+1:]
                break
            i=i+1
        return end, bits

    """
    Converts field to bytes
    """
    def extended2str(self, l):
        l=int(l)
        s = []
        # First bit is the stopping bit at zero
        bits = 0b0
        # Then we group bits 7 by 7 adding the "forwarding bit" if necessary
        i=1
        while (l>0):
            if i%8 == 0:
                s.append(bits)
                bits = 0b1
                i=0
            else:
                bits = bits | (l & 0b1) << i
                l = l >> 1
            i = i+1
        s.append(bits)
        s.reverse()

        result = "".encode()
        for x in s:
            result = result + struct.pack(">B", x)
        return result

    def i2m(self, pkt, x):
        return self.extended2str(x)

    def m2i(self, pkt, x):
        return self.str2extended(x)[1]

    def addfield(self, pkt, s, val):
        return s+self.i2m(pkt, val)

    def getfield(self, pkt, s):
        return self.str2extended(s)
...