class SAPHDBSegment(PacketNoPadded): """SAP HANA SQL Command Network Protocol Segment This packet represents a segment within a HDB packet. The segment header is comprised of 24 byte, being the first 13 bytes always the same fields and the remaining 11 bytes depend on the segment kind field. """ name = "SAP HANA SQL Command Network Protocol Segment" fields_desc = [ # Segment length needs to be calculated counting the segment header FieldLenField("segmentlength", None, length_of="parts", fmt="<i", adjust=lambda x, l:l+24), LESignedIntField("segmentofs", 0), FieldLenField("noofparts", None, count_of="parts", fmt="<h"), LESignedShortField("segmentno", 1), EnumField("segmentkind", 1, hdb_segmentkind_values, fmt="<b"), ConditionalField(EnumField("messagetype", 0, hdb_message_type_values, fmt="<b"), hdb_segment_is_request), ConditionalField(LESignedByteField("commit", 0), hdb_segment_is_request), ConditionalField(LESignedByteField("commandoptions", 0), hdb_segment_is_request), ConditionalField(LongField("reserved1", 0), hdb_segment_is_request), ConditionalField(ByteField("reserved2", 0), hdb_segment_is_reply), ConditionalField(EnumField("functioncode", 0, hdb_function_code_values, fmt="<h"), hdb_segment_is_reply), ConditionalField(LongField("reserved3", 0), hdb_segment_is_reply), ConditionalField(StrFixedLenField("reserved4", None, 11), lambda pkt: not (hdb_segment_is_reply(pkt) or hdb_segment_is_request(pkt))), PacketListField("parts", None, SAPHDBPart, count_from=lambda x: x.noofparts), ]
class ZigbeeAppDataPayload2(Packet): name = "Zigbee Application Layer Data Payload (General APS Frame Format)" fields_desc = [ # Frame control (1 octet) FlagsField("frame_control", 2, 4, ['reserved1', 'security', 'ack_req', 'extended_hdr']), BitEnumField("delivery_mode", 0, 2, {0: 'unicast', 1: 'indirect', 2: 'broadcast', 3: 'group_addressing'}), BitEnumField("aps_frametype", 0, 2, {0: 'data', 1: 'command', 2: 'ack'}), # Destination endpoint (0/1 octet) ConditionalField( ByteField("dst_endpoint", 10), lambda pkt: (pkt.frame_control.ack_req or pkt.aps_frametype == 2) ), # Group address (0/2 octets) TODO ConditionalField( # unsigned short (little-endian) EnumField("grp_address", 0, {}, fmt="<H"), lambda pkt: (pkt.frame_control.ack_req or pkt.aps_frametype == 2 \ or pkt.aps_frametype == 0) ), # Cluster identifier (0/2 octets) ConditionalField( # unsigned short (little-endian) EnumField("cluster", 0, _zcl_cluster_identifier, fmt="<H"), lambda pkt: (pkt.frame_control.ack_req or pkt.aps_frametype == 2 \ or pkt.aps_frametype == 0) ), # Profile identifier (0/2 octets) ConditionalField( EnumField("profile", 0, _zcl_profile_identifier, fmt="<H"), lambda pkt: (pkt.frame_control.ack_req or pkt.aps_frametype == 2 \ or pkt.aps_frametype == 0) ), # Source endpoint (0/1 octets) ConditionalField( ByteField("src_endpoint", 10), lambda pkt: (pkt.frame_control.ack_req or pkt.aps_frametype == 2 \ or pkt.aps_frametype == 0) ), # APS counter (1 octet) ByteField("counter", 0), # Extended header (0/1/2 octets) # cribbed from https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-zbee-aps.c # noqa: E501 ConditionalField( ByteEnumField( "fragmentation", 0, {0: "none", 1: "first_block", 2: "middle_block"}), lambda pkt: pkt.frame_control.extended_hdr ), ConditionalField(ByteField("block_number", 0), lambda pkt: pkt.fragmentation), # variable length frame payload: # 3 frame types: data, APS command, and acknowledgement # ConditionalField(StrField("data", ""), lambda pkt:pkt.aps_frametype == 0), # noqa: E501 ]
class ZigbeeAppDataPayload(Packet): name = "Zigbee Application Layer Data Payload (General APS Frame Format)" fields_desc = [ # Frame control (1 octet) FlagsField("frame_control", 2, 4, ['reserved1', 'security', 'ack_req', 'extended_hdr']), BitEnumField("delivery_mode", 0, 2, { 0: 'unicast', 1: 'indirect', 2: 'broadcast', 3: 'group_addressing' }), BitEnumField("aps_frametype", 0, 2, { 0: 'data', 1: 'command', 2: 'ack' }), # Destination endpoint (0/1 octet) ConditionalField( ByteField("dst_endpoint", 10), lambda pkt: ((pkt.frame_control.ack_req or pkt.aps_frametype == 2) and pkt. delivery_mode != 3)), # Group address (0/2 octets) TODO ConditionalField(XLEShortField("group", 0x0005), lambda pkt: (pkt.delivery_mode == 3)), # Cluster identifier (0/2 octets) EnumField("cluster", 0, _zcl_cluster_identifier, fmt="<H"), # Profile identifier (0/2 octets) EnumField("profile", 0, _zcl_profile_identifier, fmt="<H"), # Source endpoint (0/1 octets) ByteField("src_endpoint", 10), # APS counter (1 octet) ByteField("counter", 0), # Extended header (0/1/2 octets) # cribbed from https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-zbee-aps.c # noqa: E501 ConditionalField( ByteEnumField("fragmentation", 0, { 0: "none", 1: "first_block", 2: "middle_block" }), lambda pkt: pkt.frame_control.extended_hdr), ConditionalField(ByteField("block_number", 0), lambda pkt: pkt.fragmentation), # variable length frame payload: # 3 frame types: data, APS command, and acknowledgement # ConditionalField(StrField("data", ""), lambda pkt:pkt.aps_frametype == 0), # noqa: E501 ] def guess_payload_class(self, payload): if self.frame_control & 0x02: # we have a security header return ZigbeeSecurityHeader elif self.aps_frametype == 0: # data return ZigbeeClusterLibrary # TODO might also be another frame elif self.aps_frametype == 1: # command return ZigbeeAppCommandPayload else: return Packet.guess_payload_class(self, payload)
class TLS_Ext_EncryptedServerName(TLS_Ext_PrettyPacketList): name = "TLS Extension - Encrypted Server Name" fields_desc = [ ShortEnumField("type", 0xffce, _tls_ext), ShortField("len", None), EnumField("cipher", None, _tls_cipher_suites), ShortEnumField("key_exchange_group", None, _tls_named_groups), FieldLenField("key_exchange_len", None, length_of="key_exchange", fmt="H"), XStrLenField("key_exchange", "", length_from=lambda pkt: pkt.key_exchange_len), FieldLenField("record_digest_len", None, length_of="record_digest"), XStrLenField("record_digest", "", length_from=lambda pkt: pkt.record_digest_len), FieldLenField("encrypted_sni_len", None, length_of="encrypted_sni", fmt="H"), XStrLenField("encrypted_sni", "", length_from=lambda pkt: pkt.encrypted_sni_len) ]
class SAPHDBOptionPartRow(PacketNoPadded): """SAP HANA SQL Command Network Protocol Option Part Row This packet represents a row in an Option Part. Each row is comprised of a key, type and value. """ part_kind = None option_keys = None name = "SAP HANA SQL Command Network Protocol Option Part Row" fields_desc = [ MultiEnumField("key", 0, hdb_option_part_key_vals, depends_on=lambda x: x.part_kind, fmt="<b"), EnumField("type", 0, hdb_data_type_vals, fmt="<b"), ConditionalField(FieldLenField("length", None, length_of="value", fmt="<h"), lambda x: x.type in [29, 30, 33]), MultipleTypeField( [ (LESignedByteField("value", 0), lambda x: x.type == 1), (LESignedShortField("value", 0), lambda x: x.type == 2), (LESignedIntField("value", 0), lambda x: x.type == 3), (LESignedLongField("value", 0), lambda x: x.type == 4), (Field("value", 0, fmt="<d"), lambda x: x.type == 7), (YesNoByteField("value", 0), lambda x: x.type == 28), (StrFixedLenField("value", None, length_from=lambda x: x.length), lambda x: x.type in [29, 30, 33]), ], StrField("value", ""), ), ]
class USBEp(USBMitm): fields_desc = [ LEShortField('epnum', 0), EnumField( 'eptype', USBDefs.EP.TransferType.CTRL, USBDefs.EP.TransferType.desc, '<I' ), EnumField('epdir', USBDefs.EP.Direction.IN, USBDefs.EP.Direction.desc, '<I'), ] def extract_padding(self, s): return '', s def is_ctrl_0(self): return self.epnum == 0 and self.eptype == USBDefs.EP.TransferType.CTRL def is_interrupt(self): return self.eptype == USBDefs.EP.TransferType.INT
class TLS_Ext_SignatureAlgorithmsCert(TLS_Ext_Unknown): # RFC 8446 name = "TLS Extension - Signature Algorithms Cert" fields_desc = [ ShortEnumField("type", 0x31, _tls_ext), ShortField("len", None), SigAndHashAlgsLenField("sig_algs_len", None, length_of="sig_algs"), SigAndHashAlgsField("sig_algs", [], EnumField("hash_sig", None, _tls_hash_sig), length_from=lambda pkt: pkt.sig_algs_len) ] # noqa: E501
class RTPSSubMessage_HEARTBEAT(EPacket): """ 0...2...........7...............15.............23...............31 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | HEARTBEAT | flags | octetsToNextHeader | +---------------+---------------+---------------+---------------+ | EntityId readerEntityId | +---------------+---------------+---------------+---------------+ | EntityId writerEntityId | +---------------+---------------+---------------+---------------+ | | + SequenceNumber firstAvailableSeqNumber + | | +---------------+---------------+---------------+---------------+ | | + SequenceNumber lastSeqNumber + | | +---------------+---------------+---------------+---------------+ | Counter count | +---------------+---------------+---------------+---------------+ """ name = "RTPS HEARTBEAT (0x07)" fields_desc = [ XByteField("submessageId", 0x07), XByteField("submessageFlags", 0), EField(ShortField("octetsToNextHeader", 0)), EnumField( "reader_id", default=b"\x00\x00\x00\x00", fmt="4s", enum=_rtps_reserved_entity_ids, ), EnumField( "writer_id", default=b"\x00\x00\x00\x00", fmt="4s", enum=_rtps_reserved_entity_ids, ), XLongField("firstAvailableSeqNum", 0), XLongField("lastSeqNum", 0), EField(IntField("count", 0)), ]
class ManagementNewDevice(USBMitm): fields_desc = [ EnumField('speed', USBMitm.USBSpeed.HIGH_SPEED, USBMitm.USBSpeed.desc, '<I'), PacketField('device', DeviceDescriptor(), DeviceDescriptor), PacketField( 'configuration', ConfigurationDescriptor(), ConfigurationDescriptor ), ] def desc(self): return 'NewDevice'
class RTPSSubMessage_ACKNACK(EPacket): """ 0...2...........7...............15.............23...............31 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACKNACK | flags | octetsToNextHeader | +---------------+---------------+---------------+---------------+ | EntityId readerEntityId | +---------------+---------------+---------------+---------------+ | EntityId writerEntityId | +---------------+---------------+---------------+---------------+ | | + SequenceNumberSet readerSNState + | | +---------------+---------------+---------------+---------------+ | Counter count | +---------------+---------------+---------------+---------------+ """ name = "RTPS ACKNACK (0x06)" fields_desc = [ XByteField("submessageId", 0x06), XByteField("submessageFlags", 0x00), EField(ShortField("octetsToNextHeader", 0)), EnumField( "reader_id", default=b"\x00\x00\x00\x00", fmt="4s", enum=_rtps_reserved_entity_ids, ), EnumField( "writer_id", default=b"\x00\x00\x00\x00", fmt="4s", enum=_rtps_reserved_entity_ids, ), XStrLenField( "readerSNState", 0, length_from=lambda pkt: pkt.octetsToNextHeader - 8 - 4 ), XNBytesField("count", 0, 4), ]
class ZigbeeAppDataPayloadStub(Packet): name = "Zigbee Application Layer Data Payload for Inter-PAN Transmission" fields_desc = [ FlagsField("frame_control", 0, 4, ['reserved1', 'security', 'ack_req', 'extended_hdr']), # noqa: E501 BitEnumField("delivery_mode", 0, 2, {0: 'unicast', 2: 'broadcast', 3: 'group'}), # noqa: E501 BitField("frametype", 3, 2), # value 0b11 (3) is a reserved frame type # Group Address present only when delivery mode field has a value of 0b11 (group delivery mode) # noqa: E501 ConditionalField( XLEShortField("group_addr", 0x0), # 16-bit identifier of the group lambda pkt: pkt.getfieldval("delivery_mode") == 0b11 ), # Cluster identifier EnumField("cluster", 0, _zcl_cluster_identifier, fmt="<H"), # unsigned short (little-endian) # noqa: E501 # Profile identifier EnumField("profile", 0, _zcl_profile_identifier, fmt="<H"), # ZigBee Payload ConditionalField( StrField("data", ""), lambda pkt: pkt.frametype == 3 ), ]
class SAPHDBPartError(PacketNoPadded): """SAP HANA SQL Command Network Protocol Error Part """ part_kind = 6 name = "SAP HANA SQL Command Network Protocol Error Part" fields_desc = [ LESignedIntField("error_code", 0), LESignedIntField("error_position", 0), FieldLenField("error_text_length", None, length_of="error_text", fmt="<i"), EnumField("error_level", 0, hdb_error_level_vals, fmt="<b"), StrFixedLenField("sql_state", "HY000", 5), PadField(StrFixedLenField("error_text", "", length_from=lambda pkt: pkt.error_text_length), 8), ]
class VendorIdPacket(Packet): name = "RTPS Vendor ID" fields_desc = [ # ByteField("major", 0), # ByteField("minor", 0), EnumField(name="vendor_id", default=b"\x00\x00", enum=_rtps_vendor_ids, fmt="2s"), ] def extract_padding(self, p): return b"", p
class USBMessageDevice(USBMessage): 'UDP packet payload from ubq_core bearing USB traffic from device->host.' name = 'USBMessageDevice' fields_desc = [ LEIntField('len', None), EnumField('type', USBMitm.MitmType.USB, USBMitm.MitmType.desc, '<I'), TypePacketField( 'content', ManagementMessage(), 'type', {0: USBMessageResponse, 1: USBAck, 2: ManagementMessage}, ), ] def desc(self): return self.content.desc()
class SAPHDBPart(PacketNoPadded): """SAP HANA SQL Command Network Protocol Part This packet represents a part within a HDB packet. The part header is comprised of 16 bytes. """ name = "SAP HANA SQL Command Network Protocol Part" fields_desc = [ EnumField("partkind", 0, hdb_partkind_values, fmt="<b"), LESignedByteField("partattributes", 0), FieldLenField("argumentcount", None, count_of="buffer", fmt="<h"), LESignedIntField("bigargumentcount", 0), FieldLenField("bufferlength", None, length_of="buffer", fmt="<i"), LESignedIntField("buffersize", 2**17 - 32 - 24), PadField(PacketListField("buffer", [], next_cls_cb=saphdb_determine_part_class, count_from=lambda x: x.argumentcount, length_from=lambda x: x.bufferlength), 8), ]
class USBMessageHost(USBMessage): 'UDP packet payload from ubq_core bearing USB traffic from host->device.' name = 'USBMessageHost' fields_desc = [ LEIntField('len', None), EnumField( 'type', USBMitm.ManagementType.RESET, USBMitm.ManagementType.desc, '<I' ), TypePacketField( 'content', ManagementMessage(), 'type', {0: USBMessageRequest, 1: USBAck, 2: ManagementMessage}, ), ] def desc(self): return self.content.desc()
class SAPHDB(Packet): """SAP HANA SQL Command Network Protocol packet This packet is used for the HANA SQL Command Network Protocol. The message header is comprised of 32 bytes. """ name = "SAP HANA SQL Command Network Protocol" fields_desc = [ LESignedLongField("sessionid", -1), LESignedIntField("packetcount", 0), FieldLenField("varpartlength", None, length_of="segments", fmt="<I"), LEIntField("varpartsize", 2**17 - 32), FieldLenField("noofsegm", None, count_of="segments", fmt="<h"), EnumField("packetoptions", 0, hdb_packetoptions_values, fmt="b"), ByteField("reserved1", None), LEIntField("compressionvarpartlength", 0), IntField("reserved2", None), PacketListField("segments", None, SAPHDBSegment, count_from=lambda x: x.noofsegm), ]
class ManagementMessage(USBMitm): 'USBQ management message' fields_desc = [ EnumField( 'management_type', USBMitm.ManagementType.RESET, USBMitm.ManagementType.desc, '<I', ), TypePacketField( 'management_content', ManagementReset(), 'management_type', { USBMitm.ManagementType.RESET: ManagementReset, USBMitm.ManagementType.NEW_DEVICE: ManagementNewDevice, USBMitm.ManagementType.RELOAD: ManagementReload, }, ), ] # FIXME: ManagementReset is empty, so if there is nothing to dissect, management_content will be the default value def post_build(self, p, pay): if self.management_type is None: if isinstance(self.management_content, ManagementNewDevice): p = struct.pack('<H', USBMitm.ManagementType.NEW_DEVICE) + p[2:] elif isinstance(self.management_content, ManagementReload): p = struct.pack('<H', USBMitm.ManagementType.RELOAD) + p[2:] else: p = struct.pack('<H', USBMitm.ManagementType.RESET) + p[2:] return p + pay def desc(self): if self.management_type == USBMitm.ManagementType.RESET: return 'Reset' elif self.management_type == USBMitm.ManagementType.RELOAD: return 'Reload' else: return self.management_content.desc()