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 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 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 Modbus_PDU(scapy_all.Packet): FUNCTION_CODES = { # Data functions 2: "READ_DISCRETE_INPUTS", 1: "READ_COILS", 5: "WRITE_SINGLE_COIL", 15: "WRITE_MULTIPLE_COILS", 4: "READ_INPUT_REGISTER", 3: "READ_HOLDING_REGISTERS", 6: "WRITE_SINGLE_REGISTER", 16: "WRITE_MULTIPLE_REGISTERS", 23: "READ_WRITE_MULTIPLE_REGISTERS", 22: "MASK_WRITE_REGISTERS", 24: "READ_FIFO_QUEUE", 20: "WRITE_FILE_RECORD", 21: "READ_FILE_RECORD", # Diagnostic functions 7: "READ_EXCEPTION_STATUS", 8: "DIAGNOSTIC", # Note: Needs sub code (00-18, 20) 11: "GET_COM_EVENT_COUNTER", 12: "GET_COM_EVENT_LOG", 17: "REPORT_SLAVE_ID", 43: "READ_DEVICE_IDENTIFICATION", # Sub code 14 # "Other" function 43: "ENCAPSULATED_INTERFACE_TRANSPORT" # sub codes 13,14 } fields_desc = [ scapy_all.ByteEnumField("function_code", None, FUNCTION_CODES) ] def guess_payload_class(self, payload): """Used do find out what the payload is, here we will use the function code. scapy should be able to find out which packets are requests v answers by the tcp stream""" if self.function_code in FUNCTION_CODES: # Valid code if is_request(self): # Now look at code to determine payload class return modbus_classes_requests[self.function_code] elif is_response(self): return modbus_classes_responses[self.function_code] else: # if we can't figure it out, then let scapy attempt to handle it return scapy_all.guess_payload_class(self, payload)
class MDCData(scapy.Packet): name = "MulticastDataCenterData " fields_desc = [ scapy.ShortField("addr", 0), scapy.XByteField("mode", 0), scapy.XByteField("label", 0), scapy.ByteEnumField( "code", 5, { 1: "REQUEST", 2: "PTCH_REQ", 3: "DATA_FNSD", 4: "PTCH_DATA", 5: "DATA", 6: "FEEDBACK" }, ), scapy.XByteField("appID", 2), scapy.XByteField("dataID", 0), scapy.XByteField("sn", 0), scapy.XByteField("dataSize", 11), ]
class CIP_ResponseStatus(scapy_all.Packet): """The response field of CIP headers""" name = "CIP_ResponseStatus" fields_desc = [ scapy_all.XByteField("reserved", 0), # Reserved byte, always null scapy_all.ByteEnumField("status", 0, {0: "success"}), scapy_all.XByteField("additional_size", 0), scapy_all.StrLenField("additional", "", # additionnal status length_from=lambda p: 2 * p.additional_size), ] ERROR_CODES = { 0x00: "Success", 0x01: "Connection failure", 0x02: "Resource unavailable", 0x03: "Invalid parameter value", 0x04: "Path segment error", 0x05: "Path destination unknown", 0x06: "Partial transfer", 0x07: "Connection lost", 0x08: "Service not supported", 0x09: "Invalid attribute value", 0x0a: "Attribute list error", 0x0b: "Already in requested mode/state", 0x0c: "Object state conflict", 0x0d: "Object already exists", 0x0e: "Attribute not settable", 0x0f: "Privilege violation", 0x10: "Device state conflict", 0x11: "Reply data too large", 0x12: "Fragmentation of a primitive value", 0x13: "Not enough data", 0x14: "Attribute not supported", 0x15: "Too much data", 0x16: "Object does not exist", 0x17: "Service fragmentation sequence not in progress", 0x18: "No stored attribute data", 0x19: "Store operation failure", 0x1a: "Routing failure, request packet too large", 0x1b: "Routing failure, response packet too large", 0x1c: "Missing attribute list entry data", 0x1d: "Invalid attribute value list", 0x1e: "Embedded service error", 0x1f: "Vendor specific error", 0x20: "Invalid parameter", 0x21: "Write-once value or medium already written", 0x22: "Invalid reply received", 0x23: "Buffer overflow", 0x24: "Invalid message format", 0x25: "Key failure in path", 0x26: "Path size invalid", 0x27: "Unexpected attribute in list", 0x28: "Invalid Member ID", 0x29: "Member not settable", 0x2a: "Group 2 only server general failure", 0x2b: "Unknown Modbus error", 0x2c: "Attribute not gettable", } def extract_padding(self, p): return "", p def __repr__(self): if self.reserved != 0: return scapy_all.Packet.__repr__(self) # Known status if self.status in self.ERROR_CODES and self.additional_size == 0: return "<CIP_ResponseStatus status={}>".format(self.ERROR_CODES[self.status]) # Simple status if self.additional_size == 0: return "<CIP_ResponseStatus status=%#x>" % self.status # Forward Open failure if self.status == 1 and self.additional == b"\x00\x01": return "<CIP_ResponseStatus status=Connection failure>" return scapy_all.Packet.__repr__(self)
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) ]