Example #1
0
 def __init__(self, name, default, length=None, length_from=None, max_length=None, null_terminated=None):
     if null_terminated:
         self.null_terminated = null_terminated
     else:
         self.null_terminated = lambda pkt: True
     self.max_length = max_length or 200
     StrFixedLenField.__init__(self, name, default, length=length, length_from=length_from)
Example #2
0
 def randval(self):
     if self.null_terminated:
         try:
             l = self.length_from(None) - 1
         except:
             l = RandTermString(RandNum(0, self.max_length), "\x00")
         return RandBin(l)
     return StrFixedLenField.randval(self)
Example #3
0
class SAPMSStat3(PacketNoPadded):
    """SAP Message Server Statistics version 3

    Packet that contains statistics information of the Message Server service.
    This packet is for version 3.
    """
    # TODO: The fields on this packet are not correctly defined
    name = "SAP Message Server Statistics version 3"
    fields_desc = [
        ByteField("active", 0),
        ByteField("version", 0),
        ShortField("unused1", 0),
        IntField("no_requests", 0),
        StrFixedLenField("no_requests_padd", "", 12),
        IntField("no_error", 0),
        StrFixedLenField("no_error_padd", "", 4),
        IntField("no_login", 0),
        StrFixedLenField("no_login_padd", "", 4),
        IntField("no_logout", 0),
        StrFixedLenField("no_logout_padd", "", 4),
        IntField("no_send_by_name", 0),
        StrFixedLenField("no_send_by_name_padd", "", 4),
        IntField("no_send_by_type", 0),
        StrFixedLenField("no_send_by_type_padd", "", 4),
        IntField("no_adm_messages", 0),
        StrFixedLenField("no_adm_messages_padd", "", 4),
        IntField("no_adms", 0),
        StrFixedLenField("no_amds_padd", "", 4),
        StrFixedLenField("no_adm_type", "", 648),
        IntField("no_mod_types", 0),
        StrFixedLenField("no_mod_types_padd", "", 4),
        IntField("no_opcodes_rcvd", 0),
        StrFixedLenField("no_opcodes_rcvd_padd", "", 4),
        IntField("no_opcodes_send", 0),
        StrFixedLenField("no_opcodes_send_padd", "", 4),
        IntField("no_opcodes", 0),
        StrFixedLenField("no_opcode_type", "", 408),
        IntField("no_keepalive_send", 0),
        StrFixedLenField("no_keepalive_send_padd", "", 4),
        IntField("no_keepalive_rcvd", 0),
        StrFixedLenField("no_keepalive_rcvd_padd", "", 4),
        IntField("no_keepalive_disc", 0),
        StrFixedLenField("no_keepalive_disc_padd", "", 4),
        IntField("no_bytes_read", 0),
        StrFixedLenField("no_bytes_read_padd", "", 12),
        IntField("no_bytes_written", 0),
        StrFixedLenField("no_bytes_written_padd", "", 12),
        IntField("no_clients", 0),
        StrFixedLenField("sta_time", "", 30),
        StrFixedLenField("act_time", "", 30),
    ]
Example #4
0
class SAPMS(Packet):
    """SAP Message Server packet

    This packet is used for the Message Server protocol.
    """
    name = "SAP Message Server"
    fields_desc = [
        StrFixedLenField("eyecatcher", "**MESSAGE**\x00", 12),
        ByteField("version", 0x04),
        ByteEnumKeysField("errorno", 0x00, ms_errorno_values),
        StrFixedLenField("toname", "-" + " " * 39, 40),
        FlagsField("msgtype", 0, 8,
                   ["DIA", "UPD", "ENQ", "BTC", "SPO", "UP2", "ATP", "ICM"]),
        ByteField("reserved", 0x00),
        ByteEnumKeysField("domain", 0x00, ms_domain_values),
        ByteField("reserved", 0x00),
        StrFixedLenField("key", "\x00" * 8, 8),
        ByteEnumKeysField("flag", 0x01, ms_flag_values),
        ByteEnumKeysField("iflag", 0x01, ms_iflag_values),
        StrFixedLenField("fromname", "-" + " " * 39, 40),
        ConditionalField(ShortField("diag_port", 3200),
                         lambda pkt: pkt.iflag == 0x08 and pkt.flag == 0x02
                         ),  # for MS_REQUEST+MS_LOGIN_2 it's the diag port
        ConditionalField(ShortField("padd", 0x0000),
                         lambda pkt: pkt.iflag != 0x08 or pkt.flag != 0x02),

        # OpCode fields
        ConditionalField(
            ByteEnumKeysField("opcode", 0x01, ms_opcode_values),
            lambda pkt: pkt.iflag in [0x00, 0x01, 0x02, 0x07]
        ),  # extending all those fields with MS_SEND_TYPE and MS_SEND_TYPE_ONCE packets
        ConditionalField(
            ByteEnumKeysField("opcode_error", 0x00, ms_opcode_error_values),
            lambda pkt: pkt.iflag in [0x00, 0x01, 0x02, 0x7]),
        ConditionalField(ByteField("opcode_version", 0x01),
                         lambda pkt: pkt.iflag in [0x00, 0x01, 0x02, 0x07]),
        ConditionalField(ByteField("opcode_charset", 0x03),
                         lambda pkt: pkt.iflag in [0x00, 0x01, 0x02, 0x07]),
        ConditionalField(
            StrField("opcode_value", ""),
            lambda pkt: pkt.iflag in [0x00, 0x01] and pkt.opcode not in [
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                0x0a, 0x11, 0x1c, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
                0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2f, 0x43, 0x44, 0x45, 0x46,
                0x47, 0x4a
            ]),
        ConditionalField(
            StrField("opcode_trailer", ""),
            lambda pkt: pkt.iflag in [0x00, 0x01] and pkt.opcode not in [
                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                0x0a, 0x11, 0x1c, 0x1e, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
                0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2f, 0x43, 0x44, 0x45,
                0x46, 0x47, 0x4a
            ]),

        # Dispatcher info
        ConditionalField(
            ByteField("dp_version", 0x0), lambda pkt: pkt.opcode == 0x0 or
            (pkt.opcode_version == 0x00 and pkt.opcode_charset == 0x00)),
        ConditionalField(
            PacketLenField("dp_info1",
                           SAPDPInfo1(),
                           SAPDPInfo1,
                           length_from=lambda x: 507), lambda pkt:
            (pkt.opcode == 0x0 or
             (pkt.opcode_version == 0x00 and pkt.opcode_charset == 0x00
              )) and pkt.dp_version == 0x0d),  # 745 kernel
        ConditionalField(
            PacketLenField("dp_info2",
                           SAPDPInfo2(),
                           SAPDPInfo2,
                           length_from=lambda x: 203), lambda pkt:
            (pkt.opcode == 0x0 or
             (pkt.opcode_version == 0x00 and pkt.opcode_charset == 0x00
              )) and pkt.dp_version == 0x0b),  # 720 kernel
        ConditionalField(
            PacketLenField("dp_info3",
                           SAPDPInfo3(),
                           SAPDPInfo3,
                           length_from=lambda x: 179), lambda pkt:
            (pkt.opcode == 0x0 or
             (pkt.opcode_version == 0x00 and pkt.opcode_charset == 0x00
              )) and pkt.dp_version == 0x0e),  # 749 kernel

        # MS ADM layer
        ConditionalField(
            StrFixedLenField("adm_eyecatcher", "AD-EYECATCH\x00", 12), lambda
            pkt: pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(
            ByteField("adm_version", 0x01), lambda pkt: pkt.iflag in
            [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(
            ByteEnumKeysField("adm_type", 0x01, ms_adm_type_values), lambda
            pkt: pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(
            IntToStrField("adm_recsize", 104, 11), lambda pkt: pkt.iflag in
            [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(
            IntToStrField("adm_recno", 1, 11), lambda pkt: pkt.iflag in
            [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(
            PacketListField("adm_records", None, SAPMSAdmRecord), lambda pkt:
            pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),

        # Server List fields
        ConditionalField(
            PacketListField("clients", None, SAPMSClient1), lambda pkt: pkt.
            opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x01),
        ConditionalField(
            PacketListField("clients", None, SAPMSClient2), lambda pkt: pkt.
            opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x02),
        ConditionalField(
            PacketListField("clients", None, SAPMSClient3), lambda pkt: pkt.
            opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x03),
        ConditionalField(
            PacketListField("clients", None, SAPMSClient4), lambda pkt: pkt.
            opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x04),

        # Change IP fields
        ConditionalField(IPField("change_ip_addressv4", "0.0.0.0"),
                         lambda pkt: pkt.opcode == 0x06),
        ConditionalField(
            IP6Field("change_ip_addressv6", "::"),
            lambda pkt: pkt.opcode == 0x06 and pkt.opcode_version == 0x02),

        # Get/Set Text fields
        ConditionalField(StrFixedLenField("text_name", "", 40),
                         lambda pkt: pkt.opcode in [0x22, 0x23]),
        ConditionalField(
            FieldLenField("text_length",
                          None,
                          length_of="text_value",
                          fmt="!I"), lambda pkt: pkt.opcode in [0x22, 0x23]),
        ConditionalField(
            StrFixedLenField("text_value",
                             "",
                             length_from=lambda pkt: pkt.text_length or 80),
            lambda pkt: pkt.opcode in [0x22, 0x23]),

        # Counter fields
        ConditionalField(
            PacketField("counter", None, SAPMSCounter),
            lambda pkt: pkt.opcode in [0x24, 0x25, 0x26, 0x27, 0x28, 0x29]),
        ConditionalField(PacketListField("counters", None, SAPMSCounter),
                         lambda pkt: pkt.opcode in [0x2a]),

        # Security Key 1 fields
        ConditionalField(StrFixedLenField("security_name", None, 40),
                         lambda pkt: pkt.opcode in [0x07, 0x08]),
        ConditionalField(StrFixedLenField("security_key", None, 256),
                         lambda pkt: pkt.opcode in [0x07, 0x08]),

        # Security Key 2 fields
        ConditionalField(IPField("security2_addressv4", "0.0.0.0"),
                         lambda pkt: pkt.opcode == 0x09),
        ConditionalField(ShortField("security2_port", 0),
                         lambda pkt: pkt.opcode == 0x09),
        ConditionalField(StrFixedLenField("security2_key", None, 256),
                         lambda pkt: pkt.opcode == 0x09),
        ConditionalField(IP6Field("security2_addressv6", "::"),
                         lambda pkt: pkt.opcode == 0x09),

        # Hardware ID field
        ConditionalField(StrNullFixedLenField("hwid", "", length=99),
                         lambda pkt: pkt.opcode == 0x0a),

        # Statistics
        ConditionalField(PacketField("stats", None, SAPMSStat3),
                         lambda pkt: pkt.opcode == 0x11 and pkt.flag == 0x03),

        # Codepage
        ConditionalField(IntField("codepage", 0),
                         lambda pkt: pkt.opcode == 0x1c and pkt.flag == 0x03),

        # Dump Info Request fields
        ConditionalField(ByteField("dump_dest", 0x02),
                         lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),
        ConditionalField(StrFixedLenField("dump_filler", "\x00\x00\x00", 3),
                         lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),
        ConditionalField(ShortField("dump_index", 0x00),
                         lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),
        ConditionalField(
            ShortEnumKeysField("dump_command", 0x01, ms_dump_command_values),
            lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),
        ConditionalField(StrFixedLenField("dump_name", "\x00" * 40, 40),
                         lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),

        # File Reload fields
        ConditionalField(
            ByteEnumKeysField("file_reload", 0, ms_file_reload_values),
            lambda pkt: pkt.opcode == 0x1f),
        ConditionalField(StrFixedLenField("file_padding", "\x00\x00", 2),
                         lambda pkt: pkt.opcode == 0x1f),

        # Get/Set/Del Logon fields
        ConditionalField(PacketField("logon", None, SAPMSLogon),
                         lambda pkt: pkt.opcode in [0x2b, 0x2c, 0x2d]),

        # Server Disconnect/Shutdown fields
        ConditionalField(PacketField("shutdown_client", None, SAPMSClient3),
                         lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]),
        ConditionalField(
            FieldLenField("shutdown_reason_length",
                          None,
                          length_of="shutdown_reason",
                          fmt="!H"),
            lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]),
        ConditionalField(
            StrLenField("shutdown_reason",
                        "",
                        length_from=lambda pkt: pkt.shutdown_reason_length),
            lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]),

        # Get/Set Property fields
        ConditionalField(PacketField("property", None, SAPMSProperty),
                         lambda pkt: pkt.opcode in [0x43, 0x44, 0x45]),

        # IP/Port to name fields
        ConditionalField(
            IPField("ip_to_name_address4", "0.0.0.0"),
            lambda pkt: pkt.opcode == 0x46 and pkt.opcode_version == 0x01),
        ConditionalField(
            IP6Field("ip_to_name_address6", "::"),
            lambda pkt: pkt.opcode == 0x46 and pkt.opcode_version == 0x02),
        ConditionalField(ShortField("ip_to_name_port", 0),
                         lambda pkt: pkt.opcode == 0x46),
        ConditionalField(
            FieldLenField("ip_to_name_length",
                          None,
                          length_of="ip_to_name",
                          fmt="!I"), lambda pkt: pkt.opcode == 0x46),
        ConditionalField(
            StrLenField("ip_to_name",
                        "",
                        length_from=lambda pkt: pkt.logonname_length),
            lambda pkt: pkt.opcode == 0x46),

        # Check ACL fields
        ConditionalField(ShortField("error_code", 0),
                         lambda pkt: pkt.opcode == 0x47),
        ConditionalField(StrFixedLenField("acl", "", 46),
                         lambda pkt: pkt.opcode == 0x47),
    ]
Example #5
0
class EncryptedPreMasterSecret(_GenericTLSSessionInheritance):
    """
    Pay attention to implementation notes in section 7.4.7.1 of RFC 5246.
    """
    name = "RSA Encrypted PreMaster Secret"
    fields_desc = [
        _TLSClientVersionField("client_version", None, _tls_version),
        StrFixedLenField("random", None, 46)
    ]

    @classmethod
    def dispatch_hook(cls, _pkt=None, *args, **kargs):
        if 'tls_session' in kargs:
            s = kargs['tls_session']
            if s.server_tmp_rsa_key is None and s.server_rsa_key is None:
                return _UnEncryptedPreMasterSecret
        return EncryptedPreMasterSecret

    def pre_dissect(self, m):
        s = self.tls_session
        tbd = m
        tls_version = s.tls_version
        if tls_version is None:
            tls_version = s.advertised_tls_version
        if tls_version >= 0x0301:
            if len(m) < 2:  # Should not happen
                return m
            tmp_len = struct.unpack("!H", m[:2])[0]
            if len(m) != tmp_len + 2:
                err = "TLS 1.0+, but RSA Encrypted PMS with no explicit length"
                warning(err)
            else:
                tbd = m[2:]
        if s.server_tmp_rsa_key is not None:
            # priority is given to the tmp_key, if there is one
            decrypted = s.server_tmp_rsa_key.decrypt(tbd)
            pms = decrypted[-48:]
        elif s.server_rsa_key is not None:
            decrypted = s.server_rsa_key.decrypt(tbd)
            pms = decrypted[-48:]
        else:
            # the dispatch_hook is supposed to prevent this case
            pms = b"\x00" * 48
            err = "No server RSA key to decrypt Pre Master Secret. Skipping."
            warning(err)

        s.pre_master_secret = pms
        s.compute_ms_and_derive_keys()

        return pms

    def post_build(self, pkt, pay):
        """
        We encrypt the premaster secret (the 48 bytes) with either the server
        certificate or the temporary RSA key provided in a server key exchange
        message. After that step, we add the 2 bytes to provide the length, as
        described in implementation notes at the end of section 7.4.7.1.
        """
        enc = pkt

        s = self.tls_session
        s.pre_master_secret = enc
        s.compute_ms_and_derive_keys()

        if s.server_tmp_rsa_key is not None:
            enc = s.server_tmp_rsa_key.encrypt(pkt, t="pkcs")
        elif s.server_certs is not None and len(s.server_certs) > 0:
            enc = s.server_certs[0].encrypt(pkt, t="pkcs")
        else:
            warning("No material to encrypt Pre Master Secret")

        tmp_len = b""
        tls_version = s.tls_version
        if tls_version is None:
            tls_version = s.advertised_tls_version
        if tls_version >= 0x0301:
            tmp_len = struct.pack("!H", len(enc))
        return tmp_len + enc + pay

    def guess_payload_class(self, p):
        return Padding
Example #6
0
class SAPRFC(Packet):
    """SAP Remote Function Call packet

    This packet is used for the Remote Function Call (RFC) protocol.
    """
    name = "SAP Remote Function Call"
    fields_desc = [
        ByteField(
            "version", 3
        ),  # If the version is 3, the packet has a size > 88h, versions 1 and 2 are 40h
        ByteEnumKeysField("req_type", 0, rfc_req_type_values),

        # Normal client fields (GW_NORMAL_CLIENT)
        ConditionalField(IPField("address", "0.0.0.0"),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(IntField("padd1", 0),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(StrFixedLenPaddedField("service", "", length=10),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(StrFixedLenField("codepage", "1100", length=4),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(StrFixedLenField("padd2", "\x00" * 6, length=6),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(StrFixedLenPaddedField("lu", "", length=8),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(StrFixedLenPaddedField("tp", "", length=8),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(
            StrFixedLenPaddedField("conversation_id", "", length=8),
            lambda pkt: pkt.req_type == 0x03),
        ConditionalField(ByteField("appc_header_version", 6),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(ByteField("accept_info", 0xcb),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(SignedShortField("idx", -1),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(
            IP6Field("address6", "::"),
            lambda pkt: pkt.req_type == 0x03 and pkt.version == 3),
        ConditionalField(IntField("rc", 0), lambda pkt: pkt.req_type == 0x03),
        ConditionalField(ByteField("echo_data", 0),
                         lambda pkt: pkt.req_type == 0x03),
        ConditionalField(ByteField("filler", 0),
                         lambda pkt: pkt.req_type == 0x03),

        # Monitor Command fields (GW_SEND_CMD)
        ConditionalField(ByteEnumKeysField("cmd", 0, rfc_monitor_cmd_values),
                         lambda pkt: pkt.req_type == 0x09),

        # General padding for non implemented request types
        ConditionalField(StrFixedLenField("padd_v12", "\x00" * 61, length=61),
                         lambda pkt: pkt.version < 3 and pkt.req_type == 0x09),
        ConditionalField(
            StrFixedLenField("padd_v12", "\x00" * 62, length=62),
            lambda pkt: pkt.version < 3 and pkt.req_type not in [0x03, 0x09]),
        ConditionalField(
            StrFixedLenField("padd_v3", "\x00" * 133, length=133),
            lambda pkt: pkt.version == 3 and pkt.req_type == 0x09),
        ConditionalField(
            StrFixedLenField("padd_v3", "\x00" * 134, length=134),
            lambda pkt: pkt.version == 3 and pkt.req_type not in [0x03, 0x09]),
    ]
Example #7
0
class SAPCARArchiveFilev200Format(PacketNoPadded):
    """SAP CAR file information format

    This is ued to parse files inside a SAP CAR archive.
    """
    name = "SAP CAR Archive File 2.00"

    version = SAPCAR_VERSION_200
    is_filename_null_terminated = False

    fields_desc = [
        StrFixedLenField("type", SAPCAR_TYPE_FILE, 2),
        LEIntField("perm_mode", 0),
        LELongField("file_length_low", 0),
        LEIntField("file_length_high", 0),
        LELongField("timestamp", 0),
        LEIntField("code_page", 0),
        FieldLenField("user_info_length", 0, length_of="user_info", fmt="<H"),
        FieldLenField("filename_length", 0, length_of="filename", fmt="<H"),
        StrNullFixedLenField(
            "filename",
            None,
            length_from=lambda x: x.filename_length,
            null_terminated=lambda x: x.is_filename_null_terminated),
        StrFixedLenField("user_info",
                         None,
                         length_from=lambda x: x.user_info_length),
        ConditionalField(
            PacketListStopField("blocks",
                                None,
                                SAPCARCompressedBlockFormat,
                                stop=sapcar_is_last_block),
            lambda x: x.type == SAPCAR_TYPE_FILE and x.file_length > 0),
    ]

    @property
    def file_length(self):
        """Getter for the file length fields. It converts the two length fields (low and high) as provided in the
        archive file into a long long integer.
        """
        return (self.file_length_high * SIZE_FOUR_GB) + self.file_length_low

    @file_length.setter
    def file_length(self, file_length):
        """Setter for the file length fields. It splits the long long integer int on the two length fields (low and
        high) as required by the archive file.
        """
        self.file_length_low = file_length & 0xffffffff
        self.file_length_high = file_length >> 32

    def extract(self, fd):
        """Extracts the archive file and writes the extracted file to the provided file object. Returns the checksum
        obtained from the archive. If blocks are uncompressed, the file is directly extracted. If the blocks are
        compressed, each block is added to a buffer, skipping the length field, and decompression is performed after
        the block marked as end of data. Expected length and compression header is obtained from the first block and
        checksum from the end of data block.

        :param fd: file-like object to write the extracted file to
        :type fd: file

        :return: checksum
        :rtype: int

        :raise DecompressError: If there's a decompression error
        :raise SAPCARInvalidFileException: If the file is invalid
        """

        if self.file_length == 0:
            return 0

        compressed = ""
        checksum = 0
        exp_length = None

        remaining_length = self.file_length
        for block in self.blocks:
            # Process uncompressed block types
            if block.type in [
                    SAPCAR_BLOCK_TYPE_UNCOMPRESSED,
                    SAPCAR_BLOCK_TYPE_UNCOMPRESSED_LAST
            ]:
                fd.write(block.compressed)
                remaining_length -= len(block.compressed)
            # Store compressed block types for later decompression
            elif block.type in [
                    SAPCAR_BLOCK_TYPE_COMPRESSED,
                    SAPCAR_BLOCK_TYPE_COMPRESSED_LAST
            ]:
                # Add compressed block to a buffer, skipping the first 4 bytes of each block (uncompressed length)
                compressed += str(block.compressed)[4:]
                # If the expected length wasn't already set, do it
                if not exp_length:
                    exp_length = block.compressed.uncompress_length
            else:
                raise SAPCARInvalidFileException("Invalid block type found")

            # Check end of data block, performing decompression if needed
            if sapcar_is_last_block(block):
                checksum = block.checksum
                # If there was at least one compressed block that set the expected length, decompress it
                if exp_length:
                    (_, block_length,
                     block_buffer) = decompress(str(compressed), exp_length)
                    if block_length != exp_length or not block_buffer:
                        raise DecompressError("Error decompressing block")
                    fd.write(block_buffer)
                break

        return checksum
Example #8
0
 def i2repr(self, pkt, v):
     if self.null_terminated(pkt):
         if type(v) is str:
             v = v.rstrip("\0")
         return repr(v)
     return StrFixedLenField.i2repr(self, pkt, v)
Example #9
0
File: dns.py Project: netkey/scapy
 def __init__(self, name, default):
     StrFixedLenField.__init__(self, name, default, 6)
Example #10
0
 def __init__(self, name, default):
     StrFixedLenField.__init__(self, name, default, 32)
Example #11
0
 def addfield(self, pkt, s, val):
     l = self.length_from(pkt)
     val += self.padd * l
     return StrFixedLenField.addfield(self, pkt, s, val)
Example #12
0
 def __init__(self, name, default, length=None, length_from=None, padd=" "):
     StrFixedLenField.__init__(self, name, default, length, length_from)
     self.padd = padd
Example #13
0
 def __init__(self, name, default):
     return StrFixedLenField.__init__(self, name, default, length=60)
Example #14
0
 def addfield(self, pkt, s, val):
     if self.null_terminated(pkt):
         l = self.length_from(pkt) - 1
         return s + struct.pack("%is" % l, self.i2m(pkt, val)) + "\x00"
     return StrFixedLenField.addfield(self, pkt, s, val)
Example #15
0
 def getfield(self, pkt, s):
     if self.null_terminated(pkt):
         l = self.length_from(pkt) - 1
         return s[l + 1:], self.m2i(pkt, s[:l])
     return StrFixedLenField.getfield(self, pkt, s)
Example #16
0
class SAPDPInfo1(Packet):
    """SAP Dispatcher Info packet

    This packet is encapsulated inside SAPMS packet
    and before the MS ADM payload. Kernel 745
    """
    name = "SAP Dispatcher Info V1"
    fields_desc = [
        ByteEnumKeysField("dp_req_prio", 0x1, dp_prio_values),
        IntField("dp_user_trace", 0x0),
        IntField("dp_req_len", 0x0),
        ShortField("dp_padd3", 0x0),
        ByteField("dp_padd4", 0x0),
        ByteEnumKeysField("dp_type_from", 0x2, dp_type_values),
        StrFixedLenField("dp_fromname", " " * 40, 40),
        ShortField("dp_padd41", 0x0),
        ByteField("dp_padd42", 0x0),
        ByteEnumKeysField("dp_agent_type_from", 0x6, dp_agent_type_values),
        ShortField("dp_padd43", 0x0),
        ByteField("dp_padd44", 0x0),
        ByteEnumKeysField("dp_worker_type_from", 0x1, dp_worker_type_values),
        IntField("dp_worker_from_num", 0x0),
        ShortField("dp_padd6", 0x0),
        ShortField("dp_padd7", 0x0),
        ByteField("dp_addr_from_t", 0xff),
        ShortField("dp_padd8", 0x0),
        ShortField("dp_addr_from_u", 0xffff),
        ByteField("dp_addr_from_m", 0xff),
        ByteField("dp_padd9", 0x1),
        IntField("dp_respid_from", 0x0),
        ShortField("dp_padd10", 0x0),
        ByteField("dp_padd11", 0x0),
        ByteEnumKeysField("dp_type_to", 0x2, dp_type_values),
        StrFixedLenField("dp_toname", " " * 40, 40),
        ShortField("dp_padd51", 0x0),
        ByteField("dp_padd52", 0x0),
        ByteEnumKeysField("dp_agent_type_to", 0x6, dp_agent_type_values),
        ShortField("dp_padd54", 0x0),
        ByteField("dp_padd55", 0x0),
        ByteEnumKeysField("dp_worker_type_to", 0x1, dp_worker_type_values),
        IntField("dp_worker_to_num", 0x0),
        ShortField("dp_padd01", 0),
        ShortField("dp_padd02", 0),
        ByteField("dp_addr_to_t", 0xff),
        ShortField("dp_padd03", 0x1),
        ShortField("dp_addr_to_u", 0xffff),
        ByteField("dp_addr_to_m", 0x0),
        ByteField("dp_padd21", 0x0),
        IntField("dp_respid_to", 0),
        ByteField("dp_padd22", 0),
        ShortField("dp_padd23", 0),
        ByteEnumKeysField("dp_req_handler", 40, dp_req_handler_values),
        IntField("dp_req_rc", 0x0),
        StrFixedLenField("dp_blob_padding", None, 224),
        Field("dp_blob_56", 6, '<L'),
        Field("dp_blob_57", 1, '<L'),
        Field("dp_blob_worker_from_num", 0, '<L'),
        ByteField("dp_blob_worker_type_from", 0),
        StrFixedLenField("dp_blob_62", "", 3),
        Field("dp_blob_addr_from_t", 0, '<L'),
        Field("dp_blob_addr_from_u", 0, '<L'),
        ByteField("dp_blob_worker_type_to", 0),
        StrFixedLenField("dp_blob_63", "", 3),
        Field("dp_blob_respid_from", 0, '<L'),
        StrFixedLenField("dp_blob_64", "", 3),
        StrFixedLenField("dp_blob_dst", "", 80),
        ByteField("dp_blob_xx", 0),
        StrFixedLenField("dp_blob_yy", "", 8),
    ]
Example #17
0
class DoIP(Packet):
    """
    Implementation of the DoIP (ISO 13400) protocol. DoIP packets can be sent
    via UDP and TCP. Depending on the payload type, the correct connection
    need to be chosen:

    +--------------+--------------------------------------------------------------+-----------------+
    | Payload Type | Payload Type Name                                            | Connection Kind |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0000       | Generic DoIP header negative acknowledge                     | UDP / TCP       |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0001       | Vehicle Identification request message                       | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0002       | Vehicle identification request message with EID              | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0003       | Vehicle identification request message with VIN              | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0004       | Vehicle announcement message/vehicle identification response | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0005       | Routing activation request                                   | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0006       | Routing activation response                                  | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0007       | Alive Check request                                          | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0008       | Alive Check response                                         | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x4001       | IP entity status request                                     | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x4002       | DoIP entity status response                                  | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x4003       | Diagnostic power mode information request                    | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x4004       | Diagnostic power mode information response                   | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x8001       | Diagnostic message                                           | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x8002       | Diagnostic message positive acknowledgement                  | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x8003       | Diagnostic message negative acknowledgement                  | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+

    Example with UDP:
        >>> socket = L3RawSocket(iface="eth0")
        >>> resp = socket.sr1(IP(dst="169.254.117.238")/UDP(dport=13400)/DoIP(payload_type=1))

    Example with TCP:
        >>> socket = DoIPSocket("169.254.117.238")
        >>> pkt = DoIP(payload_type=0x8001, source_address=0xe80, target_address=0x1000) / UDS() / UDS_RDBI(identifiers=[0x1000])
        >>> resp = socket.sr1(pkt, timeout=1)

    Example with UDS:
        >>> socket = UDS_DoIPSocket("169.254.117.238")
        >>> pkt = UDS() / UDS_RDBI(identifiers=[0x1000])
        >>> resp = socket.sr1(pkt, timeout=1)
    """  # noqa: E501
    payload_types = {
        0x0000: "Generic DoIP header NACK",
        0x0001: "Vehicle identification request",
        0x0002: "Vehicle identification request with EID",
        0x0003: "Vehicle identification request with VIN",
        0x0004:
        "Vehicle announcement message/vehicle identification response message",  # noqa: E501
        0x0005: "Routing activation request",
        0x0006: "Routing activation response",
        0x0007: "Alive check request",
        0x0008: "Alive check response",
        0x4001: "DoIP entity status request",
        0x4002: "DoIP entity status response",
        0x4003: "Diagnostic power mode information request",
        0x4004: "Diagnostic power mode information response",
        0x8001: "Diagnostic message",
        0x8002: "Diagnostic message ACK",
        0x8003: "Diagnostic message NACK"
    }
    name = 'DoIP'
    fields_desc = [
        XByteField("protocol_version", 0x02),
        XByteField("inverse_version", 0xFD),
        XShortEnumField("payload_type", 0, payload_types),
        IntField("payload_length", None),
        ConditionalField(
            ByteEnumField(
                "nack", 0, {
                    0: "Incorrect pattern format",
                    1: "Unknown payload type",
                    2: "Message too large",
                    3: "Out of memory",
                    4: "Invalid payload length"
                }), lambda p: p.payload_type in [0x0]),
        ConditionalField(StrFixedLenField("vin", b"", 17),
                         lambda p: p.payload_type in [3, 4]),
        ConditionalField(XShortField("logical_address", 0),
                         lambda p: p.payload_type in [4]),
        ConditionalField(StrFixedLenField("eid", b"", 6),
                         lambda p: p.payload_type in [2, 4]),
        ConditionalField(StrFixedLenField("gid", b"", 6),
                         lambda p: p.payload_type in [4]),
        ConditionalField(
            XByteEnumField(
                "further_action", 0, {
                    0x00:
                    "No further action required",
                    0x01:
                    "Reserved by ISO 13400",
                    0x02:
                    "Reserved by ISO 13400",
                    0x03:
                    "Reserved by ISO 13400",
                    0x04:
                    "Reserved by ISO 13400",
                    0x05:
                    "Reserved by ISO 13400",
                    0x06:
                    "Reserved by ISO 13400",
                    0x07:
                    "Reserved by ISO 13400",
                    0x08:
                    "Reserved by ISO 13400",
                    0x09:
                    "Reserved by ISO 13400",
                    0x0a:
                    "Reserved by ISO 13400",
                    0x0b:
                    "Reserved by ISO 13400",
                    0x0c:
                    "Reserved by ISO 13400",
                    0x0d:
                    "Reserved by ISO 13400",
                    0x0e:
                    "Reserved by ISO 13400",
                    0x0f:
                    "Reserved by ISO 13400",
                    0x10:
                    "Routing activation required to initiate central security",
                }), lambda p: p.payload_type in [4]),
        ConditionalField(
            XByteEnumField(
                "vin_gid_status", 0, {
                    0x00: "VIN and/or GID are synchronized",
                    0x01: "Reserved by ISO 13400",
                    0x02: "Reserved by ISO 13400",
                    0x03: "Reserved by ISO 13400",
                    0x04: "Reserved by ISO 13400",
                    0x05: "Reserved by ISO 13400",
                    0x06: "Reserved by ISO 13400",
                    0x07: "Reserved by ISO 13400",
                    0x08: "Reserved by ISO 13400",
                    0x09: "Reserved by ISO 13400",
                    0x0a: "Reserved by ISO 13400",
                    0x0b: "Reserved by ISO 13400",
                    0x0c: "Reserved by ISO 13400",
                    0x0d: "Reserved by ISO 13400",
                    0x0e: "Reserved by ISO 13400",
                    0x0f: "Reserved by ISO 13400",
                    0x10: "Incomplete: VIN and GID are NOT synchronized"
                }), lambda p: p.payload_type in [4]),
        ConditionalField(
            XShortField("source_address", 0), lambda p: p.payload_type in
            [5, 8, 0x8001, 0x8002, 0x8003]),  # noqa: E501
        ConditionalField(
            XByteEnumField("activation_type", 0, {
                0: "Default",
                1: "WWH-OBD",
                0xe0: "Central security"
            }), lambda p: p.payload_type in [5]),
        ConditionalField(XShortField("logical_address_tester", 0),
                         lambda p: p.payload_type in [6]),
        ConditionalField(XShortField("logical_address_doip_entity", 0),
                         lambda p: p.payload_type in [6]),
        ConditionalField(
            XByteEnumField(
                "routing_activation_response",
                0,
                {
                    0x00:
                    "Routing activation denied due to unknown source address.",
                    0x01:
                    "Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active.",  # noqa: E501
                    0x02:
                    "Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket.",  # noqa: E501
                    0x03:
                    "Routing activation denied because the SA is already registered and active on a different TCP_DATA socket.",  # noqa: E501
                    0x04:
                    "Routing activation denied due to missing authentication.",
                    0x05:
                    "Routing activation denied due to rejected confirmation.",
                    0x06:
                    "Routing activation denied due to unsupported routing activation type.",  # noqa: E501
                    0x07: "Reserved by ISO 13400.",
                    0x08: "Reserved by ISO 13400.",
                    0x09: "Reserved by ISO 13400.",
                    0x0a: "Reserved by ISO 13400.",
                    0x0b: "Reserved by ISO 13400.",
                    0x0c: "Reserved by ISO 13400.",
                    0x0d: "Reserved by ISO 13400.",
                    0x0e: "Reserved by ISO 13400.",
                    0x0f: "Reserved by ISO 13400.",
                    0x10: "Routing successfully activated.",
                    0x11: "Routing will be activated; confirmation required."
                }),
            lambda p: p.payload_type in [6]),
        ConditionalField(XIntField("reserved_iso", 0),
                         lambda p: p.payload_type in [5, 6]),
        ConditionalField(XIntField("reserved_oem", 0),
                         lambda p: p.payload_type in [5, 6]),
        ConditionalField(
            XByteEnumField("diagnostic_power_mode", 0, {
                0: "not ready",
                1: "ready",
                2: "not supported"
            }), lambda p: p.payload_type in [0x4004]),
        ConditionalField(
            ByteEnumField("node_type", 0, {
                0: "DoIP gateway",
                1: "DoIP node"
            }), lambda p: p.payload_type in [0x4002]),
        ConditionalField(XByteField("max_open_sockets", 0),
                         lambda p: p.payload_type in [0x4002]),
        ConditionalField(XByteField("cur_open_sockets", 0),
                         lambda p: p.payload_type in [0x4002]),
        ConditionalField(IntField("max_data_size", 0),
                         lambda p: p.payload_type in [0x4002]),
        ConditionalField(XShortField("target_address", 0),
                         lambda p: p.payload_type in [0x8001, 0x8002, 0x8003
                                                      ]),  # noqa: E501
        ConditionalField(XByteEnumField("ack_code", 0, {0: "ACK"}),
                         lambda p: p.payload_type in [0x8002]),
        ConditionalField(
            ByteEnumField(
                "nack_code", 0, {
                    0x00: "Reserved by ISO 13400",
                    0x01: "Reserved by ISO 13400",
                    0x02: "Invalid source address",
                    0x03: "Unknown target address",
                    0x04: "Diagnostic message too large",
                    0x05: "Out of memory",
                    0x06: "Target unreachable",
                    0x07: "Unknown network",
                    0x08: "Transport protocol error"
                }), lambda p: p.payload_type in [0x8003]),
    ]

    def answers(self, other):
        # type: (Packet) -> int
        """DEV: true if self is an answer from other"""
        if isinstance(other, type(self)):
            if self.payload_type == 0:
                return 1

            matches = [(4, 1), (4, 2), (4, 3), (6, 5), (8, 7),
                       (0x4002, 0x4001), (0x4004, 0x4003), (0x8001, 0x8001),
                       (0x8003, 0x8001)]
            if (self.payload_type, other.payload_type) in matches:
                if self.payload_type == 0x8001:
                    return self.payload.answers(other.payload)
                return 1
        return 0

    def hashret(self):
        # type: () -> bytes
        if self.payload_type in [0x8001, 0x8002, 0x8003]:
            return bytes(self)[:2] + struct.pack(
                "H", self.target_address ^ self.source_address)
        return bytes(self)[:2]

    def post_build(self, pkt, pay):
        # type: (bytes, bytes) -> bytes
        """
        This will set the Field 'payload_length' to the correct value.
        """
        if self.payload_length is None:
            pkt = pkt[:4] + struct.pack("!I", len(pay) + len(pkt) - 8) + \
                pkt[8:]
        return pkt + pay

    def extract_padding(self, s):
        # type: (bytes) -> Tuple[bytes, Optional[bytes]]
        if self.payload_type == 0x8001:
            return s[:self.payload_length - 4], None
        else:
            return b"", None
Example #18
0
class SkinnyMessageCallInfo(Packet):
    name = 'call information'
    fields_desc = [
        StrFixedLenField("callername", "Jean Valjean", 40),
        StrFixedLenField("callernum", "1337", 24),
        StrFixedLenField("calledname", "Causette", 40),
        StrFixedLenField("callednum", "1034", 24),
        LEIntField("lineinstance", 1),
        LEIntField("callid", 0),
        StrFixedLenField("originalcalledname", "Causette", 40),
        StrFixedLenField("originalcallednum", "1034", 24),
        StrFixedLenField("lastredirectingname", "Causette", 40),
        StrFixedLenField("lastredirectingnum", "1034", 24),
        LEIntField("originalredirectreason", 0),
        LEIntField("lastredirectreason", 0),
        StrFixedLenField('voicemailboxG', b'\0' * 24, 24),
        StrFixedLenField('voicemailboxD', b'\0' * 24, 24),
        StrFixedLenField('originalvoicemailboxD', b'\0' * 24, 24),
        StrFixedLenField('lastvoicemailboxD', b'\0' * 24, 24),
        LEIntField('security', 0),
        FlagsField('restriction', 0, 16,
                   _skinny_message_callinfo_restrictions),  # noqa: E501
        LEIntField('unknown', 0)
    ]
Example #19
0
 def __init__(self, name, default, length=None, length_from=None, padd=" "):
     StrFixedLenField.__init__(self, name, default, length, length_from)
     self.padd = padd
Example #20
0
class SAPRouter(Packet):
    """SAP Router packet

    This packet is used for general SAP Router packets. There are (at least)
    five types of SAP Router packets:

        1. Route packets. For requesting the routing of a connection to a
        remote hosts. The packet contains some general information and a
        connection string with a list of routing hops (:class:`SAPRouterRouteHop`).

        2. Administration packets. This packet is used for the SAP Router to
        send administrative commands. It's suppose to be used only from the
        hosts running the SAP Router or when an specific route is included in
        the routing table. Generally administration packets are not accepted
        from the external binding.

        3. Error Information packets. Packets sent when an error occurred.

        4. Control Message packets. Used to perform some control activities,
        like retrieving the current SAPRouter version or to perform the SNC
        handshake. They have the same structure that error information
        packets.

        5. Route accepted packet. Used to acknowledge a route request
        ("NI_PONG").


    Routed packets and some responses doesn't fill in these five packet
    types. For identifying those cases, you should check the type using the
    function :class:`router_is_known_type`.

    NI Versions found (unconfirmed):
        - 30: Release 40C
        - 36: Release <6.20
        - 38: Release 7.00/7.10
        - 39: Release 7.11
        - 40: Release 7.20/7.21
    """

    # Default router version to use
    SAPROUTER_DEFAULT_VERSION = 40

    # Constants for router types
    SAPROUTER_ROUTE = "NI_ROUTE"
    """ :cvar: Constant for route packets
        :type: C{string} """

    SAPROUTER_ADMIN = "ROUTER_ADM"
    """ :cvar: Constant for administration packets
        :type: C{string} """

    SAPROUTER_ERROR = "NI_RTERR"
    """ :cvar: Constant for error information packets
        :type: C{string} """

    SAPROUTER_CONTROL = "NI_RTERR"
    """ :cvar: Constant for control messages packets
        :type: C{string} """

    SAPROUTER_PONG = "NI_PONG"
    """ :cvar: Constant for route accepted packets
        :type: C{string} """

    router_type_values = [
        SAPROUTER_ADMIN,
        SAPROUTER_ERROR,
        SAPROUTER_CONTROL,
        SAPROUTER_ROUTE,
        SAPROUTER_PONG,
    ]
    """ :cvar: List of known packet types
        :type: ``list`` of C{string} """

    name = "SAP Router"
    fields_desc = [
        # General fields present in all SAP Router packets
        StrNullField("type", SAPROUTER_ROUTE),
        ConditionalField(
            ByteField("version", 2),
            lambda pkt: router_is_known_type(pkt) and not router_is_pong(pkt)),

        # Route packets
        ConditionalField(
            ByteField("route_ni_version", SAPROUTER_DEFAULT_VERSION),
            router_is_route),
        ConditionalField(ByteField("route_entries", 0), router_is_route),
        ConditionalField(
            ByteEnumKeysField("route_talk_mode", 0,
                              router_ni_talk_mode_values), router_is_route),
        ConditionalField(ShortField("route_padd", 0), router_is_route),
        ConditionalField(ByteField("route_rest_nodes", 0), router_is_route),
        ConditionalField(
            FieldLenField("route_length", 0, length_of="route_string",
                          fmt="I"), router_is_route),
        ConditionalField(IntField("route_offset", 0), router_is_route),
        ConditionalField(
            PacketListField("route_string",
                            None,
                            SAPRouterRouteHop,
                            length_from=lambda pkt: pkt.route_length),
            router_is_route),

        # Admin packets
        ConditionalField(
            ByteEnumKeysField("adm_command", 0x02, router_adm_commands),
            router_is_admin),
        ConditionalField(
            ShortField("adm_unused", 0x00), lambda pkt: router_is_admin(pkt)
            and pkt.adm_command not in [10, 11, 12, 13]),

        # Info Request fields
        ConditionalField(
            StrNullFixedLenField("adm_password", "", 19),
            lambda pkt: router_is_admin(pkt) and pkt.adm_command in [2]),

        # Cancel Route fields
        ConditionalField(
            FieldLenField("adm_client_count",
                          None,
                          count_of="adm_client_ids",
                          fmt="H"),
            lambda pkt: router_is_admin(pkt) and pkt.adm_command in [6]),
        # Trace Connection fields
        ConditionalField(
            FieldLenField("adm_client_count",
                          None,
                          count_of="adm_client_ids",
                          fmt="I"),
            lambda pkt: router_is_admin(pkt) and pkt.adm_command in [12, 13]),

        # Cancel Route or Trace Connection fields
        ConditionalField(
            FieldListField("adm_client_ids", [0x00],
                           IntField("", 0),
                           count_from=lambda pkt: pkt.adm_client_count), lambda
            pkt: router_is_admin(pkt) and pkt.adm_command in [6, 12, 13]),

        # Set/Clear Peer Trace fields  # TODO: Check whether this field should be a IPv6 address or another proper field
        ConditionalField(
            StrFixedLenField("adm_address_mask", "", 32),
            lambda pkt: router_is_admin(pkt) and pkt.adm_command in [10, 11]),

        # Error Information/Control Messages fields
        ConditionalField(
            ByteEnumKeysField("opcode", 0, router_control_opcodes),
            lambda pkt: router_is_error(pkt) or router_is_control(pkt)),
        ConditionalField(
            ByteField("opcode_padd", 0),
            lambda pkt: router_is_error(pkt) or router_is_control(pkt)),
        ConditionalField(
            SignedIntEnumField("return_code", 0, router_return_codes),
            lambda pkt: router_is_error(pkt) or router_is_control(pkt)),

        # Error Information fields
        ConditionalField(
            FieldLenField("err_text_length",
                          None,
                          length_of="err_text_value",
                          fmt="!I"),
            lambda pkt: router_is_error(pkt) and pkt.opcode == 0),
        ConditionalField(
            PacketField("err_text_value", SAPRouterError(),
                        SAPRouterError), lambda pkt: router_is_error(pkt) and
            pkt.opcode == 0 and pkt.err_text_length > 0),
        ConditionalField(IntField("err_text_unknown", 0),
                         lambda pkt: router_is_error(pkt) and pkt.opcode == 0),

        # Control Message fields
        ConditionalField(
            IntField("control_text_length", 0),
            lambda pkt: router_is_control(pkt) and pkt.opcode != 0),
        ConditionalField(
            StrField("control_text_value", "*ERR"),
            lambda pkt: router_is_control(pkt) and pkt.opcode != 0),

        # SNC Frame fields
        ConditionalField(
            PacketField("snc_frame", None, SAPSNCFrame),
            lambda pkt: router_is_control(pkt) and pkt.opcode in [70, 71])
    ]
Example #21
0
class NTLMSSPLE(Packet):
    name = 'NTLM Secure Service Provider'
    fields_desc = [
        StrFixedLenField('identifier', 'NTLMSSP', length=8),
        LEIntEnumField('messageType', 3, {3: 'NTLMSSP_AUTH'}),
        LEShortField('lanManagerLen', 0),
        LEShortField('lanManagerMax', 0),
        LEIntField('lanManagerOffset', 0),
        LEShortField('NTLMRepLen', 0),
        LEShortField('NTLMRepMax', 0),
        LEIntField('NTLMRepOffset', 0),
        LEShortField('domainNameLen', 0),
        LEShortField('domainNameMax', 0),
        LEIntField('domainNameOffset', 0),
        LEShortField('userNameLen', 0),
        LEShortField('userNameMax', 0),
        LEIntField('userNameOffset', 0),
        LEShortField('hostNameLen', 0),
        LEShortField('hostNameMax', 0),
        LEIntField('hostNameOffset', 0),
        LEShortField('sessionKeyLen', 0),
        LEShortField('sessionKeyMax', 0),
        LEIntField('sessionKeyOffset', 0),
        FlagsField('negociateFlags', 0, 32, _negociate_flags),
        ByteField('versionMajor', 0),
        ByteField('versionMinor', 0),
        LEShortField('buildNumber', 0),
        ByteField('reserved', 0),
        ShortField('reserved2', 0),
        ByteField('NTLMCurrentRevision', 0),
        StrFixedLenField('MIC', '', 16),
        StrLenField('domainName',
                    '',
                    length_from=lambda pkt: pkt.domainNameLen),
        StrLenField('userName', '', length_from=lambda pkt: pkt.userNameLen),
        StrLenField('hostName', '', length_from=lambda pkt: pkt.hostNameLen),
        StrLenField('lanManager',
                    '',
                    length_from=lambda pkt: pkt.lanManagerLen),
        StrFixedLenField('NTLMRep', '', length=16),
        ByteField('responseVersion', 0),
        ByteField('hiResponseVersion', 0),
        StrFixedLenField('Z', '', 6),
        LELongField('timestamp', 0),  # Time in nanosecond
        StrFixedLenField('clientChallenge', '', 8),
        LEIntField('Z', 0),
        PacketField('attribute1', None, AttributeNameLE),
        PacketField('attribute2', None, AttributeNameLE),
        PacketField('attribute3', None, AttributeNameLE),
        PacketField('attribute4', None, AttributeNameLE),
        PacketField('attribute5', None, AttributeNameLE),
        PacketField('attribute6', None, AttributeNameLE),
        PacketField('attribute7', None, AttributeNameLE),
        PacketField('attribute8', None, AttributeNameLE),
        PacketField('attribute9', None, AttributeNameLE),
        PacketField('attribute10', None, AttributeNameLE),
        LEIntField('Z', 0),
        LEIntField('padding', 0),
        StrLenField('sessionKey',
                    '',
                    length_from=lambda pkt: pkt.sessionKeyLen),
    ]

    def extract_padding(self, p):
        return b"", p
Example #22
0
class ARP(Packet):
    name = "ARP"
    fields_desc = [
        XShortField("hwtype", 0x0001),
        XShortEnumField("ptype", 0x0800, ETHER_TYPES),
        FieldLenField("hwlen", None, fmt="B", length_of="hwsrc"),
        FieldLenField("plen", None, fmt="B", length_of="psrc"),
        ShortEnumField(
            "op", 1, {
                "who-has": 1,
                "is-at": 2,
                "RARP-req": 3,
                "RARP-rep": 4,
                "Dyn-RARP-req": 5,
                "Dyn-RAR-rep": 6,
                "Dyn-RARP-err": 7,
                "InARP-req": 8,
                "InARP-rep": 9
            }),
        MultipleTypeField(
            [
                (SourceMACField("hwsrc"),
                 (lambda pkt: pkt.hwtype == 1 and pkt.hwlen == 6,
                  lambda pkt, val: pkt.hwtype == 1 and
                  (pkt.hwlen == 6 or
                   (pkt.hwlen is None and
                    (val is None or len(val) == 6 or valid_mac(val)))))),
            ],
            StrFixedLenField("hwsrc", None, length_from=lambda pkt: pkt.hwlen),
        ),
        MultipleTypeField(
            [
                (SourceIPField("psrc", "pdst"),
                 (lambda pkt: pkt.ptype == 0x0800 and pkt.plen == 4,
                  lambda pkt, val: pkt.ptype == 0x0800 and
                  (pkt.plen == 4 or (pkt.plen is None and
                                     (val is None or valid_net(val)))))),
                (SourceIP6Field("psrc", "pdst"),
                 (lambda pkt: pkt.ptype == 0x86dd and pkt.plen == 16,
                  lambda pkt, val: pkt.ptype == 0x86dd and
                  (pkt.plen == 16 or (pkt.plen is None and
                                      (val is None or valid_net6(val)))))),
            ],
            StrFixedLenField("psrc", None, length_from=lambda pkt: pkt.plen),
        ),
        MultipleTypeField(
            [
                (MACField("hwdst", ETHER_ANY),
                 (lambda pkt: pkt.hwtype == 1 and pkt.hwlen == 6,
                  lambda pkt, val: pkt.hwtype == 1 and
                  (pkt.hwlen == 6 or
                   (pkt.hwlen is None and
                    (val is None or len(val) == 6 or valid_mac(val)))))),
            ],
            StrFixedLenField("hwdst", None, length_from=lambda pkt: pkt.hwlen),
        ),
        MultipleTypeField(
            [
                (IPField("pdst", "0.0.0.0"),
                 (lambda pkt: pkt.ptype == 0x0800 and pkt.plen == 4,
                  lambda pkt, val: pkt.ptype == 0x0800 and
                  (pkt.plen == 4 or (pkt.plen is None and
                                     (val is None or valid_net(val)))))),
                (IP6Field("pdst", "::"),
                 (lambda pkt: pkt.ptype == 0x86dd and pkt.plen == 16,
                  lambda pkt, val: pkt.ptype == 0x86dd and
                  (pkt.plen == 16 or (pkt.plen is None and
                                      (val is None or valid_net6(val)))))),
            ],
            StrFixedLenField("pdst", None, length_from=lambda pkt: pkt.plen),
        ),
    ]

    def hashret(self):
        return struct.pack(">HHH", self.hwtype, self.ptype,
                           ((self.op + 1) // 2)) + self.payload.hashret()

    def answers(self, other):
        if not isinstance(other, ARP):
            return False
        if self.op != other.op + 1:
            return False
        # We use a loose comparison on psrc vs pdst to catch answers
        # with ARP leaks
        self_psrc = self.get_field('psrc').i2m(self, self.psrc)
        other_pdst = other.get_field('pdst').i2m(other, other.pdst)
        return self_psrc[:len(other_pdst)] == other_pdst[:len(self_psrc)]

    def route(self):
        fld, dst = self.getfield_and_val("pdst")
        fld, dst = fld._find_fld_pkt_val(self, dst)
        if isinstance(dst, Gen):
            dst = next(iter(dst))
        if isinstance(fld, IP6Field):
            return conf.route6.route(dst)
        elif isinstance(fld, IPField):
            return conf.route.route(dst)
        else:
            return None, None, None

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

    def mysummary(self):
        if self.op == 1:
            return self.sprintf("ARP who has %pdst% says %psrc%")
        if self.op == 2:
            return self.sprintf("ARP is at %hwsrc% says %psrc%")
        return self.sprintf("ARP %op% %psrc% > %pdst%")
Example #23
0
class RadioTap(Packet):
    name = "RadioTap dummy"
    fields_desc = [ByteField('version', 0),
                   ByteField('pad', 0),
                   LEShortField('len', None),
                   FlagsField('present', None, -32, ['TSFT', 'Flags', 'Rate', 'Channel', 'FHSS', 'dBm_AntSignal',  # noqa: E501
                                                     'dBm_AntNoise', 'Lock_Quality', 'TX_Attenuation', 'dB_TX_Attenuation',  # noqa: E501
                                                     'dBm_TX_Power', 'Antenna', 'dB_AntSignal', 'dB_AntNoise',  # noqa: E501
                                                     'RXFlags', 'TXFlags', 'b17', 'b18', 'ChannelPlus', 'MCS', 'A_MPDU',  # noqa: E501
                                                     'VHT', 'timestamp', 'b24', 'b25', 'b26', 'b27', 'b28', 'b29',  # noqa: E501
                                                     'RadiotapNS', 'VendorNS', 'Ext']),  # noqa: E501
                   # Extended presence mask
                   ConditionalField(PacketListField("Ext", [], next_cls_cb=_next_radiotap_extpm), lambda pkt: pkt.present and pkt.present.Ext),  # noqa: E501
                   # Default fields
                   ConditionalField(_RadiotapReversePadField(BitField("mac_timestamp", 0, -64)), lambda pkt: pkt.present and pkt.present.TSFT),  # noqa: E501
                   ConditionalField(
                       _RadiotapReversePadField(
                           FlagsField("Flags", None, -8, ['CFP', 'ShortPreamble', 'wep', 'fragment',  # noqa: E501
                                                          'FCS', 'pad', 'badFCS', 'ShortGI'])  # noqa: E501
                       ),
                       lambda pkt: pkt.present and pkt.present.Flags),
                   ConditionalField(_RadiotapReversePadField(ByteField("Rate", 0)), lambda pkt: pkt.present and pkt.present.Rate),  # noqa: E501
                   ConditionalField(_RadiotapReversePadField(LEShortField("Channel", 0)), lambda pkt: pkt.present and pkt.present.Channel),  # noqa: E501
                   ConditionalField(
                       _RadiotapReversePadField(
                           FlagsField("ChannelFlags", None, -16, ['res1', 'res2', 'res3', 'res4', 'Turbo', 'CCK',  # noqa: E501
                                                                  'OFDM', '2GHz', '5GHz', 'Passive', 'Dynamic_CCK_OFDM',  # noqa: E501
                                                                  'GFSK', 'GSM', 'StaticTurbo', '10MHz', '5MHz'])  # noqa: E501
                       ),
                       lambda pkt: pkt.present and pkt.present.Channel),
                   ConditionalField(_RadiotapReversePadField(_dbmField("dBm_AntSignal", -256)), lambda pkt: pkt.present and pkt.present.dBm_AntSignal),  # noqa: E501
                   ConditionalField(_RadiotapReversePadField(_dbmField("dBm_AntNoise", -256)), lambda pkt: pkt.present and pkt.present.dBm_AntNoise),  # noqa: E501
                   ConditionalField(_RadiotapReversePadField(ByteField("Antenna", 0)), lambda pkt: pkt.present and pkt.present.Antenna),  # noqa: E501
                   # RX Flags
                   ConditionalField(_RadiotapReversePadField(FlagsField("RXFlags", None, -16, ["res1", "BAD_PLCP", "res2"])),   # noqa: E501
                                    lambda pkt: pkt.present and pkt.present.RXFlags),  # noqa: E501#
                   # TX Flags
                   ConditionalField(_RadiotapReversePadField(FlagsField("TXFlags", None, -16, ["TX_FAIL", "CTS", "RTS", "NOACK", "NOSEQ"])),   # noqa: E501
                                    lambda pkt: pkt.present and pkt.present.TXFlags),  # noqa: E501
                   # ChannelPlus
                   ConditionalField(
                       _RadiotapReversePadField(
                           FlagsField("ChannelFlags2", None, -32, ['res1', 'res2', 'res3', 'res4', 'Turbo', 'CCK',  # noqa: E501
                                                                   'OFDM', '2GHz', '5GHz', 'Passive', 'Dynamic_CCK_OFDM',  # noqa: E501
                                                                   'GFSK', 'GSM', 'StaticTurbo', '10MHz', '5MHz',  # noqa: E501
                                                                   '20MHz', '40MHz_ext_channel_above', '40MHz_ext_channel_below',  # noqa: E501
                                                                   'res5', 'res6', 'res7', 'res8', 'res9'])  # noqa: E501
                       ),
                       lambda pkt: pkt.present and pkt.present.ChannelPlus),
                   ConditionalField(_RadiotapReversePadField(LEShortField("ChannelFrequency", 0)), lambda pkt: pkt.present and pkt.present.ChannelPlus),  # noqa: E501
                   ConditionalField(_RadiotapReversePadField(ByteField("ChannelNumber", 0)), lambda pkt: pkt.present and pkt.present.ChannelPlus),  # noqa: E501
                   # MCS
                   ConditionalField(
                       _RadiotapReversePadField(FlagsField("knownMCS", None, -8, ['bandwidth', 'MCS_index', 'guard_interval', 'HT_format',  # noqa: E501
                                                                                  'FEC_type', 'STBC_streams', 'Ness', 'Ness_MSB'])),  # noqa: E501
                       lambda pkt: pkt.present and pkt.present.MCS),
                   ConditionalField(BitEnumField("bandwidth", 0, 2, {0: "20MHz", 1: "40MHz", 2: "ht40Mhz-", 3: "ht40MHz+"}),  # noqa: E501
                                    lambda pkt: pkt.present and pkt.present.MCS),  # noqa: E501
                   ConditionalField(BitEnumField("guard_interval", 0, 1, {0: "Long_GI", 1: "Short_GI"}), lambda pkt: pkt.present and pkt.present.MCS),  # noqa: E501
                   ConditionalField(BitEnumField("HT_format", 0, 1, {0: "mixed", 1: "greenfield"}), lambda pkt: pkt.present and pkt.present.MCS),  # noqa: E501
                   ConditionalField(BitEnumField("FEC_type", 0, 1, {0: "BCC", 1: "LDPC"}), lambda pkt: pkt.present and pkt.present.MCS),  # noqa: E501
                   ConditionalField(BitField("STBC_streams", 0, 2), lambda pkt: pkt.present and pkt.present.MCS),  # noqa: E501
                   ConditionalField(BitField("Ness_LSB", 0, 1), lambda pkt: pkt.present and pkt.present.MCS),  # noqa: E501
                   ConditionalField(ByteField("MCS_index", 0), lambda pkt: pkt.present and pkt.present.MCS),  # noqa: E501
                   # A_MPDU
                   ConditionalField(_RadiotapReversePadField(LEIntField("A_MPDU_ref", 0)), lambda pkt: pkt.present and pkt.present.A_MPDU),  # noqa: E501
                   ConditionalField(
                       _RadiotapReversePadField(
                           FlagsField("A_MPDU_flags", None, -32, ['Report0Subframe', 'Is0Subframe', 'KnownLastSubframe',  # noqa: E501
                                                                  'LastSubframe', 'CRCerror', 'EOFsubframe', 'KnownEOF',  # noqa: E501
                                                                  'res1', 'res2', 'res3', 'res4', 'res5', 'res6', 'res7', 'res8'])  # noqa: E501
                       ),
                       lambda pkt: pkt.present and pkt.present.A_MPDU),
                   # VHT
                   ConditionalField(
                       _RadiotapReversePadField(
                           FlagsField("KnownVHT", None, -16, ['STBC', 'TXOP_PS_NOT_ALLOWED', 'GuardInterval', 'SGINsysmDis',  # noqa: E501
                                                              'LDPCextraOFDM', 'Beamformed', 'Bandwidth', 'GroupID', 'PartialAID',  # noqa: E501
                                                              'res1', 'res2', 'res3', 'res4', 'res5', 'res6', 'res7'])  # noqa: E501
                       ),
                       lambda pkt: pkt.present and pkt.present.VHT),
                   ConditionalField(
                       _RadiotapReversePadField(
                           FlagsField("PresentVHT", None, -8, ['STBC', 'TXOP_PS_NOT_ALLOWED', 'GuardInterval', 'SGINsysmDis',  # noqa: E501
                                                               'LDPCextraOFDM', 'Beamformed', 'res1', 'res2'])  # noqa: E501
                       ),
                       lambda pkt: pkt.present and pkt.present.VHT),
                   ConditionalField(_RadiotapReversePadField(ByteEnumField("bandwidth", 0, _vht_bandwidth)), lambda pkt: pkt.present and pkt.present.VHT),  # noqa: E501
                   ConditionalField(_RadiotapReversePadField(StrFixedLenField("mcs_nss", 0, length=5)), lambda pkt: pkt.present and pkt.present.VHT),  # noqa: E501
                   ConditionalField(_RadiotapReversePadField(ByteField("GroupID", 0)), lambda pkt: pkt.present and pkt.present.VHT),  # noqa: E501
                   ConditionalField(_RadiotapReversePadField(ShortField("PartialAID", 0)), lambda pkt: pkt.present and pkt.present.VHT),  # noqa: E501
                   StrLenField('notdecoded', "", length_from=lambda pkt: pkt.len - pkt._tmp_dissect_pos)]  # noqa: E501

    def guess_payload_class(self, payload):
        if self.present and self.present.Flags and self.Flags.FCS:
            return Dot11FCS
        return Dot11

    def post_build(self, p, pay):
        if self.len is None:
            p = p[:2] + struct.pack("!H", len(p))[::-1] + p[4:]
        return p + pay
Example #24
0
class PNIORealTime(Packet):
    """PROFINET cyclic real-time"""
    name = "PROFINET Real-Time"
    fields_desc = [
        NotionalLenField("len", None, length_from=lambda p, s: len(s)),
        NotionalLenField("dataLen", None, length_from=lambda p, s: len(s[:-4].rstrip(b"\0"))),
        LowerLayerBoundPacketListField("data", [], _pnio_rtc_guess_payload_class, length_from=lambda p: p.dataLen),
        StrFixedLenField("padding", "", length_from=lambda p: p[PNIORealTime].padding_length()),
        ShortField("cycleCounter", 0),
        FlagsField("dataStatus", 0x35, 8, _PNIO_DS_FLAGS),
        ByteField("transferStatus", 0)
    ]
    overload_fields = {
        ProfinetIO: {"frameID": 0x8000},   # RT_CLASS_1
    }

    def padding_length(self):
        """Compute the length of the padding need for the ethernet frame"""
        fld, val = self.getfield_and_val("data")

        # use the len field if available to define the padding length, eg for
        # dissected packets
        pkt_len = self.getfieldval("len")
        if pkt_len is not None:
            return max(0, pkt_len - len(fld.addfield(self, b"", val)) - 4)

        if isinstance(self.underlayer, ProfinetIO) and \
                isinstance(self.underlayer.underlayer, UDP):
            return max(0, 12 - len(fld.addfield(self, b"", val)))
        else:
            return max(0, 40 - len(fld.addfield(self, b"", val)))

    @staticmethod
    def analyse_data(packets):
        """Analyse the data to find heuristical properties and determine
        location and type of data"""
        loc = PNIORealTime.find_data(packets)
        loc = PNIORealTime.analyse_profisafe(packets, loc)
        pnio_update_config(loc)
        return loc

    @staticmethod
    def find_data(packets):
        """Analyse a packet list to extract data offsets from packets data."""
        # a dictionary to count data offsets (ie != 0x80)
        # It's formatted: {(src, dst): (total, [count for offset in len])}
        heuristic = {}

        # Counts possible data locations
        # 0x80 are mainly IOxS and trailling 0x00s are just padding
        for pkt in packets:
            if PNIORealTime in pkt:
                pdu = bytes(pkt[PNIORealTime])[:-4].rstrip(b"\0")

                if (pkt.src, pkt.dst) not in heuristic:
                    heuristic[(pkt.src, pkt.dst)] = (0, [])

                total, counts = heuristic[(pkt.src, pkt.dst)]

                if len(counts) < len(pdu):
                    counts.extend([0 for _ in range(len(pdu) - len(counts))])

                for i in range(len(pdu)):
                    if orb(pdu[i]) != 0x80:
                        counts[i] += 1

                comm = (pkt.src, pkt.dst)
                heuristic[comm] = (total + 1, counts)

        # Determine data locations
        locations = {}
        for comm in heuristic:
            total, counts = heuristic[comm]
            length = len(counts)
            loc = locations[comm] = []
            start = None
            for i in range(length):
                if counts[i] > total // 2:   # Data if more than half is != 0x80
                    if start is None:
                        start = i
                else:
                    if start is not None:
                        loc.append((
                            start - length,
                            PNIORealTimeRawData,
                            {"length": i - start}
                        ))
                        start = None

        return locations

    @staticmethod
    def analyse_profisafe(packets, locations=None):
        """Analyse a packet list to find possible PROFISafe profils.

        It's based on an heuristical analysis of each payload to try to find
        CRC and control/status byte.

        locations: possible data locations. If not provided, analyse_pn_rt will
        be called beforehand. If not given, it calls in the same time
        analyse_data which update the configuration of the data field"""
        # get data locations and entropy of bytes
        if not locations:
            locations = PNIORealTime.find_data(packets)
        entropies = PNIORealTime.data_entropy(packets, locations)

        # Try to find at least 3 high entropy successive bytes (the CRC)
        for comm in entropies:
            entropy = dict(entropies[comm])  # Convert tuples to key => value

            for i in range(len(locations[comm])):
                # update each location with its value after profisafe analysis
                locations[comm][i] = \
                    PNIORealTime.analyse_one_profisafe_location(
                    locations[comm][i], entropy
                )

        return locations

    @staticmethod
    def analyse_one_profisafe_location(location, entropy):
        """Analyse one PNIO RTC data location to find if its a PROFISafe

        :param location: location to analyse, a tuple (start, type, config)
        :param entropy: the entropy of each byte of the packet data
        :returns: the configuration associated with the data
        """
        start, klass, conf = location
        if conf["length"] >= 4:     # Minimal PROFISafe length
            succ_count = 0
            for j in range(start, start + conf["length"]):
                # Limit for a CRC is set to 6 bit of entropy min
                if j in entropy and entropy[j] >= 6:
                    succ_count += 1
                else:
                    succ_count = 0
            # PROFISafe profiles must end with at least 3 bytes of high entropy
            if succ_count >= 3:  # Possible profisafe CRC
                return (
                    start,
                    Profisafe,
                    {"CRC": succ_count, "length": conf["length"]}
                )
        # Not a PROFISafe profile
        return (start, klass, conf)

    @staticmethod
    def data_entropy(packets, locations=None):
        """Analyse a packet list to find the entropy of each data byte

        locations: possible data locations. If not provided, analyse_pn_rt will
        be called beforehand. If not given, it calls in the same time
        analyse_data which update the configuration of the data field"""
        if not locations:
            locations = PNIORealTime.find_data(packets)

        # Retrieve the entropy of each data byte, for each communication
        entropies = {}
        for comm in locations:
            if len(locations[comm]) > 0:  # Doesn't append empty data
                entropies[comm] = []
                comm_packets = []

                # fetch all packets from the communication
                for pkt in packets:
                    if PNIORealTime in pkt and (pkt.src, pkt.dst) == comm:
                        comm_packets.append(
                            bytes(pkt[PNIORealTime])[:-4].rstrip(b"\0")
                        )

                # Get the entropy
                for start, dummy, config in locations[comm]:
                    for i in range(start, start + config["length"]):
                        entropies[comm].append(
                            (i, entropy_of_byte(comm_packets, i))
                        )

        return entropies

    @staticmethod
    def draw_entropy(packets, locations=None):
        """Plot the entropy of each data byte of PN RT communication"""
        import matplotlib.pyplot as plt
        import matplotlib.cm as cm
        entropies = PNIORealTime.data_entropy(packets, locations)

        rows = len(entropies)
        cur_row = 1
        for comm in entropies:
            index = []
            vals = []
            for i, ent in entropies[comm]:
                index.append(i)
                vals.append(ent)

            # Offsets the indexes to get the index from the beginning
            offset = -min(index)
            index = [i + offset for i in index]

            plt.subplot(rows, 1, cur_row)
            plt.bar(index, vals, 0.8, color="r")
            plt.xticks([i + 0.4 for i in index], index)
            plt.title("Entropy from %s to %s" % comm)
            cur_row += 1
            plt.ylabel("Shannon Entropy")

        plt.xlabel("Byte offset")   # x label only on the last row
        plt.legend()

        plt.tight_layout()
        plt.show()
Example #25
0
class SAPDiag(PacketNoPadded):
    """SAP Diag packet

    This packet holds the Diag Header and serve as a container for
    :class:`SAPDiagItem` items. It handles compression/decompression, adding the
    appropriate Compression Header when necessary.
    """
    name = "SAP Diag"
    fields_desc = [
        ByteField("mode", 0),

        # Communication flags
        BitField("com_flag_TERM_GRA", 0, 1),
        BitField("com_flag_TERM_NNM", 0, 1),
        BitField("com_flag_TERM_CAS", 0, 1),
        BitField("com_flag_TERM_INI", 0, 1),
        BitField("com_flag_TERM_EOP", 0, 1),
        BitField("com_flag_TERM_NOP", 0, 1),
        BitField("com_flag_TERM_EOC", 0, 1),
        BitField("com_flag_TERM_EOS", 0, 1),
        ByteField("mode_stat", 0),
        ByteField("err_no", 0),
        ByteField("msg_type", 0),
        ByteField("msg_info", 0),
        ByteField("msg_rc", 0),
        ByteEnumKeysField("compress", 0, diag_compress_values),

        # Compression Header
        ConditionalField(LEIntField("uncompress_length", None),
                         lambda pkt: pkt.compress == 1),
        ConditionalField(
            ByteEnumField("algorithm", 0x12, {
                0x12: "LZH",
                0x10: "LZC"
            }), lambda pkt: pkt.compress == 1),
        ConditionalField(StrFixedLenField("magic_bytes", "\x1f\x9d", 2),
                         lambda pkt: pkt.compress == 1),
        ConditionalField(ByteField("special", 2),
                         lambda pkt: pkt.compress == 1),

        # SNC Frame
        ConditionalField(PacketField("snc_frame", None, SAPSNCFrame),
                         lambda pkt: pkt.compress in [2, 3]),

        # Message info
        ConditionalField(StrEncodedPaddedField("info", None),
                         lambda pkt: pkt.err_no != 0),

        # Payload
        PacketListField("message", None, SAPDiagItem)
    ]

    def do_compress(self, s):
        """Compress a string using SAP compression C++ extension.

        :param s: string to compress
        :type s: C{string}

        :return: string compression header plus the compressed string
        :rtype: C{string}

        :raise pysapcompress.Error: when a compression error is raised
        """
        if len(s) > 0:
            # Compress the payload and return the output
            (_, _, outbuffer) = pysapcompress.compress(s,
                                                       pysapcompress.ALG_LZH)
            return outbuffer

    def do_decompress(self, s, length):
        """Decompress a string using SAP compression C++ extension.

        :param s: compression header plus compressed string
        :type s: C{string}

        :param length: reported compressed length
        :type length: ``int``

        :return: decompressed string
        :rtype: C{string}

        :raise pysapcompress.Error: when a decompression error is raised
        """
        if len(s) > 0:
            # Decompress the payload and return the output
            (_, _, outbuffer) = pysapcompress.decompress(s, length)
            return outbuffer

    def pre_dissect(self, s):
        """Prepares the packet for dissection. If the compression flag is set,
        decompress the payload.
        """
        # If the compression flag is set, decompress everything after the headers
        if s[7] == "\x01":
            # First need to get the reported decompressed length
            (reported_length, ) = unpack("<I", s[8:12])

            # Then return the headers (Diag and Compression) and the payload (message field)
            try:
                return s[:16] + self.do_decompress(s[8:], reported_length)
            except DecompressError:
                return s
        # Uncompressed packet, just return them
        return s

    def post_build(self, p, pay):
        """Compress the payload. If the compression flag is set, compress both
        the message field and the payload.
        """
        if pay is None:
            pay = ''
        if self.compress == 1:
            payload = "".join([str(item) for item in self.message]) + pay
            if len(payload) > 0:
                try:
                    return p[:8] + self.do_compress(payload)
                except CompressError:
                    return p + pay
        return p + pay

    def get_item(self, item_type=None, item_id=None, item_sid=None):
        """Get an item from the packet's message. Returns None if the message
        is not found, or a list if the item is found multiple times.

        :param item_type: item type byte or string value
        :type item_type: ``int`` or C{string} or ``list``

        :param item_id: item ID byte or string value
        :type item_id: ``int`` or C{string} or ``list``

        :param item_sid: item SID byte or string value
        :type item_sid: ``int`` or C{string} or ``list``

        :return: list of items found on the packet or None
        :rtype: ``list`` of :class:`SAPDiagItem`
        """
        # Expand list lookups
        items = []
        if item_type is not None and type(item_type) == list:
            for itype in item_type:
                items.extend(self.get_item(itype, item_id, item_sid))
            return items
        if item_id is not None and type(item_id) == list:
            for iid in item_id:
                items.extend(self.get_item(item_type, iid, item_sid))
            return items
        if item_sid is not None and type(item_sid) == list:
            for isid in item_sid:
                items.extend(self.get_item(item_type, item_id, isid))
            return items

        # Perform name lookups
        if item_type is not None and isinstance(item_type, str):
            item_type = list(diag_item_types.keys())[list(
                diag_item_types.values()).index(item_type)]
        if item_id is not None and isinstance(item_id, str):
            item_id = list(diag_appl_ids.keys())[list(
                diag_appl_ids.values()).index(item_id)]
        if item_sid is not None and isinstance(item_sid, str):
            item_sid = list(diag_appl_sids[item_id].keys())[list(
                diag_appl_sids[item_id].values()).index(item_sid)]

        # Filter and return items
        if item_sid is None and item_id is None:
            items = [
                item for item in self.message
                if hasattr(item, "item_type") and item.item_type == item_type
            ]
        elif item_sid is None:
            items = [
                item for item in self.message if hasattr(item, "item_type")
                and item.item_type == item_type and item.item_id == item_id
            ]
        else:
            items = [
                item for item in self.message
                if hasattr(item, "item_type") and item.item_type == item_type
                and item.item_id == item_id and item.item_sid == item_sid
            ]

        return items
Example #26
0
class SAPIGS(Packet):
    """SAP Internet Graphic Server call packet

    This packet is used for the Remote IGS Function Call protocol.
    """
    name = "SAP IGS Call"
    fields_desc = [
        StrFixedLenPaddedField("function", "", padd="\x00", length=32),
        StrFixedLenPaddedField("listener", "ListenerX", padd="\x00",
                               length=32),
        StrFixedLenPaddedField("hostname", "pysap", padd="\x00", length=81),
        StrFixedLenPaddedField("id", "1234", padd="\x00", length=4),
        StrFixedLenPaddedField("padd1", "\x00" * 15, length=15),
        ByteField("todo1", 0x01),  # TODO: need to work on it
        StrFixedLenPaddedField("padd2", "\x00" * 20, length=20),
        ByteField("todo2", 0x08),  # TODO: need to work on it
        StrFixedLenPaddedField("padd3", "\x00" * 6, length=6),
        StrFixedLenField("eye_catch", "TransMagic", length=10),
        StrFixedLenPaddedField("padd4", "\x00" * 2, length=2),
        StrFixedLenField("codepage", "4103", length=4),
        StrFixedLenPaddedField("offset_content", "", padd="\x00", length=16),
        StrFixedLenPaddedField("packet_size", "", padd="\x00", length=16),
    ]

    @staticmethod
    def http(host, port, interpreter, files=None, tls=False, method='POST'):
        """HTTP request for IGS

        This method build a http(s) request for IGS HTTP Multiplexer service
        instead of Remote IGS Function Call

        :param host: remote host to connect to
        :type host: ``string``

        :param port: remote port to connect to
        :type port: ``int``

        :param interpreter: interpreter of function to call
        :type interpreter: ``string``

        :param files: list of files to send in case of multipart/form-data
        :type files: ``dict``

        :param tls: using https or not
        :type tls: ``bool``

        :param method: HTTP request method to use
        :type method: ``string``

        :return: the HTTP request to send as raw
        :rtype: ``string``

        :raise ImportError: if the requests library can't be imported
        """
        if Request is None:
            raise ImportError("requests library not available")

        protocol = 'https' if tls else 'http'
        url = "%s://%s:%d/%s" % (protocol, host, port, interpreter
                                 )  # forge url
        # using PreparedRequest to retrieve the raw http request
        req = Request(method, url, files=files).prepare()
        # update User-Agent header
        req.headers['User-Agent'] = 'pysap'
        # format the request than could be send with SAP NI
        req_format = ('{}\r\n{}\r\n\r\n{}'.format(
            req.method + ' ' + req.url + ' HTTP/1.1',
            '\r\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
            req.body))
        return req_format
Example #27
0
class SAPDPInfo3(Packet):
    """SAP Dispatcher Info packet

    This packet is encapsulated inside SAPMS packet
    and before the MS ADM payload. Kernel 749.
    """
    name = "SAP Dispatcher Info v3"
    fields_desc = [
        IntField("dp_padd1", 185),
        ByteEnumKeysField("dp_req_prio", 0x1, dp_prio_values),
        ShortField("dp_padd2", 0x0),
        ByteField("dp_padd3", 0x0),
        ByteField("dp_padd4", 0x0),
        IntField("dp_req_len", 0x0),
        ShortField("dp_padd5", 0x0),
        ByteField("dp_padd6", 0x0),
        ByteEnumKeysField("dp_type_from", 0x2, dp_type_values),
        StrFixedLenField("dp_fromname", " " * 40, 40),
        ShortField("dp_padd7", 0x0),
        ByteField("dp_padd8", 0x0),
        ByteEnumKeysField("dp_agent_type_from", 0x6, dp_agent_type_values),
        ShortField("dp_padd9", 0x0),
        ByteField("dp_padd10", 0x0),
        ByteField("dp_padd12", 0xff),
        ShortField("dp_padd13", 0x0),
        ByteEnumKeysField("dp_worker_type_from", 0x1, dp_worker_type_values),
        ByteField("dp_worker_from_num", 0x0),
        ByteField("dp_padd133", 0x0),
        ShortField("dp_padd111", 0x0000),
        ByteField("dp_padd11", 0x00),
        ByteField("dp_addr_from_t", 0x0),
        ShortField("dp_padd14", 0x0),
        ShortField("dp_addr_from_u", 0x0),
        ByteField("dp_addr_from_m", 0x0),
        ByteField("dp_padd15", 0x1),
        IntField("dp_respid_from", 0x0),
        ShortField("dp_padd16", 0x0),
        ByteField("dp_padd17", 0x0),
        ByteEnumKeysField("dp_type_to", 0x2, dp_type_values),
        StrFixedLenField("dp_toname", " " * 40, 40),
        ShortField("dp_padd18", 0x0),
        ByteField("dp_padd19", 0x0),
        ByteEnumKeysField("dp_agent_type_to", 0x6, dp_agent_type_values),
        ShortField("dp_padd20", 0x0),
        ByteField("dp_padd21", 0x0),
        ByteEnumKeysField("dp_worker_type_to", 0x1, dp_worker_type_values),
        ShortField("dp_padd22", 0x0),
        ByteField("dp_worker_to_num", 0x0),
        ByteField("dp_padd222", 0x0),
        IntField("dp_padd23", 0x0),
        ByteField("dp_addr_to_t", 0x0),
        ShortField("dp_padd24", 0x0),
        ShortField("dp_addr_to_u", 0x0),
        ByteField("dp_addr_from_m", 0x0),
        ByteField("dp_padd25", 0x1),
        IntField("dp_respid_to", 0x0),
        ShortField("dp_padd26", 0x0),
        ByteField("dp_padd27", 0x0),
        ByteEnumKeysField("dp_req_handler", 40, dp_req_handler_values),
        StrFixedLenField("dp_padd28", "\xff\xff\xff\xff", 4),
        IntField("dp_padd29", 0x0),
        IntField("dp_padd30", 0x0),
        IntField("dp_padd31", 0x0),
        StrFixedLenField("dp_padd32", "\x00" * 5, 5),
    ]
Example #28
0
class SM_Confirm(Packet):
    name = "Pairing Confirm"
    fields_desc = [StrFixedLenField("confirm", b'\x00' * 16, 16)]
Example #29
0
class SAPMSAdmRecord(PacketNoPadded):
    """SAP Message Server Administration Record packet

    Packet for Message Server administration records. Each administration
    package has a variable number of records, each one specifies an operation
    to execute.
    """
    name = "SAP Message Server Adm Record"
    fields_desc = [
        ByteEnumKeysField("opcode", 0x00, ms_adm_opcode_values),
        ByteField("serial_number", 0x00),
        ByteField("executed", 0x00),
        ByteField("errorno", 0x00),  # TODO: Look for error names
        ConditionalField(
            StrFixedLenField("record", None, 75), lambda pkt: pkt.opcode not in
            [0x01, 0x15, 0x2e] and pkt.executed == 0x01),
        ConditionalField(
            StrFixedLenField("record_pad", None, 25), lambda pkt: pkt.opcode
            not in [0x01, 0x15, 0x2e] and pkt.executed == 0x01),
        ConditionalField(
            StrFixedLenField("record", None, 100), lambda pkt: pkt.opcode
            not in [0x01, 0x15, 0x2e] and pkt.executed == 0x00),

        # TODO: Add more opcodes fields

        # AD_PROFILE and AD_SHARED_PARAMETER fields
        ConditionalField(StrNullFixedLenPaddedField("parameter", "", 100),
                         lambda pkt: pkt.opcode in [0x01, 0x2e]),

        # AD_RZL_STRG opcode
        ConditionalField(
            ByteEnumKeysField("rzl_strg_type", 1, ms_adm_rzl_strg_type_values),
            lambda pkt: pkt.opcode in [0x15]),
        ConditionalField(ByteField("rzl_strg_name_length", 0),
                         lambda pkt: pkt.opcode in [0x15]),
        ConditionalField(ByteField("rzl_strg_value_offset", 0),
                         lambda pkt: pkt.opcode in [0x15]),
        ConditionalField(ByteField("rzl_strg_value_length", 0),
                         lambda pkt: pkt.opcode in [0x15]),
        ConditionalField(StrFixedLenField("rzl_strg_name", None, 20),
                         lambda pkt: pkt.opcode in [0x15]),
        ConditionalField(
            IntField("rzl_strg_uptime", 0), lambda pkt: pkt.opcode in [0x15]
            and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_integer1", 0), lambda pkt: pkt.opcode in [0x15]
            and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_delay", 0), lambda pkt: pkt.opcode in [0x15] and
            pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_integer3", 0), lambda pkt: pkt.opcode in [0x15]
            and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_users", 0), lambda pkt: pkt.opcode in [0x15] and
            pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_quality", 0), lambda pkt: pkt.opcode in [0x15]
            and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_integer6", 0), lambda pkt: pkt.opcode in [0x15]
            and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_integer7", 0), lambda pkt: pkt.opcode in [0x15]
            and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_integer8", 0), lambda pkt: pkt.opcode in [0x15]
            and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            IntField("rzl_strg_integer9", 0), lambda pkt: pkt.opcode in [0x15]
            and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]),
        ConditionalField(
            StrFixedLenField("rzl_strg_value", None,
                             40), lambda pkt: pkt.opcode in [0x15] and pkt.
            rzl_strg_type not in [11, 15, 21, 31, 41, 51]),
        ConditionalField(StrFixedLenField("rzl_strg_padd2", None, 36),
                         lambda pkt: pkt.opcode in [0x15]),
    ]
Example #30
0
class SM_Random(Packet):
    name = "Pairing Random"
    fields_desc = [StrFixedLenField("random", b'\x00' * 16, 16)]
Example #31
0
class SAPMSProperty(Packet):
    """SAP Message Server Property packet.

    Packet containing information about properties.
    """
    name = "SAP Message Server Property"
    fields_desc = [
        StrNullFixedLenField("client", None, 40),
        IntEnumField("id", 0x00, ms_property_id_values),

        # MS_PROPERTY_VHOST
        ConditionalField(ShortEnumKeysField("logon", 0, ms_logon_type_values),
                         lambda pkt: pkt.id in [0x02]),
        ConditionalField(StrFixedLenField("pad", None, 12),
                         lambda pkt: pkt.id in [0x02]),
        ConditionalField(ShortField("len", 0), lambda pkt: pkt.id in [0x02]),
        ConditionalField(
            StrLenField("value", "", length_from=lambda pkt: pkt.len),
            lambda pkt: pkt.id in [0x02]),
        ConditionalField(ShortField("pad2", 0xffff),
                         lambda pkt: pkt.id in [0x02]),

        # MS_PROPERTY_IPADR
        ConditionalField(IPField("address", "0.0.0.0"),
                         lambda pkt: pkt.id in [0x03]),
        ConditionalField(IP6Field("address6", "::"),
                         lambda pkt: pkt.id in [0x03]),

        # MS_PROPERTY_PARAM
        ConditionalField(
            FieldLenField("param_len", 0, length_of="param", fmt="I"),
            lambda pkt: pkt.id in [0x04]),
        ConditionalField(
            StrLenField("param", "", length_from=lambda pkt: pkt.param_len),
            lambda pkt: pkt.id in [0x04]),
        ConditionalField(
            StrLenField("param_padding",
                        "",
                        length_from=lambda pkt: 100 - pkt.param_len),
            lambda pkt: pkt.id in [0x04]),
        ConditionalField(ShortField("pad3", 0), lambda pkt: pkt.id in [0x04]),
        ConditionalField(
            FieldLenField("value_len", 0x0, length_of="value", fmt="H"),
            lambda pkt: pkt.id in [0x04]),
        ConditionalField(
            StrLenField("value", "", length_from=lambda pkt: pkt.value_len),
            lambda pkt: pkt.id in [0x04]),

        # MS_PROPERTY_SERVICE
        ConditionalField(ShortField("service", 0),
                         lambda pkt: pkt.id in [0x05]),
        ConditionalField(ByteField("value", 0), lambda pkt: pkt.id in [0x05]),

        # Release Information fields
        ConditionalField(StrNullFixedLenField("release", "720", length=10),
                         lambda pkt: pkt.id in [0x07]),
        ConditionalField(IntField("patchno", 0), lambda pkt: pkt.id in [0x07]),
        ConditionalField(IntField("supplvl", 0), lambda pkt: pkt.id in [0x07]),
        ConditionalField(IntField("platform", 0),
                         lambda pkt: pkt.id in [0x07]),
    ]
Example #32
0
class SM_Encryption_Information(Packet):
    name = "Encryption Information"
    fields_desc = [
        StrFixedLenField("ltk", b"\x00" * 16, 16),
    ]
Example #33
0
class SAPDPInfo2(Packet):
    """SAP Dispatcher Info packet

    This packet is encapsulated inside SAPMS packet
    and before the MS ADM payload. Kernel 720.
    """
    name = "SAP Dispatcher Info v2"
    fields_desc = [
        ByteEnumKeysField("dp_req_prio", 0x1, dp_prio_values),
        XByteField("dp_blob_00", 0x2),
        XByteField("dp_blob_01", 0x80),
        XByteField("dp_blob_02", 0x21),
        ShortField("dp_blob_03", 0x0),
        ShortField("dp_blob_04", 0xffff),
        StrFixedLenField("dp_blob_05", "\xff\xff\xff\xff\xff", 5),
        ByteField("dp_addr_from_t", 0x0),
        StrFixedLenField("dp_blob_06", "\xff\xff", 2),
        StrFixedLenField("dp_blob_07", "\xff\xff\xff\xff", 4),
        StrFixedLenField("dp_blob_08", "\xff\xff\xff\xff", 4),
        StrFixedLenField("dp_blob_09", "\xff\xcc", 2),
        StrFixedLenField("dp_blob_10", "\x01\x00", 2),
        ByteField("dp_addr_from_m", 0x0),
        ByteField("dp_addr_from_u", 0x0),
        StrFixedLenField("dp_blob_11", "\xff\xff", 2),
        StrFixedLenField("dp_blob_12", "\xff\xff\xff\xff", 4),
        StrFixedLenField("dp_blob_13", "", 86),
        StrFixedLenField("dp_blob_14", "", 5),
        StrFixedLenField("dp_name_to", "", 40),
        XByteField("dp_blob_15", 0x0),
        ByteField("dp_addr_to_t", 0x0),
        ShortField("dp_addr_to_u", 0x0),
        ByteField("dp_addr_to_m", 0x0),
        ByteField("dp_blob_16", 0x0),
        ShortField("dp_respid_to", 0x0),
        StrFixedLenField("dp_blob_17", "\xff\xff\xff\xff", 4),
        StrFixedLenField("dp_blob_18", "\x00\x00\x00\x00", 4),
        Field("dp_blob_19", 0x1, '<L'),
        StrFixedLenField("dp_blob_20", "", 12),
        Field("dp_blob_21", 0x0, '<L'),
    ]
Example #34
0
class SM_Master_Identification(Packet):
    name = "Master Identification"
    fields_desc = [
        XLEShortField("ediv", 0),
        StrFixedLenField("rand", b'\x00' * 8, 8),
    ]
Example #35
0
class HCI_Cmd_LE_Long_Term_Key_Request_Reply(Packet):
    name = "LE Long Term Key Request Reply"
    fields_desc = [
        LEShortField("handle", 0),
        StrFixedLenField("ltk", b'\x00' * 16, 16),
    ]
Example #36
0
class SM_Identity_Information(Packet):
    name = "Identity Information"
    fields_desc = [
        StrFixedLenField("irk", b'\x00' * 16, 16),
    ]
Example #37
0
 def __init__(self, name, default, length=None, length_from=None, max_length=None):
     self.max_length = max_length or 200
     StrFixedLenField.__init__(self, name, default, length=length, length_from=length_from)
Example #38
0
class SM_Signing_Information(Packet):
    name = "Signing Information"
    fields_desc = [
        StrFixedLenField("csrk", b'\x00' * 16, 16),
    ]
Example #39
0
 def addfield(self, pkt, s, val):
     l = self.length_from(pkt)
     val += self.padd * l
     return StrFixedLenField.addfield(self, pkt, s, val)
Example #40
0
class HCI_Cmd_Set_Event_Mask(Packet):
    name = "Set Event Mask"
    fields_desc = [
        StrFixedLenField("mask", b"\xff\xff\xfb\xff\x07\xf8\xbf\x3d", 8)
    ]  # noqa: E501