class VXLAN(Packet): name = "VXLAN" fields_desc = [ FlagsField("flags", 0x8, 8, _VXLAN_FLAGS), ConditionalField( ThreeBytesField("reserved1", 0x000000), lambda pkt: not pkt.flags & 0x80, ), ConditionalField( FlagsField("gpflags", 0x0, 8, _GP_FLAGS), lambda pkt: pkt.flags & 0x80, ), ConditionalField( ShortField("gpid", 0), lambda pkt: pkt.flags & 0x80, ), ThreeBytesField("vni", 0), XByteField("reserved2", 0x00), ] # Use default linux implementation port overload_fields = { UDP: {'dport': 8472}, } def mysummary(self): if self.flags & 0x80: return self.sprintf("VXLAN (vni=%VXLAN.vni% gpid=%VXLAN.gpid%)") else: return self.sprintf("VXLAN (vni=%VXLAN.vni%)")
class VrouterAgentHdr(Packet): name = "VrAgentHdr" fields_desc = [ ShortField("ifindex", None), ShortField("vrf", None), ShortEnumField("cmd", 1, vrouter_agent_cmd_no), IntField("param", None), IntField("param_1", None), IntField("param_2", None), IntField("param_3", None), IntField("param_4", None), ByteField("param_5", None), ThreeBytesField("param_5_pack", None) ] def mysummary(self): summary = self.sprintf("%cmd% vif0/%ifindex% Vrf:%vrf%") if self.cmd == 6 or self.cmd == 15: summary += self.sprintf(" Flow:%param% Gen:%param_5%" " K(nh)=%param_1%") return summary def guess_payload_class(self, payload): return InnerEther
class IEC104_IE_LOF: """ LOF - length of file or section EN 60870-5-101:2003, sec. 7.2.6.35 (p. 55) """ informantion_element_fields = [ThreeBytesField('file_length', 0)]
class GTPHeader(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) # without the version name = "GTP v2 Header" fields_desc = [ BitField("version", 2, 3), BitField("P", 1, 1), BitField("T", 1, 1), BitField("SPARE", 0, 1), BitField("SPARE", 0, 1), BitField("SPARE", 0, 1), ByteEnumField("gtp_type", None, GTPmessageType), ShortField("length", None), ConditionalField(XIntField("teid", 0), lambda pkt: pkt.T == 1), ThreeBytesField("seq", RandShort()), ByteField("SPARE", 0) ] def post_build(self, p, pay): p += pay if self.length is None: tmp_len = len(p) - 8 p = p[:2] + struct.pack("!H", tmp_len) + p[4:] return p def hashret(self): return struct.pack("B", self.version) + self.payload.hashret() def answers(self, other): return (isinstance(other, GTPHeader) and self.version == other.version and self.payload.answers(other.payload))
class SLPExtension(Packet): name = "SLPExtension" __slots__ = ["my_offset", "pkt_len"] fields_desc = [ XShortField("ext_id", 0), ThreeBytesField("next_ext_off", 0), BoundStrLenField( "data", b"", length_from=lambda pkt, *args: pkt._length_from(pkt, *args)) ] @classmethod def _length_from(cls, x): ext_end = x.next_ext_off if x.next_ext_off else x.pkt_len r = max(0, ext_end - x.my_offset - 5) #log.debug(f"Ext: my_len {r} next_off {x.next_ext_off} my_off {x.my_offset} total {x.pkt_len}") if ext_end > x.pkt_len: raise Scapy_Exception( "%s: malformed packet, extension exceeds packet length" % cls.__name__) return r # https://github.com/secdev/scapy/blob/cfe00d5c952e9048a40150390e0025b5ceff7228/scapy/layers/bluetooth.py#L485 def __init__(self, _pkt=None, offset=0, pkt_len=0, **kwargs): self.my_offset = offset self.pkt_len = pkt_len Packet.__init__(self, _pkt, **kwargs) def extract_padding(self, p): return "", p
class MulticastOperationsProfile(EntityClass): class_id = 309 attributes = [ ECA(ShortField("managed_entity_id", None), {AA.R, AA.SBC}), ECA(ByteField("igmp_version", None), {AA.R, AA.W, AA.SBC}), ECA(ByteField("igmp_function", None), {AA.R, AA.W, AA.SBC}), ECA(ByteField("immediate_leave", None), {AA.R, AA.W, AA.SBC}), ECA(ShortField("us_igmp_tci", None), {AA.R, AA.W, AA.SBC}, optional=True), ECA(ByteField("us_igmp_tag_ctrl", None), {AA.R, AA.W, AA.SBC}, optional=True), ECA(IntField("us_igmp_rate", None), {AA.R, AA.W, AA.SBC}, optional=True), # TODO: need to make table and add column data ECA(StrFixedLenField( "dynamic_access_control_list_table", None, 24), {AA.R, AA.W}), # TODO: need to make table and add column data ECA(StrFixedLenField( "static_access_control_list_table", None, 24), {AA.R, AA.W}), # TODO: need to make table and add column data ECA(StrFixedLenField("lost_groups_list_table", None, 10), {AA.R}, optional=True), ECA(ByteField("robustness", None), {AA.R, AA.W, AA.SBC}, optional=True), ECA(IPField("querier_ip", None), {AA.R, AA.W, AA.SBC}, optional=True), ECA(IntField("query_interval", None), {AA.R, AA.W, AA.SBC}, optional=True), ECA(IntField("querier_max_response_time", None), {AA.R, AA.W, AA.SBC}, optional=True), ECA(IntField("last_member_response_time", None), {AA.R, AA.W}, optional=True), ECA(ByteField("unauthorized_join_behaviour", None), {AA.R, AA.W}, optional=True), ECA(ThreeBytesField("ds_igmp_mcast_tci", None), {AA.R, AA.W, AA.SBC}, optional=True), ] mandatory_operations = {OP.Create, OP.Delete, OP.Set, OP.Get, OP.GetNext}
class SignalHeader(CAN): """Special implementation of a CAN Packet to allow dynamic binding. This class can be provided to CANSockets as basecls. Example: >>> class floatSignals(SignalPacket): >>> fields_desc = [ >>> LEFloatSignalField("floatSignal2", default=0, start=32), >>> BEFloatSignalField("floatSignal1", default=0, start=7)] >>> >>> bind_layers(SignalHeader, floatSignals, identifier=0x321) >>> >>> dbc_sock = CANSocket("can0", basecls=SignalHeader) All CAN messages received from this dbc_sock CANSocket will be interpreted as SignalHeader. Through Scapys ``bind_layers`` mechanism, all CAN messages with CAN identifier 0x321 will interpret the payload bytes of these CAN messages as floatSignals packet. """ fields_desc = [ FlagsField('flags', 0, 3, ['error', 'remote_transmission_request', 'extended']), XBitField('identifier', 0, 29), LenField('length', None, fmt='B'), ThreeBytesField('reserved', 0) ] def extract_padding(self, s): # type: (bytes) -> Tuple[bytes, Optional[bytes]] return s, None
class EIGRPv6ExtRoute(EIGRPGeneric): name = "EIGRP for IPv6 External Route" fields_desc = [ XShortField("type", 0x0403), FieldLenField("len", None, "dst", "!H", adjust=lambda pkt, x: x + 57), # noqa: E501 IP6Field("nexthop", "::"), IPField("originrouter", "192.168.0.1"), IntField("originasn", 0), IntField("tag", 0), IntField("externalmetric", 0), ShortField("reserved", 0), ByteEnumField("extprotocolid", 3, _EIGRP_EXTERNAL_PROTOCOL_ID), # noqa: E501 FlagsField("flags", 0, 8, _EIGRP_EXTROUTE_FLAGS), IntField("delay", 0), IntField("bandwidth", 256000), ThreeBytesField("mtu", 1500), ByteField("hopcount", 1), ByteField("reliability", 0), ByteField("load", 1), XShortField("reserved2", 0), ByteField("prefixlen", 8), EigrpIP6Field("dst", "::", length_from=lambda pkt: pkt.prefixlen) # noqa: E501 ]
class CAN(Packet): """A minimal implementation of the CANopen protocol, based on Wireshark dissectors. See https://wiki.wireshark.org/CANopen """ fields_desc = [ FlagsField('flags', 0, 3, ['error', 'remote_transmission_request', 'extended']), XBitField('identifier', 0, 29), FieldLenField('length', None, length_of='data', fmt='B'), ThreeBytesField('reserved', 0), StrLenField('data', b'', length_from=lambda pkt: int(pkt.length)), ] @staticmethod def inv_endianness(pkt): # type: (bytes) -> bytes """ Invert the order of the first four bytes of a CAN packet This method is meant to be used specifically to convert a CAN packet between the pcap format and the socketCAN format :param pkt: str of the CAN packet :return: packet str with the first four bytes swapped """ len_partial = len(pkt) - 4 # len of the packet, CAN ID excluded return struct.pack('<I{}s'.format(len_partial), *struct.unpack('>I{}s'.format(len_partial), pkt)) def pre_dissect(self, s): # type: (bytes) -> bytes """ Implements the swap-bytes functionality when dissecting """ if conf.contribs['CAN']['swap-bytes']: data = CAN.inv_endianness(s) # type: bytes return data return s def post_dissect(self, s): # type: (bytes) -> bytes self.raw_packet_cache = None # Reset packet to allow post_build return s def post_build(self, pkt, pay): # type: (bytes, bytes) -> bytes """ Implements the swap-bytes functionality when building this is based on a copy of the Packet.self_build default method. The goal is to affect only the CAN layer data and keep under layers (e.g LinuxCooked) unchanged """ if conf.contribs['CAN']['swap-bytes']: data = CAN.inv_endianness(pkt) # type: bytes return data + pay return pkt + pay def extract_padding(self, p): # type: (bytes) -> Tuple[bytes, Optional[bytes]] return b'', p
class ISIS_SRGBDescriptorEntry(Packet): name = "ISIS SRGB Descriptor" fields_desc = [ ThreeBytesField("range", 0), PacketField("sid_label", None, ISIS_SIDLabelSubTLV) ] def extract_padding(self, s): return "", s
class ISIS_ExtendedIsNeighbourEntry(Packet): name = "ISIS Extended IS Neighbour Entry" fields_desc = [ISIS_NodeIdField("neighbourid", "0102.0304.0506.07"), ThreeBytesField("metric", 1), FieldLenField("subtlvslen", None, length_of="subtlvs", fmt= "B"), ConditionalField(PacketListField("subtlvs", [], _isis_guess_subtlv_cls, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvslen > 0)] def extract_padding(self, s): return "", s
class NTLMSSP(Packet): # [MS-NLMP] v16.2 sect 2.2.1 name = 'NTLM Authentication Protocol' deprecated_fields_desc = { 'identifier': ('signature', '2.5.0'), } fields_desc = [ StrFixedLenField('signature', b'NTLMSSP\0', length=8), IntEnumField('messageType', 3, {1: 'NEGOTIATE_MESSAGE', 2: 'CHALLENGE_MESSAGE', 3: 'AUTHENTICATE_MESSAGE'}), # TODO: ONLY AUTHENTICATE_MESSAGE IMPLEMENTED # sect 2.2.1.3 ShortField('lmChallengeResponseLen', 0), ShortField('lmChallengeResponseMaxLen', 0), IntField('lmChallengeResponseBufferOffset', 0), ShortField('ntChallengeResponseLen', 0), ShortField('ntChallengeResponseMaxLen', 0), IntField('ntChallengeResponseBufferOffset', 0), ShortField('domainNameLen', 0), ShortField('domainNameMax', 0), IntField('domainNameOffset', 0), ShortField('userNameLen', 0), ShortField('userNameMax', 0), IntField('userNameOffset', 0), ShortField('workstationLen', 0), ShortField('workstationMaxLen', 0), IntField('workstationBufferOffset', 0), ShortField('encryptedRandomSessionKeyLen', 0), ShortField('encryptedRandomSessionKeyMaxLen', 0), IntField('encryptedRandomSessionKeyBufferOffset', 0), FlagsField('negociateFlags', 0, 32, _negociate_flags), ByteField('productMajorVersion', 0), ByteField('productMinorVersion', 0), ShortField('productBuild', 0), ThreeBytesField('reserved', 0), ByteField('NTLMRevisionCurrent', 0), StrFixedLenField('MIC', '', 16), # payload field. # TODO: those challenges are structures that should be defined StrLenField('lmChallengeResponse', '', length_from=lambda pkt: pkt.lmChallengeResponseLen), StrLenField('ntChallengeResponse', '', length_from=lambda pkt: pkt.ntChallengeResponseLen), StrLenField('domainName', '', length_from=lambda pkt: pkt.domainNameLen), StrLenField('userName', '', length_from=lambda pkt: pkt.userNameLen), StrLenField('workstation', '', length_from=lambda pkt: pkt.workstationLen), StrLenField('encryptedRandomSessionKey', '', length_from=lambda pkt: pkt.encryptedRandomSessionKeyLen) ] def extract_padding(self, p): return b"", p
class BuildChecksum(Packet): # Build checksum over memory range fields_desc = [ # specification says: position 1-3 type byte The example(Part 5 # Example Communication Sequences ) shows 3 bytes for "reserved" # http://read.pudn.com/downloads192/doc/comm/903802/XCP%20-Part%205-%20Example%20Communication%20Sequences%20-1.0.pdf # noqa: E501 # --> 3 bytes XCPEndiannessField(ThreeBytesField("reserved", 0)), XCPEndiannessField(XIntField("block_size", 0)) ]
class OmciAlarmNotification(OmciMessage): name = "AlarmNotification" message_id = 0x10 fields_desc = [ ShortField("entity_class", None), ShortField("entity_id", 0), BitField("alarm_bit_map", 0, 224), ThreeBytesField("zero_padding", 0), ByteField("alarm_sequence_number", None) ]
class ISIS_SIDLabelSubTLV(ISIS_GenericSubTlv): name = "ISIS SID Label sub TLV" fields_desc = [ ByteEnumField("type", 1, _isis_subtlv_names_3), ByteField("len", 3), ConditionalField(ThreeBytesField("sid", 0), lambda pkt: pkt.len == 3), ConditionalField(IntField("idx", 0), lambda pkt: pkt.len == 4) ]
class VXLAN(Packet): name = "VXLAN" fields_desc = [ FlagsField("flags", 0x08000000, 32, _VXLAN_FLAGS), ThreeBytesField("vni", 0), XByteField("reserved", 0x00) ] def mysummary(self): return self.sprintf("VXLAN (vni=%VXLAN.vni%)")
class CAN(Packet): """A minimal implementation of the CANopen protocol, based on Wireshark dissectors. See https://wiki.wireshark.org/CANopen """ fields_desc = [ FlagsField('flags', 0, 3, ['error', 'remote_transmission_request', 'extended']), XBitField('identifier', 0, 29), FieldLenField('length', None, length_of='data', fmt='B'), ThreeBytesField('reserved', 0), StrLenField('data', '', length_from=lambda pkt: pkt.length), StrLenField('padding', '', length_from=lambda pkt: 8 - pkt.length), ] def pre_dissect(self, s): """ Implements the swap-bytes functionality when dissecting """ if conf.contribs['CAN']['swap-bytes']: return struct.pack('<I12s', *struct.unpack('>I12s', s)) return s def self_build(self, field_pos_list=None): """ Implements the swap-bytes functionality when building this is based on a copy of the Packet.self_build default method. The goal is to affect only the CAN layer data and keep under layers (e.g LinuxCooked) unchanged """ if self.raw_packet_cache is not None: for fname, fval in six.iteritems(self.raw_packet_cache_fields): if self.getfieldval(fname) != fval: self.raw_packet_cache = None self.raw_packet_cache_fields = None break if self.raw_packet_cache is not None: if conf.contribs['CAN']['swap-bytes']: return struct.pack( '<I12s', *struct.unpack('>I12s', self.raw_packet_cache)) return self.raw_packet_cache p = b"" for f in self.fields_desc: val = self.getfieldval(f.name) if isinstance(val, RawVal): sval = raw(val) p += sval if field_pos_list is not None: field_pos_list.append( (f.name, sval.encode('string_escape'), len(p), len(sval))) else: p = f.addfield(self, p, val) if conf.contribs['CAN']['swap-bytes']: return struct.pack('<I12s', *struct.unpack('>I12s', p)) return p
class S7COMM_Data(Packet): name = "S7COMM_Data" fields_desc = [ ThreeBytesField("param_head", 0x000112), ByteField("param_length", 4), ByteField("request_response", 0x11), BitField('type', 4, 4), BitField('func_group', 0, 4), ByteField("subfunc", 1), ByteField("seq_num", 0) ]
class ISIS_ExtendedIsNeighbourEntry(Packet): name = "ISIS Extended IS Neighbour Entry" fields_desc = [ ISIS_NodeIdField("neighbourid", "0102.0304.0506.07"), ThreeBytesField("metric", 1), FieldLenField("subtlvslen", None, length_of="subtlvs", fmt="B"), PacketListField("subtlvs", [], _ISIS_GuessSubTlvClass_1, length_from=lambda x: x.subtlvslen) # noqa: E501 ] def extract_padding(self, s): return "", s
class ISIS_TEDefaultMetricSubTlv(ISIS_GenericSubTlv): name = "TE Default Metric SubTLV" fields_desc = [ ByteEnumField("type", 18, _isis_subtlv_names_1), FieldLenField("len", None, length_of="temetric", adjust=lambda pkt, x: x - 1, fmt="B"), # noqa: E501 ThreeBytesField("temetric", 1000) ]
class SignalHeader(CAN): fields_desc = [ FlagsField('flags', 0, 3, ['error', 'remote_transmission_request', 'extended']), XBitField('identifier', 0, 29), LenField('length', None, fmt='B'), ThreeBytesField('reserved', 0) ] def extract_padding(self, s): return s, None
class ISIS_PrefixSegmentIdentifierSubTlv(ISIS_GenericSubTlv): name = "ISIS Prefix SID sub TLV" fields_desc = [ByteEnumField("type", 3, _isis_subtlv_names_2), ByteField("len", 5), FlagsField( "flags", 0, 8, ["res1", "res2", "L", "V", "E", "P", "N", "R"]), ByteField("algorithm", 0), ConditionalField(ThreeBytesField("sid", 0), lambda pkt: pkt.len == 5), ConditionalField(IntField("idx", 0), lambda pkt: pkt.len == 6)]
class CCP(CAN): name = 'CAN Calibration Protocol' fields_desc = [ FlagsField('flags', 0, 3, ['error', 'remote_transmission_request', 'extended']), XBitField('identifier', 0, 29), ByteField('length', 8), ThreeBytesField('reserved', 0), ] def extract_padding(self, p): return p, None
class TLSHandshake(Packet): name = 'TLSHandshake' fields_desc = [ ByteEnumField('handshake_type', None, { 1: 'Client Hello', 2: 'Server Hello', 11: 'Certificate', 12: 'Server Key Exchange', 14: 'Server Hello Done', 16: 'Client Key Exchange', }), ThreeBytesField("length", None) ]
class SPBM(Packet): name = "SPBM" fields_desc = [ BitField("prio", 0, 3), BitField("dei", 0, 1), BitField("nca", 0, 1), BitField("res1", 0, 1), BitField("res2", 0, 2), ThreeBytesField("isid", 0) ] def mysummary(self): return self.sprintf("SPBM (isid=%SPBM.isid%")
class CAN(Packet): """A minimal implementation of the CANopen protocol, based on Wireshark dissectors. See https://wiki.wireshark.org/CANopen """ fields_desc = [ FlagsField("flags", 0, 3, ["extended", "remote_transmission_request", "error"]), BitField("unknown", 0, 18), XBitField("identifier", 0, 11), FieldLenField("length", None, length_of="data", fmt="B"), ThreeBytesField("reserved", 0), StrLenField("data", "", length_from=lambda pkt: pkt.length), ]
class VXLAN(Packet): name = "VXLAN" fields_desc = [ FlagsField( "flags", 0x8, 8, ['OAM', 'R', 'NextProtocol', 'Instance', 'V1', 'V2', 'R', 'G']), ConditionalField( ShortField("reserved0", 0), lambda pkt: pkt.flags.NextProtocol, ), ConditionalField( ByteEnumField('NextProtocol', 0, { 0: 'NotDefined', 1: 'IPv4', 2: 'IPv6', 3: 'Ethernet', 4: 'NSH' }), lambda pkt: pkt.flags.NextProtocol, ), ConditionalField( ThreeBytesField("reserved1", 0), lambda pkt: (not pkt.flags.G) and (not pkt.flags.NextProtocol), ), ConditionalField( FlagsField("gpflags", 0, 8, _GP_FLAGS), lambda pkt: pkt.flags.G, ), ConditionalField( ShortField("gpid", 0), lambda pkt: pkt.flags.G, ), X3BytesField("vni", 0), XByteField("reserved2", 0), ] # Use default linux implementation port overload_fields = { UDP: { 'dport': 8472 }, } def mysummary(self): if self.flags.G: return self.sprintf("VXLAN (vni=%VXLAN.vni% gpid=%VXLAN.gpid%)") else: return self.sprintf("VXLAN (vni=%VXLAN.vni%)")
class Wireguard(Packet): """ Wrapper that only contains the message type. """ name = "Wireguard" fields_desc = [ ByteEnumField("message_type", 1, { 1: "initiate", 2: "respond", 3: "cookie reply", 4: "transport" }), ThreeBytesField("reserved_zero", 0) ]
class EIGRPIntRoute(EIGRPGeneric): name = "EIGRP Internal Route" fields_desc = [XShortField("type", 0x0102), FieldLenField("len", None, "dst", "!H", adjust=lambda pkt, x: x + 25), # noqa: E501 IPField("nexthop", "192.168.0.0"), IntField("delay", 128000), IntField("bandwidth", 256), ThreeBytesField("mtu", 1500), ByteField("hopcount", 0), ByteField("reliability", 255), ByteField("load", 0), XShortField("reserved", 0), ByteField("prefixlen", 24), EigrpIPField("dst", "192.168.1.0", length_from=lambda pkt: pkt.prefixlen), # noqa: E501 ]
class EIGRPv6IntRoute(EIGRPGeneric): name = "EIGRP for IPv6 Internal Route" fields_desc = [XShortField("type", 0x0402), FieldLenField("len", None, "dst", "!H", adjust=lambda pkt, x: x + 37), # noqa: E501 IP6Field("nexthop", "::"), IntField("delay", 128000), IntField("bandwidth", 256000), ThreeBytesField("mtu", 1500), ByteField("hopcount", 1), ByteField("reliability", 255), ByteField("load", 0), XShortField("reserved", 0), ByteField("prefixlen", 16), EigrpIP6Field("dst", "2001::", length_from=lambda pkt: pkt.prefixlen) # noqa: E501 ]