[Python] Concrete RTPExtension for Scapy

Discussão em 'Python' iniciado por Stack, Abril 4, 2025.

  1. Stack

    Stack Membro Participativo

    Scapy defines a RTP packet and a RTPExtension

    The RTPExtension is defined as follows:

    class RTPExtension(Packet):
    name = "RTP extension"
    fields_desc = [ShortField("header_id", 0),
    FieldLenField("header_len", None, count_of="header", fmt="H"), # noqa: E501
    FieldListField('header', [], IntField("hdr", 0), count_from=lambda pkt: pkt.header_len)] # noqa: E501


    I have a specific implementation of such an extension and want to be able to parse its header.

    The length of the header is always one and its fields is a list of 4 bit enums. It has a fixed header_id, let's say 0xABC.

    How can I implement this so that scapy parses/dissects the packet correctly?

    I've tried

    class MyRTPExtensionHeader(Packet):
    name = "My RTP extension header"
    fields_desc = [
    BitEnumField("field_a", 0, 4, enum_a),
    BitEnumField("field_b", 0, 4, enum_b),
    BitEnumField("field_c", 0, 4, enum_c),
    ...
    ]

    bind_layers(RTPExtension, MyRTPExtensionHeader, header=0xABC)

    RTP(...) / RTPExtension(...) / MyRTPExtensionHeader()


    But this way, the data of MyRTPExtensionHeader is in the payload field of RTPExtension and the length field of RTPExtension is not set correclty. Also the dissecting does not work as expected.

    So I tried to re-implement the RTP Extension and directly used it on tow:

    class MyRTPExtension(Packet):
    name = "My RTP extension header"
    fields_desc = [
    # Implement the fields from RTPExtension
    ShortField("header_id", 0xABC), # Header field set to my fixed header_id value
    FieldLenField("header_len", 1), # fixed length or count all remaining fields' length

    # My fields
    BitEnumField("field_a", 0, 4, enum_a),
    BitEnumField("field_b", 0, 4, enum_b),
    BitEnumField("field_c", 0, 4, enum_c),
    ...
    ]

    bind_layers(RTP, MyRTPExtension, extension=1)

    RTP(...) / MyRTPExtension()


    This way I can build my packets correctly. But when I load an RDP packet from a string, the Packet type is not correct. It will always use the generic RTPExtension. I need to somehow tell scapy to use MyRTPExtension if the header_id inside the extension is 0xABC and otherwise the generic RTPExtension. How can I achieve this?

    EDIT


    The only solution I found so far is to patch RTP.guess_payload_class. Is there some more elegant/straightforward way?

    def rtp_modified_guess_payload_class(self, pkt):
    if self.extension:
    if pkt.startswith(b'\x01g'):
    return MyRTPExtension
    else:
    return RTPExtension

    RTP.guess_payload_class = rtp_modified_guess_payload_class

    Continue reading...

Compartilhe esta Página