Create a BitField with dynamic bitwidth in scapy.

huangapple go评论73阅读模式
英文:

Create a BitField with dynamic bitwidth in scapy

问题

class CustomPacket(Packet):
    name="CustomPacket"
    fields_desc = [
        BitField("bitstring", 0, 8),
        BitField("offsets",0, length_from=xxx),
        BitField("_padding",0, length_from=xxx), # to make the whole pkt byte aligned 
   ]
class CustomPacket(Packet):
    name = "CustomPacket"
    offset_len = 6 # each offset part in the whole string shall be 6 bits long, e.g.
    bitstring_len = 8
    fields_desc = [
        BitField("bitstring", 0, bitstring_len),
        StrLenField(
            "offsetstring",
            0,
            length_from=lambda pkt: pkt._calculate_amount_of_offsets(),
        ),
        StrLenField(
            "_padding", 0, length_from=lambda pkt: pkt._calculate_needed_padding()
        ),
    ]

    def _calculate_amount_of_offsets(self):
        bits = "{0:08b}".format(self.bitstring)
        bits = [int(bit) for bit in list(bits)]
        return sum(bits) * self.offset_len

    def _calculate_needed_padding(self):
        offset_len = self._calculate_amount_of_offsets()
        if remainder:= offset_len % 8 != 0:
            return 8 - remainder
        else:
            return remainder
        
    def extract_padding(self, p):
        return "", p
英文:

I'm trying to implement a custom Packet type for scapy. My Problem is that I need BitFields with a dynamic width depending of another field in the packet:

class CustomPacket(Packet):
    name="CustomPacket"
    fields_desc = [
        BitField("bitstring", 0, 8),
        BitField("offsets",0, length_from=xxx),
        BitField("_padding",0, length_from=xxx), # to make the whole pkt byte aligned 
   ]

The length should depend on how much 1 are in the 8bit bitstring field.

I tried it with StrLenField but that didn't work as the length_from function returns the length in byte not bit, as I understand it:

class CustomPacket(Packet):
    name = "CustomPacket"
    offset_len = 6 # each offset part in the whole string shall be 6 bits long, e.g.
    bitstring_len = 8
    fields_desc = [
        BitField("bitstring", 0, bitstring_len),
        StrLenField(
            "offsetstring",
            0,
            length_from=lambda pkt: pkt._calculate_amount_of_offsets(),
        ),
        StrLenField(
            "_padding", 0, length_from=lambda pkt: pkt._calculate_needed_padding()
        ),
    ]

    def _calculate_amount_of_offsets(self):
        bits = "{0:08b}".format(self.bitstring)
        bits = [int(bit) for bit in list(bits)]
        return sum(bits) * self.offset_len

    def _calculate_needed_padding(self):
        offset_len = self._calculate_amount_of_offsets()
        if remainder:= offset_len % 8 != 0:
            return 8 - remainder
        else:
            return remainder
        
    # necessary for show2()
    def extract_padding(self, p):
        return "", p

Maybe I can somehow create a own FieldType, but I don't get how I can specify a length function there.

答案1

得分: 0

名字很糟糕,因为它说“Fixed”,但实际上它并没有固定,但你可以使用BitFixedLenField:https://scapy.readthedocs.io/en/latest/api/scapy.fields.html#scapy.fields.BitFixedLenField 来达到这个目的。

英文:

The name is terrible because it says Fixed where it's actually not fixed, but you can use BitFixedLenField: https://scapy.readthedocs.io/en/latest/api/scapy.fields.html#scapy.fields.BitFixedLenField for this purpose.

huangapple
  • 本文由 发表于 2023年6月13日 03:00:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76459564.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定