class CIP_ReqForwardOpen(scapy_all.Packet): """Forward Open request""" name = "CIP_ReqForwardOpen" fields_desc = [ scapy_all.XByteField("priority_ticktime", 0), scapy_all.ByteField("timeout_ticks", 249), scapy_all.LEIntField("OT_network_connection_id", 0x80000031), scapy_all.LEIntField("TO_network_connection_id", 0x80fe0030), scapy_all.LEShortField("connection_serial_number", 0x1337), scapy_all.LEShortField("vendor_id", 0x004d), scapy_all.LEIntField("originator_serial_number", 0xdeadbeef), scapy_all.ByteField("connection_timeout_multiplier", 0), scapy_all.XByteField("reserved1", 0), scapy_all.XByteField("reserved2", 0), scapy_all.XByteField("reserved3", 0), scapy_all.LEIntField("OT_rpi", 0x007a1200), # 8000 ms scapy_all.LEShortField("OT_connection_param", 0x43f4), # exclusive, PtP, low prio, size 500 scapy_all.LEIntField("TO_rpi", 0x007a1200), scapy_all.LEShortField("TO_connection_param", 0x43f4), scapy_all.XByteField( "transport_type", 0xa3), # direction server, application object, class 3 scapy_all.ByteField("path_wordsize", None), CIP_PathField("path", None, length_from=lambda p: 2 * p.path_wordsize), ]
class CIP_ReqForwardOpen(scapy_all.Packet): """Forward Open request""" name = "CIP_ReqForwardOpen" fields_desc = [ scapy_all.BitField("priority", 0, 4), scapy_all.BitField("tick_time", 0, 4), scapy_all.ByteField("timeout_ticks", 249), scapy_all.LEIntField("OT_network_connection_id", 0x80000031), scapy_all.LEIntField("TO_network_connection_id", 0x80fe0030), scapy_all.LEShortField("connection_serial_number", 0x1337), scapy_all.LEShortField("vendor_id", 0x004d), scapy_all.LEIntField("originator_serial_number", 0xdeadbeef), scapy_all.ByteField("connection_timeout_multiplier", 0), scapy_all.X3BytesField("reserved", 0), scapy_all.LEIntField("OT_rpi", 0x007a1200), # 8000 ms For ToCNC and ToCell #scapy_all.LEIntField("OT_rpi", 0x00000000), # for j scapy_all.LEShortField("OT_connection_param", 0x4802), #for ToCNC and ToCell #scapy_all.LEShortField("OT_connection_param", 0x0400), #for j #scapy_all.PacketField('OT_connection_param', CIP_ConnectionParam(), CIP_ConnectionParam), scapy_all.LEIntField("TO_rpi", 0x007a1200), #ToCNC and ToCell #scapy_all.LEIntField("TO_rpi", 0x00000000), #for j scapy_all.LEShortField("TO_connection_param", 0x281a), #for ToCNC and ToCell #scapy_all.LEShortField("TO_connection_param", 0x0400), #for j #scapy_all.PacketField('TO_connection_param', CIP_ConnectionParam(), CIP_ConnectionParam), scapy_all.XByteField("transport_type", 0x81), # direction server, application object, class 3 scapy_all.ByteField("path_wordsize", None), CIP_PathField("path", None, length_from=lambda p: 2 * p.path_wordsize), ]
class RdmaDCQCNstate(scapy.Packet): name = "RdmaDCQCNstate" fields_desc = [ scapy.BitField("last_cnp_timestamp", 0, 48), scapy.IntField("byte_counter_thr", 0), scapy.ByteField("rsvd1", 0), scapy.BitField("sq_msg_psn", 0, 24), scapy.IntField("rate_enforced", 0), scapy.IntField("target_rate", 0), scapy.BitField("alpha_value", 0, 16), scapy.IntField("cur_byte_counter", 0), scapy.BitField("byte_counter_exp_cnt", 0, 16), scapy.BitField("timer_exp_cnt", 0, 16), scapy.BitField("num_alpha_exp_cnt", 0, 16), scapy.ByteField("num_cnp_rcvd", 0), scapy.ByteField("num_cnp_processed", 0), scapy.BitField("max_rate_reached", 0, 1), scapy.BitField("log_sq_size", 0, 5), scapy.BitField("resp_rl_failure", 0, 1), scapy.BitField("rsvd0", 0, 1), scapy.BitField("last_sched_timestamp", 0, 48), scapy.BitField("delta_tokens_last_sched", 0, 16), scapy.BitField("cur_avail_tokens", 0, 48), scapy.BitField("token_bucket_size", 0, 48), scapy.BitField("sq_cindex", 0, 16), scapy.ByteField("num_sched_drop", 0), scapy.BitField("cur_timestamp", 0, 32), ]
class Command(scapy.Packet): name = "Command" fields_desc = [ scapy.ByteField("Command", 0x00), scapy.ByteField("Value", 0x00), scapy.ByteField("Value2", 0x00) ]
class CIP_ReqConnectionManager(scapy_all.Packet): fields_desc = [ scapy_all.BitField("reserved", 0, 3), scapy_all.BitField("priority", 0, 1), scapy_all.BitField("ticktime", 5, 4), scapy_all.ByteField("timeout_ticks", 157), utils.LEShortLenField("message_size", None, length_of="message"), scapy_all.PacketLenField("message", None, CIP, length_from=lambda pkt: pkt.message_size), scapy_all.StrLenField("message_padding", None, length_from=lambda pkt: pkt.message_size % 2), scapy_all.ByteField("route_path_size", 1), # TODO: size in words scapy_all.ByteField("reserved2", 0), scapy_all.ByteField("route_path_size_port", 1), scapy_all.ByteField("route_path_size_addr", 0), ] def post_build(self, p, pay): # Autofill the padding if len(p) % 2: p = p[:-4] + b"\0" + p[-4:] return p + pay
class SWAT_P1_RIO_DO(scapy_all.Packet): name = "SWAT_P1_RIO_DO" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.ByteField('number', 0), scapy_all.StrFixedLenField('reserved', 0, length=5), scapy_all.BitField('spare', 0, 4), scapy_all.BitEnumField('valve_close', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('valve_open', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('pump2_start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('pump1_start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.FieldListField( "spare2", [], scapy_all.ByteField('', 0), length_from=lambda p: p.underlayer.length - 9), ]
class Pixels(scapy.Packet): name = "Pixels" fields_desc = [ scapy.ByteField("TypeOfUpdate", 0x00), scapy.ByteField("Layer", 0x01), scapy.FieldLenField("NumberOfPixelUpdates", None, count_of="PixelData", fmt='H'), scapy.PacketListField("PixelData", None, Pixel, count_from=lambda pkt: pkt.NumberOfPixelUpdates) ]
class Pixel(scapy.Packet): name = "Pixel" fields_desc = [ scapy.ByteField("Index", 0x00), scapy.ByteField("Red", 0x00), scapy.ByteField("Green", 0x00), scapy.ByteField("Blue", 0x00) ]
class ENIP_DeviceRevision(scapy_all.Packet): name = "ENIP_DeviceRevision" fields_desc = [ scapy_all.ByteField("Major", 0), scapy_all.ByteField("Minor", 0), ] def extract_padding(self, p): # print self.__class__.__name__ + ": P=" + str(p) return "", p
class CIP_ReqForwardClose(scapy_all.Packet): """Forward Close request""" name = "CIP_ReqForwardClose" fields_desc = [ scapy_all.XByteField("priority_ticktime", 0), scapy_all.ByteField("timeout_ticks", 249), scapy_all.LEShortField("connection_serial_number", 0x1337), scapy_all.LEShortField("vendor_id", 0x004d), scapy_all.LEIntField("originator_serial_number", 0xdeadbeef), scapy_all.ByteField("path_wordsize", None), scapy_all.XByteField("reserved", 0), CIP_PathField("path", None, length_from=lambda p: 2 * p.path_wordsize), ]
class CIP_LogicalSegment(scapy_all.Packet): name="CIP_LogicalSegment" LOGICAL_TYPE = { 0: "Class ID", 1: "Instance ID", 2: "Member ID", 3: "Connection Point", 4: "Attribute ID", 5: "Special", 6: "Service ID", 7: "Reserved" # The Special and Service ID Logical Types do not use the logical addressing definition for the Logical Format. } LOGICAL_FORMAT = { 0: "8 - bit logical address", 1: "16-bit logical address", 2: "32-bit logical address", 3: "Reserved for future use" } fields_desc = [ scapy_all.BitEnumField("logical_type", 0, 3, LOGICAL_TYPE), scapy_all.BitEnumField("logical_format", 0, 2, LOGICAL_FORMAT), # When the logical segment is included within a Padded Path, the 16 - bit and 32 - bit # logical formats shall have a pad inserted between the segment type byte and the Logical Value # (the 8 - bit format is identical to the Packed Path).The pad byte shall be set to zero. scapy_all.ConditionalField(scapy_all.ByteField("padding", 0), lambda p: p.logical_format > 0x0), # scapy_all.ByteField("value", 0), scapy_all.ConditionalField( scapy_all.ByteField("value8bit", 0), lambda p: p.logical_format >= 0x0 ), scapy_all.ConditionalField( scapy_all.LEShortField("value16bit", 0), lambda p: p.logical_format >= 0x1 ), scapy_all.ConditionalField( scapy_all.LELongField("value32bit", 0), lambda p: p.logical_format >= 0x2 ), ] def extract_padding(self, p): # print self.__class__.__name__ + ": P=" + str(p) return "", p
class SWAT_P2_RIO_DO(scapy_all.Packet): name = "SWAT_P2_RIO_DO" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.ByteField('number', 0), scapy_all.StrFixedLenField('reserved', 0, length=5), scapy_all.BitEnumField('P208_Start', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('P207_Start', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('P206_Start', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('P205_Start', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('P204_Start', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('P203_Start', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('P202_Start', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('P201_Start', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('spare', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('spare', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('spare', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('spare', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('spare', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('LED_RED', 0, 1, {0: 'disable', 1: 'enable'}), #LED_RED scapy_all.BitEnumField('MV201_Close', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('MV201_Open', 0, 1, {0: 'disable', 1: 'enable'}), ]
class CIP_PortSegment(scapy_all.Packet): name="CIP_PortSegment" PORT_IDENT={ 0: "Reserved", 1: "Back-Plane", 15: "Extended", } fields_desc = [ scapy_all.BitField("extended_link_address_size", 0, 1), scapy_all.BitEnumField("port_identifier", 0, 4, PORT_IDENT), scapy_all.ByteField("link_address_size", 0), scapy_all.ConditionalField( scapy_all.LEIntField("extended_port_identifier", 0), lambda p: p.port_identifier == 0xf # If the Port Identifier is 15, then a 16-bit field, called the Extended Port Identifier, shall be the next part of the Port Segment ), scapy_all.ConditionalField( scapy_all.FieldListField("Link_Address", [], scapy_all.XByteField("",0), length_from=lambda p: p.link_address_size ), lambda p: p.extended_link_address_size == 0x1 # If the Port Identifier is 15, then a 16-bit field, called the Extended Port Identifier, shall be the next part of the Port Segment ) ] def extract_padding(self, p): print self.__class__.__name__ + ": P=" + str(p) return "", p
class Header(scapy.Packet): name = "Header" fields_desc = [ scapy.IntField("MagicWord", 0xDEC0DED), # 32 bit scapy.ByteField("MessageDataType", 0x00), # 8 bit scapy.LEShortField("MessageDataSize", 0x00) # 16 bit ]
class SecurityExtension(scapy.Packet): name = "SCION Security Extension" fields_desc = [ scapy.BitEnumField('next_hdr', None, 8, scapy.IP_PROTOS), scapy.ByteField('hdr_len', None), scapy.XByteField('extType', 0x2), scapy.ByteEnumField("secMode", 0x0, { 0x0: "AES-CMAC", 0x1: "HMAC_SHA256", 0x2: "Ed25519", 0x3: "GCM_AES128" }), scapy.XBitField('metadata', 0xffffffff, 4 * 8), scapy.MultipleTypeField([ (scapy.XBitField('authenticator', None, 16 * 8), lambda pkt: pkt.secMode == 0x0), (scapy.XBitField('authenticator', None, 32 * 8), lambda pkt: pkt.secMode == 0x1), (scapy.XBitField('authenticator', None, 64 * 8), lambda pkt: pkt.secMode == 0x2), (scapy.XBitField('authenticator', None, 16 * 8), lambda pkt: pkt.secMode == 0x3), ], scapy.StrField("authenticator", None)), ] def extract_padding(self, p): # TODO fix when removing hard-coded v4 return "", p def post_build(self, pkt, pay): if self.hdr_len == None: self.hdr_len = len(pkt) pkt = pkt[:1] + struct.pack('B', int(self.hdr_len / 8)) + pkt[2:] return pkt + pay
class ENIP_ListIdentity_TargetItem(scapy_all.Packet): name = "ENIP_ListIdentity_TargetItem" fields_desc = [ scapy_all.LEShortField("item_type_code", 0), scapy_all.LEShortField("length", 0), scapy_all.LEShortField("encapsulation_version", 1), scapy_all.PacketField("ListIdentityItems", ENIP_ListIdentity_SocketItem(), ENIP_ListIdentity_SocketItem), #, count_from=1), scapy_all.LEShortField("vendor_ID", 0), scapy_all.LEShortEnumField("device_type", 0x21, DEVICE_PROFILES), scapy_all.LEShortField("product_code", 0), scapy_all.PacketField("ENIP_DeviceRevision", ENIP_DeviceRevision(), ENIP_DeviceRevision), scapy_all.XShortField("status", 0x0000), utils.XLEIntField("serial", 0x00000000), scapy_all.ByteField("product_name_length", 0), scapy_all.StrLenField("product_name", "", length_from=lambda p: p.product_name_length), scapy_all.XByteField("state", 0), ] def extract_padding(self, p): # print self.__class__.__name__ + ": P=" + str(p) return "", p
class SWAT_MV(scapy_all.Packet): name = 'SWAT_MV' fields_desc = [ scapy_all.ByteEnumField('cmd', 0, {1: 'closed', 2: 'open'}), scapy_all.ByteField('spare2', 0), scapy_all.ByteEnumField('status', 0, {1: 'closed', 2: 'open'}), scapy_all.ByteField('spare3', 0), scapy_all.BitEnumField('spare4', 0, 1, {}), scapy_all.BitEnumField('spare5', 0, 1, {}), scapy_all.BitEnumField('spare6', 0, 1, {}), scapy_all.BitEnumField('Avl', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('FTC', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('FTO', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('Auto', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('Reset', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.X3BytesField('Spare7', 0) ]
class CIP_Path(scapy_all.Packet): name = "CIP_Path" fields_desc = [ scapy_all.ByteField("wordsize", None), CIP_PathField("path", None, length_from=lambda p: 2 * p.wordsize), ] def extract_padding(self, p): return "", p @classmethod def make(cls, class_id=None, instance_id=None, member_id=None, attribute_id=None): """Create a CIP_Path from its attributes""" content = b"" if class_id is not None: if class_id < 256: # 8-bit class ID content += b"\x20" + struct.pack("B", class_id) else: # 16-bit class ID content += b"\x21\0" + struct.pack("<H", class_id) if instance_id is not None: # Always use 16-bit instance ID content += b"\x25\0" + struct.pack("<H", instance_id) if member_id is not None: if member_id < 256: # 8-bit member ID content += b"\x28" + struct.pack("B", member_id) else: # 16-bit attribute ID content += b"\x29\0" + struct.pack("<H", member_id) if attribute_id is not None: if attribute_id < 256: # 8-bit attribute ID content += b"\x30" + struct.pack("B", attribute_id) else: # 16-bit attribute ID content += b"\x31\0" + struct.pack("<H", attribute_id) return cls(wordsize=len(content) // 2, path=content) @classmethod def make_str(cls, name): content = struct.pack('BB', 0x91, len(name)) + name.encode('ascii') if len(content) & 1: content += b'\0' return cls(wordsize=len(content) // 2, path=content) def to_tuplelist(self): """Return a list of tuples describing the content of the path encoded in val""" return CIP_PathField.to_tuplelist(self.path) def to_repr(self): """Return a representation of the path, not of the packet (!= repr(path))""" return self.get_field("path").i2repr(self, self.path)
class CIP_ReqForwardOpen(scapy_all.Packet): """Forward Open request""" name = "CIP_ReqForwardOpen" SEGMENT_TYPE = { 0x00: "Port Segment", 0x01: "Logical Segment", 0x02: "Network Segment", 0x03: "Symbolic Segment", 0x04: "Data Segment", 0x05: "Data Type (constructed)", 0x06: "Data Type (elementary)", 0x07: "Reserved for future use", } fields_desc = [ # Updated a few field descriptions to adjust how they are displayed # Altered fields begin with utils. rather than scapy_all. - MED scapy_all.BitField("priority", 0, 4), scapy_all.BitField("tick_time", 0, 4), scapy_all.ByteField("timeout_ticks", 249), utils.XLEIntField("OT_network_connection_id", 0x80000031), utils.XLEIntField("TO_network_connection_id", 0x80fe0030), scapy_all.LEShortField("connection_serial_number", 0x1337), utils.XLEShortField("vendor_id", 0x004d), utils.XLEIntField("originator_serial_number", 0xdeadbeef), scapy_all.ByteField("connection_timeout_multiplier", 0), scapy_all.X3BytesField("reserved", 0), utils.XLEIntField("OT_rpi", 0x007a1200), # 8000 ms scapy_all.PacketField('OT_connection_param', CIP_ConnectionParam(), CIP_ConnectionParam), utils.XLEIntField("TO_rpi", 0x007a1200), scapy_all.PacketField('TO_connection_param', CIP_ConnectionParam(), CIP_ConnectionParam), scapy_all.XByteField("transport_type", 0xa3), # direction server, application object, class 3 # Changed name - MED scapy_all.ByteField("Connection_Path_Size", None), #The number of 16 bit words in the Connection_Path field. # scapy_all.PacketListField("path_segment_items", [], CIP_Path1, length_from=lambda p: 2 * p.Connection_Path_Size), # Modified Implementation - MED scapy_all.PacketListField("path_segment_items", [], CIP_PathPadded, length_from=lambda p: 6), # CIP_PathField("path", None, length_from=lambda p: 2 * p.path_wordsize), ]
class CIP_RespForwardOpen(scapy_all.Packet): """Forward Open response""" name = "CIP_RespForwardOpen" fields_desc = [ scapy_all.LEIntField("OT_network_connection_id", None), scapy_all.LEIntField("TO_network_connection_id", None), scapy_all.LEShortField("connection_serial_number", None), scapy_all.LEShortField("vendor_id", None), scapy_all.LEIntField("originator_serial_number", None), scapy_all.LEIntField("OT_api", None), scapy_all.LEIntField("TO_api", None), scapy_all.ByteField("application_reply_size", None), scapy_all.XByteField("reserved", 0), ]
class SWAT_P(scapy_all.Packet): name = 'SWAT_P' fields_desc = [ scapy_all.ByteEnumField('cmd', 0, {1: 'closed', 2: 'open'}), scapy_all.ByteField('spare2', 0), scapy_all.ByteEnumField('status', 0, {1: 'closed', 2: 'open'}), scapy_all.ByteField('spare3', 0), scapy_all.LEIntField('RunMin', 0), scapy_all.LEIntField('Total_RunMin', 0), scapy_all.LEIntField('RunHr', 0), scapy_all.LEIntField('Total_RunHr', 0), scapy_all.LEIntField('Permissive', 0), scapy_all.LEIntField('Shutdown', 0), scapy_all.LEIntField('SD', 0), scapy_all.BitEnumField('Avl', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('Fault', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('Auto', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('Remote', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('FTS', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('FTR', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('Reset_RunHr', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('Reset', 0, 1, {0: 'disable', 1: 'enable'}), ]
class HopField(scapy.Packet): IMMUTABLE_FLAGS = 0x0 # TODO FLAGS = 0 RANGE_SKIP_FLAGS = 1 RANGE_END = 8 RANGE_BEFORE_MAC = 5 name = 'SCION Hop field' fields_desc = [ scapy.XBitField('flags', 0x0, 8), scapy.ByteField('expiry', 63), scapy.BitField('ingress_if', None, 12), scapy.BitField('egress_if', None, 12), scapy.XBitField('mac', None, 3 * 8), # TODO ] def extract_padding(self, p): return "", p
class SWAT_P4_RIO_DO(scapy_all.Packet): name = "SWAT_P4_RIO_DO" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.ByteField('number', 0), scapy_all.StrFixedLenField('reserved', 0, length=5), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('UV_Start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('P404_Start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('P403_Start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('P402_Start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('P401_Start', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), ]
class Mode(scapy.Packet): name = "Mode" fields_desc = [scapy.ByteField("Mode", 0x00)]
class Effect(scapy.Packet): name = "Effect" fields_desc = [ scapy.ByteField("Effect", 0x00), scapy.ByteField("Permanent", 0x00) ]
class SWAT_P5_RIO_DO(scapy_all.Packet): name = "SWAT_P5_RIO_DO" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.ByteField('number', 0), scapy_all.StrFixedLenField('reserved', 0, length=5), scapy_all.BitEnumField('MV504_Close', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('MV504_Open', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('MV503_Close', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('MV503_Open', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('MV502_Close', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('MV502_Open', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('MV501_Close', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('MV501_Open', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), scapy_all.BitEnumField('spare', 0, 1, { 0: 'disable', 1: 'enable' }), ]
class SWAT_P1_ALL(scapy_all.Packet): name = 'SWAT_P1_ALL' fields_desc = [ scapy_all.LEIntField('FIT101_Pv', 0), scapy_all.LEIntField('LIT101_Pv', 0), scapy_all.ByteField('spare3', 0), scapy_all.ByteField('spare4', 0), scapy_all.ByteEnumField('P101_cmd', 0, {1: 'off', 2: 'on'}), scapy_all.ByteField('spare5', 0), scapy_all.ByteEnumField('P102_cmd', 0, {1: 'off', 2: 'on'}), scapy_all.ByteField('spare6', 0), scapy_all.ByteField('spare7', 0), scapy_all.ByteField('spare8', 0), scapy_all.BitEnumField('FIT101_status', 0, 1, {0: 'unhealthy', 1: 'healthy'}), scapy_all.BitEnumField('FIT101_Rst_Totaliser', 0, 1, {0: 'unhealthy', 1: 'healthy'}), scapy_all.BitEnumField('FIT101_WiFi', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('FIT101_control', 0, 1, {0: 'actual', 1: 'simulation'}), scapy_all.BitEnumField('FIT101_ALL', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('FIT101_AL', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('FIT101_AH', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('FIT101_AHH', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.ByteField('spare9', 0), scapy_all.LEIntField('FIT101_H', 0), scapy_all.LEIntField('FIT101_HH', 0), scapy_all.LEIntField('FIT101_L', 0), scapy_all.LEIntField('FIT101_LL', 0), scapy_all.BitEnumField('LIT101_spare', 0, 1, {}), scapy_all.BitEnumField('LIT101_control', 0, 1, {0: 'actual', 1: 'simulation'}), scapy_all.BitEnumField('LIT101_status', 0, 1, {0: 'unhealthy', 1: 'healthy'}), scapy_all.BitEnumField('LIT101_WiFi', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('LIT101_ALL', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('LIT101_AL', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('LIT101_AH', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('LIT101_AHH', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.LEIntField('LIT101_SALL', 0), scapy_all.LEIntField('LIT101_SAL', 0), scapy_all.LEIntField('LIT101_SAH', 0), scapy_all.LEIntField('LIT101_SAHH', 0), scapy_all.BitEnumField('spare10', 0, 1, {}), scapy_all.BitEnumField('spare11', 0, 1, {}), scapy_all.BitEnumField('spare12', 0, 1, {}), scapy_all.BitEnumField('MV101_Avl', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('MV101_FTC', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('MV101_FTO', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('MV101_Auto', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.BitEnumField('MV101_Reset', 0, 1, {0: 'disable', 1: 'enable'}), scapy_all.ByteEnumField('MV101_status', 0, {1: 'off', 2: 'on'}), scapy_all.ByteField('spare13', 0), scapy_all.ByteField('spare14', 0), scapy_all.ByteEnumField('P101_status', 0, {1: 'off', 2: 'on'}), scapy_all.X3BytesField('Spare', 0), scapy_all.LEIntField('spare15', 0), scapy_all.LEIntField('spare16', 0), scapy_all.LEIntField('spare17', 0), scapy_all.LEIntField('spare18', 0), scapy_all.LEIntField('P101_RunHr', 0), scapy_all.LEIntField('P101_RunHr2', 0), scapy_all.ByteField('spare19', 0), scapy_all.ByteField('spare20', 0), scapy_all.LEIntField('P101_Permissive', 0), scapy_all.LEIntField('spare21', 0) # scapy_all.ByteField('spare4', 0), # scapy_all.LEIntField('spare', 0), # scapy_all.LEIntField('LIT101_Sim_Pv', 0), # scapy_all.ByteField('spare4', 0), # scapy_all.ByteField('spare5', 0), # scapy_all.LEIntField('P102_RunHr', 0), # scapy_all.LEIntField('P102_RunHr', 0), # scapy_all.ByteField('spare4', 0), # scapy_all.ByteField('spare5', 0), # scapy_all.LEIntField('P102_Permissive', 0), # scapy_all.LEIntField('spare', 0) ]
class Modbus_MBAP(scapy_all.Packet): """Modbus TCP base packet layer. This represents the Modbus application protocol header (MBAP)""" name = "Modbus_MBAP" fields_desc = [ scapy_all.ShortField( "transaction_id", 0 ), # A simple implementation of this is to use the tcp sequence number, and increment by 1 for each packet scapy_all.ShortField("protocol_id", 0), # I believe for Modbus TCP this is always 0 scapy_all.ShortField( "length", None ), # Is the length inherited from the child layers? If so, it'll need to be calculated. I'm sure there is a function for this! scapy_all.ByteField("unit_id", None), ] @classmethod def generate_unique_id(self): # should check that this layer is associated with a tcp sequence number, as when it is instantiated it might not be if TCP in self: return self[ TCP].seq # Just being lazy and using tcp sequence num for this else: return 1 # Boring default value @classmethod def is_request(self): """Function to determine if the packet is a request or response There is nothing explicit in the protocol to delineate each, so we must infer it from other things. returns True if 'this' packet is a request, false if a response""" if self[TCP].sport != 502 and self[TCP].dport == 502: return True elif self[TCP].sport == 502 and self[TCP].dport != 502: return False elif self[TCP].sport == self[TCP].dport == 502: return guess_request_response( self) # Define another function to guess else: # None of the ports are 502 return False # Default value #What do we do if both ports are 502? # Can return a default Value # Could return exception? # Could try and use some other method using sequence numbers # Can we use TCP flags? @classmethod def is_response(self): # Added for code readability return (not is_request(self)) def extract_padding( self, p ): # Will there be any padding? This is supposed to return the length return p[:self.length], p[self.length:] def default_payload_class( self ): # In case we want to overload a default payload class with our own return Modbus_PDU # def post_build(self, p, pay): # Post build is used to calculate the length of fields if self.length is None and pay: l = len(pay) p = p[:4] + struct.pack( ">H", l) + p[6:] # This is due to the structure of the frame return p + pay def answers(self, other): # This needs adjusting! # Can base this on whether the packet is a request or response return isinstance(other, Modbus_MBAP)