Exemplo n.º 1
0
class MKADistributedCAKParamSet(MKAParamSet):
    """
    Distributed CAK Parameter Set (802.1X-2010, section 11.11).
    """

    #########################################################################
    #
    # IEEE 802.1X-2010 standard
    # Section 11.11
    #########################################################################
    #

    name = "Distributed CAK parameter set"
    fields_desc = [
        PadField(
            ByteEnumField(
                "param_set_type",
                5,
                _parameter_set_types
            ),
            2,
            padwith=b"\x00"
        ),
        ShortField("param_set_body_len", 0),
        XStrFixedLenField(
            "cak_aes_key_wrap",
            "",
            length=MKAParamSet.EAPOL_MKA_DEFAULT_KEY_WRAP_LEN
        ),
        XStrField("cak_key_name", "")
    ]
Exemplo n.º 2
0
class ESP(Packet):
    """
    Encapsulated Security Payload

    See https://tools.ietf.org/rfc/rfc4303.txt
    """
    name = 'ESP'

    fields_desc = [
        XIntField('spi', 0x0),
        IntField('seq', 0),
        XStrField('data', None),
    ]

    overload_fields = {
        IP: {
            'proto': socket.IPPROTO_ESP
        },
        IPv6: {
            'nh': socket.IPPROTO_ESP
        },
        IPv6ExtHdrHopByHop: {
            'nh': socket.IPPROTO_ESP
        },
        IPv6ExtHdrDestOpt: {
            'nh': socket.IPPROTO_ESP
        },
        IPv6ExtHdrRouting: {
            'nh': socket.IPPROTO_ESP
        },
    }
Exemplo n.º 3
0
class TLSInnerPlaintext(_GenericTLSSessionInheritance):
    name = "TLS Inner Plaintext"
    fields_desc = [
        _TLSMsgListField("msg", []),
        ByteEnumField("type", None, _tls_type),
        XStrField("pad", "")
    ]

    def pre_dissect(self, s):
        """
        We need to parse the padding and type as soon as possible,
        else we won't be able to parse the message list...
        """
        if len(s) < 1:
            raise Exception("Invalid InnerPlaintext (too short).")

        tmp_len = len(s) - 1
        if s[-1] != b"\x00":
            msg_len = tmp_len
        else:
            n = 1
            while s[-n] != b"\x00" and n < tmp_len:
                n += 1
            msg_len = tmp_len - n
        self.fields_desc[0].length_from = lambda pkt: msg_len

        self.type = struct.unpack("B", s[msg_len:msg_len + 1])[0]

        return s
Exemplo n.º 4
0
class WireguardTransport(Packet):
    name = "Wireguard Transport"

    fields_desc = [
        XLEIntField("receiver_index", 0),
        XLELongField("counter", 0),
        XStrField("encrypted_encapsulated_packet", None)
    ]
Exemplo n.º 5
0
class ZigbeeSecurityHeader(Packet):
    name = "Zigbee Security Header"
    fields_desc = [
        # Security control (1 octet)
        FlagsField("reserved1", 0, 2, ['reserved1', 'reserved2']),
        BitField("extended_nonce", 1, 1),  # set to 1 if the sender address field is present (source)  # noqa: E501
        # Key identifier
        BitEnumField("key_type", 1, 2, {
            0: 'data_key',
            1: 'network_key',
            2: 'key_transport_key',
            3: 'key_load_key'
        }),
        # Security level (3 bits)
        BitEnumField("nwk_seclevel", 0, 3, {
            0: "None",
            1: "MIC-32",
            2: "MIC-64",
            3: "MIC-128",
            4: "ENC",
            5: "ENC-MIC-32",
            6: "ENC-MIC-64",
            7: "ENC-MIC-128"
        }),
        # Frame counter (4 octets)
        XLEIntField("fc", 0),  # provide frame freshness and prevent duplicate frames  # noqa: E501
        # Source address (0/8 octets)
        ConditionalField(dot15d4AddressField("source", 0, adjust=lambda pkt, x: 8), lambda pkt: pkt.extended_nonce),  # noqa: E501
        # Key sequence number (0/1 octet): only present when key identifier is 1 (network key)  # noqa: E501
        ConditionalField(ByteField("key_seqnum", 0), lambda pkt: pkt.getfieldval("key_type") == 1),  # noqa: E501
        # Payload
        # the length of the encrypted data is the payload length minus the MIC
        XStrField("data", ""),  # noqa: E501
        # Message Integrity Code (0/variable in size), length depends on nwk_seclevel  # noqa: E501
        XStrField("mic", ""),
    ]

    def post_dissect(self, s):
        # Get the mic dissected correctly
        mic_length = util_mic_len(self)
        if mic_length > 0:  # Slice "data" into "data + mic"
            _data, _mic = self.data[:-mic_length], self.data[-mic_length:]
            self.data, self.mic = _data, _mic
        return s
Exemplo n.º 6
0
class SSLv2RequestCertificate(_SSLv2Handshake):
    """
    In order to parse a RequestCertificate, the exact message string should be
    fed to the class. This is how SSLv2 defines the challenge length...
    """
    name = "SSLv2 Handshake - Request Certificate"
    fields_desc = [ByteEnumField("msgtype", 7, _sslv2_handshake_type),
                   ByteEnumField("authtype", 1, {1: "md5_with_rsa"}),
                   XStrField("challenge", "")]

    def tls_session_update(self, msg_str):
        super(SSLv2RequestCertificate, self).tls_session_update(msg_str)
        self.tls_session.sslv2_challenge_clientcert = self.challenge
Exemplo n.º 7
0
class SSLv2ServerFinished(_SSLv2Handshake):
    """
    In order to parse a ServerFinished, the exact message string should be fed
    to the class. SSLv2 does not offer any other way to know the sid length.
    """
    name = "SSLv2 Handshake - Server Finished"
    fields_desc = [ByteEnumField("msgtype", 6, _sslv2_handshake_type),
                   XStrField("sid", "")]

    def build(self, *args, **kargs):
        fval = self.getfieldval("sid")
        if fval == b"":
            self.sid = self.tls_session.sid
        return super(SSLv2ServerFinished, self).build(*args, **kargs)

    def post_dissection_tls_session_update(self, msg_str):
        self.tls_session_update(msg_str)
        self.tls_session.sid = self.sid
Exemplo n.º 8
0
class SSLv2ClientFinished(_SSLv2Handshake):
    """
    In order to parse a ClientFinished, the exact message string should be fed
    to the class. SSLv2 does not offer any other way to know the c_id length.
    """
    name = "SSLv2 Handshake - Client Finished"
    fields_desc = [ByteEnumField("msgtype", 3, _sslv2_handshake_type),
                   XStrField("connection_id", "")]

    def build(self, *args, **kargs):
        fval = self.getfieldval("connection_id")
        if fval == b"":
            self.connection_id = self.tls_session.sslv2_connection_id
        return super(SSLv2ClientFinished, self).build(*args, **kargs)

    def post_dissection(self, pkt):
        s = self.tls_session
        if s.sslv2_connection_id is not None:
            if self.connection_id != s.sslv2_connection_id:
                pkt_info = pkt.firstlayer().summary()
                log_runtime.info("TLS: invalid client Finished received [%s]", pkt_info)
Exemplo n.º 9
0
class SSLv2ServerVerify(_SSLv2Handshake):
    """
    In order to parse a ServerVerify, the exact message string should be
    fed to the class. This is how SSLv2 defines the challenge length...
    """
    name = "SSLv2 Handshake - Server Verify"
    fields_desc = [ByteEnumField("msgtype", 5, _sslv2_handshake_type),
                   XStrField("challenge", "")]

    def build(self, *args, **kargs):
        fval = self.getfieldval("challenge")
        if fval is None:
            self.challenge = self.tls_session.sslv2_challenge
        return super(SSLv2ServerVerify, self).build(*args, **kargs)

    def post_dissection(self, pkt):
        s = self.tls_session
        if s.sslv2_challenge is not None:
            if self.challenge != s.sslv2_challenge:
                pkt_info = pkt.firstlayer().summary()
                log_runtime.info("TLS: invalid ServerVerify received [%s]", pkt_info)
Exemplo n.º 10
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",
                    0x16: "Default",
                    0x116: "Diagnostic",
                    0xe016: "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:
                    "Routing activation denied because the specified activation type requires a secure TLS TCP_DATA socket.",  # noqa: E501
                    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(XStrField("reserved_oem", b""),
                         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", 1),
                         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]),
        ConditionalField(XStrField("previous_msg", b""),
                         lambda p: p.payload_type in [0x8002, 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
Exemplo n.º 11
0
class NTLM_AUTHENTICATE(Packet):
    name = "NTLM Authenticate"
    messageType = 3
    OFFSET = 88
    NTLM_VERSION = 1
    fields_desc = [
        NTLM_Header,
        # LmChallengeResponseFields
        LEShortField('LmChallengeResponseLen', None),
        LEShortField('LmChallengeResponseMaxLen', None),
        LEIntField('LmChallengeResponseBufferOffset', None),
        # NtChallengeResponseFields
        LEShortField('NtChallengeResponseLen', None),
        LEShortField('NtChallengeResponseMaxLen', None),
        LEIntField('NtChallengeResponseBufferOffset', None),
        # DomainNameFields
        LEShortField('DomainNameLen', None),
        LEShortField('DomainNameMaxLen', None),
        LEIntField('DomainNameBufferOffset', None),
        # UserNameFields
        LEShortField('UserNameLen', None),
        LEShortField('UserNameMaxLen', None),
        LEIntField('UserNameBufferOffset', None),
        # WorkstationFields
        LEShortField('WorkstationLen', None),
        LEShortField('WorkstationMaxLen', None),
        LEIntField('WorkstationBufferOffset', None),
        # EncryptedRandomSessionKeyFields
        LEShortField('EncryptedRandomSessionKeyLen', None),
        LEShortField('EncryptedRandomSessionKeyMaxLen', None),
        LEIntField('EncryptedRandomSessionKeyBufferOffset', None),
        # NegotiateFlags
        FlagsField('NegotiateFlags', 0, -32, _negotiateFlags),
        # VERSION
        _NTLM_Version,
        # MIC
        XStrFixedLenField('MIC', b"", length=16),
        # Payload
        _NTLMPayloadField('Payload', OFFSET, [
            MultipleTypeField([
                (PacketField('LmChallengeResponse', LMv2_RESPONSE(),
                             LMv2_RESPONSE), lambda pkt: pkt.NTLM_VERSION == 2)
            ], PacketField('LmChallengeResponse', LM_RESPONSE(), LM_RESPONSE)),
            MultipleTypeField([(PacketField(
                'NtChallengeResponse', NTLMv2_RESPONSE(),
                NTLMv2_RESPONSE), lambda pkt: pkt.NTLM_VERSION == 2)],
                              PacketField('NtChallengeResponse',
                                          NTLM_RESPONSE(), NTLM_RESPONSE)),
            _NTLMStrField('DomainName', b''),
            _NTLMStrField('UserName', b''),
            _NTLMStrField('Workstation', b''),
            XStrField('EncryptedRandomSessionKey', b''),
        ])
    ]

    def post_build(self, pkt, pay):
        # type: (bytes, bytes) -> bytes
        return _NTML_post_build(
            self, pkt, self.OFFSET, {
                "LmChallengeResponse": 12,
                "NtChallengeResponse": 20,
                "DomainName": 28,
                "UserName": 36,
                "Workstation": 44,
                "EncryptedRandomSessionKey": 52
            }) + pay