# gmlan unit tests # # Type the following command to launch start the tests: # $ sudo bash test/run_tests -t test/gmlan.uts -F % gmlan unit tests + Configuration of scapy = Load gmlan layer ~ conf load_contrib("automotive.ecu", globals_dict=globals()) load_contrib("automotive.gm.gmlan", globals_dict=globals()) from scapy.contrib.automotive.gm.gmlan_ecu_states import * from scapy.contrib.automotive.gm.gmlan_logging import * + Basic Packet Tests() = Set GMLAN ECU AddressingScheme conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2 assert conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] == 2 = Craft Packet x = GMLAN(b'\x52\x02\x01\x16\x71\x00\x00\x0c\xaa\xbb') x.load == b'\x00\x0c\xaa\xbb' x.service == 0x52 = Craft VIN Packet x = GMLAN(b'\x5a\x90'+ raw(b"WOOOJBF35W1042000")) x.load == b'WOOOJBF35W1042000' x.dataIdentifier == 0x90 = Test Packet with ECU AddressingScheme2 x = GMLAN()/GMLAN_RMBA(b'\x11\x22\x44\x22') x.memoryAddress == 0x1122 x.memorySize == 0x4422 = Test Packet GMLAN_RMBAPR with ECU AddressingScheme2 y = GMLAN()/GMLAN_RMBAPR(b'\x11\x22\x44\x22') y.memoryAddress == 0x1122 y.dataRecord == b'\x44\x22' y.answers(x) == True = Craft Packet with ECU AddressingScheme2 x = GMLAN() / GMLAN_RMBA(b'\x11\x22\x44\x22') y = GMLAN()/GMLAN_RMBA(memoryAddress=0x1122, memorySize=0x4422) bytes(x) == bytes(y) = Test Packet with ECU AddressingScheme3 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3 x = GMLAN()/GMLAN_RMBA(b'\x11\x22\x44\x22\x11') x.memoryAddress == 0x112244 x.memorySize == 0x2211 = Test Packet GMLAN_RMBAPR with ECU AddressingScheme3 y = GMLAN()/GMLAN_RMBAPR(b'\x11\x22\x44\x22\x11') y.memoryAddress == 0x112244 y.dataRecord == b'\x22\x11' y.answers(x) == True = Craft Packet with ECU AddressingScheme3 x = GMLAN() / GMLAN_RMBA(b'\x11\x22\x44\x22\x11') y = GMLAN()/GMLAN_RMBA(memoryAddress=0x112244, memorySize=0x2211) bytes(x) == bytes(y) = Test Packet with ECU AddressingScheme4 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4 x = GMLAN()/GMLAN_RMBA(b'\x11\x22\x44\x22\x11\x00') x.memoryAddress == 0x11224422 x.memorySize == 0x1100 = Test Packet GMLAN_RMBAPR with ECU AddressingScheme4 y = GMLAN()/GMLAN_RMBAPR(b'\x11\x22\x44\x22\x11\x00') y.memoryAddress == 0x11224422 y.dataRecord == b'\x11\x00' y.answers(x) == True = Craft Packet with ECU AddressingScheme4 x = GMLAN() / GMLAN_RMBA(b'\x11\x22\x44\x22\x11\x00') y = GMLAN()/GMLAN_RMBA(memoryAddress=0x11224422, memorySize=0x1100) bytes(x) == bytes(y) = Craft Packet for RequestDownload2 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2 x = GMLAN(b'\x34\x12\x08\x15') x.service == 0x34 x.dataFormatIdentifier == 0x12 x.memorySize == 0x815 y = GMLAN()/GMLAN_RD(dataFormatIdentifier=0x12, memorySize=0x815) bytes(y) == bytes(x) = Craft Packet for RequestDownload3 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3 x = GMLAN(b'\x34\x12\x08\x15\x00') x.service == 0x34 x.dataFormatIdentifier == 0x12 x.memorySize == 0x81500 y = GMLAN()/GMLAN_RD(dataFormatIdentifier=0x12, memorySize=0x81500) bytes(y) == bytes(x) = Craft Packet for RequestDownload4 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4 x = GMLAN(b'\x34\x12\x08\x15\x00\x11') x.service == 0x34 x.dataFormatIdentifier == 0x12 x.memorySize == 0x8150011 = Craft Packet for RFRD1 a = GMLAN(b'\x12\x01') a.service == 0x12 a.subfunction == 1 = Craft Packet for RFRD2 b = GMLAN(b'\x12\x02\x01\x02\x03\x04') b.service == 0x12 b.subfunction == 2 b.dtc.failureRecordNumber == 1 b.dtc.DTCHighByte == 2 b.dtc.DTCLowByte == 3 b.dtc.DTCFailureType == 4 = Craft Packet for RFRDPR_RFRI x = GMLAN(b'\x52\x01\x00\x01\x02\x03\x04') x.service == 0x52 x.subfunction == 1 x.failureRecordDataStructureIdentifier == 0 x.dtcs[0].failureRecordNumber == 1 x.dtcs[0].DTCHighByte == 2 x.dtcs[0].DTCLowByte == 3 x.dtcs[0].DTCFailureType == 4 x.answers(a) == True = Craft Packet for RFRDPR_RFRI x = GMLAN(b'\x52\x01\x00\x01\x02\x03\x04\x01\x02\x03\x04\x01\x02\x03\x04\x01\x02\x03\x04') x.service == 0x52 x.subfunction == 1 x.failureRecordDataStructureIdentifier == 0 x.dtcs[0].failureRecordNumber == 1 x.dtcs[0].DTCHighByte == 2 x.dtcs[0].DTCLowByte == 3 x.dtcs[0].DTCFailureType == 4 x.dtcs[1].failureRecordNumber == 1 x.dtcs[1].DTCHighByte == 2 x.dtcs[1].DTCLowByte == 3 x.dtcs[1].DTCFailureType == 4 x.dtcs[2].failureRecordNumber == 1 x.dtcs[2].DTCHighByte == 2 x.dtcs[2].DTCLowByte == 3 x.dtcs[2].DTCFailureType == 4 x.dtcs[3].failureRecordNumber == 1 x.dtcs[3].DTCHighByte == 2 x.dtcs[3].DTCLowByte == 3 x.dtcs[3].DTCFailureType == 4 x.answers(a) == True = Craft Packet for RFRDPR_RFRP x = GMLAN(b'\x52\x02\x01\x02\x03\x04deadbeef') x.service == 0x52 x.subfunction == 2 x.dtc.failureRecordNumber == 1 x.dtc.DTCHighByte == 2 x.dtc.DTCLowByte == 3 x.dtc.DTCFailureType == 4 x.show() x.load == b'deadbeef' x.answers(b) == True = Craft Packet for RDBI x = GMLAN(b'\x1A\x11') x.service == 0x1A x.dataIdentifier == 0x11 = Craft Packet for RDBIPR y = GMLAN(b'\x5A\x11deadbeef') y.service == 0x5A y.dataIdentifier == 0x11 y.load == b'deadbeef' y.answers(x) == True = Craft Packet for RDBPI x = GMLAN(b'\x22\x11\x11\x22\x22\x33\x33\x44\x44\x55\x55\x66\x66\x77\x77\x88\x88\x99\x99') x.service == 0x22 x.identifiers[0] == 0x1111 x.identifiers[1] == 0x2222 x.identifiers[2] == 0x3333 x.identifiers[3] == 0x4444 x.identifiers[4] == 0x5555 x.identifiers[5] == 0x6666 x.identifiers[6] == 0x7777 x.identifiers[7] == 0x8888 x.identifiers[8] == 0x9999 = Craft Packet for RDBPIPR y = GMLAN(b'\x62\x11\x11deadbeef') y.service == 0x62 y.parameterIdentifier == 0x1111 y.load == b'deadbeef' y.answers(x) == True = Craft Packet for GMLAN_RDBPKTI1 x = GMLAN(b'\xAA\x01deadbeef') x.service == 0xAA x.subfunction == 0x01 x.request_DPIDs == [0x64, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66] = Craft Packet for GMLAN_RDBPKTI3 x = GMLAN(b'\xAA\x02deadbeef') x.service == 0xAA x.subfunction == 0x02 x.request_DPIDs == [0x64, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66] = Craft Packet for GMLAN_RDBPKTI4 x = GMLAN(b'\xAA\x03deadbeef') x.service == 0xAA x.subfunction == 0x03 x.request_DPIDs == [0x64, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66] = Craft Packet for GMLAN_RDBPKTI2 x = GMLAN(b'\xAA\x00') x.service == 0xAA x.subfunction == 0 = Build GMLAN_RDBPKTI1 x = GMLAN()/GMLAN_RDBPKTI(subfunction=1, request_DPIDs=[0x64, 0x65]) assert b"\xaa\x01de" == bytes(x) = Craft Packet for GMLAN_SA1 a = GMLAN(b'\x27\x01') a.service == 0x27 a.subfunction == 1 = Craft Packet for GMLAN_SA2 b = GMLAN(b'\x27\x02\xde\xad') b.service == 0x27 b.subfunction == 2 b.securityKey == 0xdead = Craft Packet for GMLAN_SAPR1 x = GMLAN(b'\x67\x02') x.service == 0x67 x.subfunction == 2 x.answers(b) ecu = Ecu() ecu.update(b) ecu.update(x) assert ecu.state.security_level == 2 = Craft Packet for GMLAN_SAPR2 x = GMLAN(b'\x67\x01\xde\xad') x.service == 0x67 x.subfunction == 1 x.securitySeed == 0xdead x.answers(a) = Craft Packet for GMLAN_DDM x = GMLAN(b'\x2c\x02dead') x.service == 0x2c x.DPIDIdentifier == 2 x.PIDData == b'dead' = Craft Packet for GMLAN_DDMPR y = GMLAN(b'\x6c\x02dead') y.service == 0x6c y.DPIDIdentifier == 2 y.answers(x) = Craft Packet for GMLAN_DPBA1 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2 x = GMLAN(b'\x2D\x02\x02\x11\x11\x33') x.service == 0x2d x.parameterIdentifier == 0x202 x.memoryAddress == 0x1111 x.memorySize == 0x33 = Craft Packet for GMLAN_DPBA2 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3 x = GMLAN(b'\x2D\x02\x02\x11\x11\x11\x33') x.service == 0x2d x.parameterIdentifier == 0x202 x.memoryAddress == 0x111111 x.memorySize == 0x33 = Craft Packet for GMLAN_DPBA3 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4 x = GMLAN(b'\x2D\x02\x02\x11\x11\x11\x11\x33') x.service == 0x2d x.parameterIdentifier == 0x202 x.memoryAddress == 0x11111111 x.memorySize == 0x33 = Craft Packet for GMLAN_DPBAPR y = GMLAN(b'\x6D\x02\x02') y.service == 0x6d y.parameterIdentifier == 0x202 y.answers(x) = Craft Packet for GMLAN_RD1 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2 x = GMLAN(b'\x34\x02\x11\x11') x.service == 0x34 x.dataFormatIdentifier == 0x2 x.memorySize == 0x1111 = Craft Packet for GMLAN_RD2 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3 x = GMLAN(b'\x34\x02\x11\x11\x11') x.service == 0x34 x.dataFormatIdentifier == 0x2 x.memorySize == 0x111111 = Craft Packet for GMLAN_RD3 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4 x = GMLAN(b'\x34\x02\x11\x11\x11\x11') x.service == 0x34 x.dataFormatIdentifier == 0x2 x.memorySize == 0x11111111 = Craft Packet for GMLAN_TD1 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2 x = GMLAN(b'\x36\x02\x11\x11dead') x.service == 0x36 x.subfunction == 0x2 x.startingAddress == 0x1111 x.dataRecord == b'dead' = Craft Packet for GMLAN_TD2 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3 x = GMLAN(b'\x36\x02\x11\x11\x11dead') x.service == 0x36 x.subfunction == 0x2 x.startingAddress == 0x111111 x.dataRecord == b'dead' = Craft Packet for GMLAN_TD3 conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4 x = GMLAN(b'\x36\x02\x11\x11\x11\x11dead') x.service == 0x36 x.subfunction == 0x2 x.startingAddress == 0x11111111 x.dataRecord == b'dead' = Craft Packet for WDBI x = GMLAN(b'\x3b\x11deadbeef') x.service == 0x3b x.dataIdentifier == 0x11 x.dataRecord == b'deadbeef' = Craft Packet for WDBIPR y = GMLAN(b'\x7b\x11') y.service == 0x7b y.dataIdentifier == 0x11 y.answers(x) = Craft Packet for RPSPR x = GMLAN(b'\xe2\x11') x.service == 0xe2 x.programmedState == 0x11 = Craft Packet for PM x = GMLAN(b'\xA5\x11') x.service == 0xA5 x.subfunction == 0x11 = Craft Packet for RDI x = GMLAN(b'\xA9\x11') x.service == 0xA9 x.subfunction == 0x11 = Craft Packet for RDI_BN x = GMLAN(b'\xA9\x80\x11\x22\x33') x.service == 0xA9 x.subfunction == 0x80 x.DTCHighByte == 0x11 x.DTCLowByte == 0x22 x.DTCFailureType == 0x33 = Craft Packet for RDI_BM1 x = GMLAN(b'\xA9\x81\x11') x.service == 0xA9 x.subfunction == 0x81 x.DTCStatusMask == 0x11 = Craft Packet for RDI_BM2 x = GMLAN(b'\xA9\x82\x11') x.service == 0xA9 x.subfunction == 0x82 x.DTCStatusMask == 0x11 = Craft Packet for NR x = GMLAN(b'\x7f\x11\x00\x11\x22') x.service == 0x7f x.requestServiceId == 0x11 x.returnCode == 0 x.deviceControlLimitExceeded == 0x1122 = Check not answers y = GMLAN(b'\x11deadbeef') x = GMLAN(b'\x7f\x10\x00\x11\x22') assert not x.answers(y) = Check answers 1 y = GMLAN(b'\x10deadbeef') x = GMLAN(b'\x7f\x10\x00\x11\x22') assert x.answers(y) = Set treat-response-pending-as-answer conf.contribs['GMLAN']['treat-response-pending-as-answer'] = False assert conf.contribs['GMLAN']['treat-response-pending-as-answer'] == False = Check response-pending is not considered as answer y = GMLAN(b'\x10deadbeef') x = GMLAN(b'\x7f\x10\x78\x11\x22') assert not x.answers(y) = Check response-pending is considered as answer conf.contribs['GMLAN']['treat-response-pending-as-answer'] = True assert conf.contribs['GMLAN']['treat-response-pending-as-answer'] == True y = GMLAN(b'\x10deadbeef') x = GMLAN(b'\x7f\x10\x78\x11\x22') assert x.answers(y) = Check hashret 1 print(y.hashret()) print(x.hashret()) y.hashret() == x.hashret() = Check answers 2 y = GMLAN()/GMLAN_SA(subfunction=1) x = GMLAN()/GMLAN_SAPR(subfunction=1) assert x.answers(y) = Check hashret 2 y.hashret() == x.hashret() = Check modifies ecu state ecu = Ecu() ecu.update(GMLAN(service="InitiateDiagnosticOperation")) ecu.update(GMLAN(service="InitiateDiagnosticOperationPositiveResponse")) assert ecu.state.session == 3 ecu.update(GMLAN(service="ReturnToNormalOperation")) ecu.update(GMLAN(service="ReturnToNormalOperationPositiveResponse")) assert ecu.state.session == 1 ecu.update(GMLAN(service="ProgrammingMode")) ecu.update(GMLAN(service="ProgrammingModePositiveResponse")) assert ecu.state.session == 2 ecu.update(GMLAN(service="DisableNormalCommunication")) ecu.update(GMLAN(service="DisableNormalCommunicationPositiveResponse")) assert ecu.state.communication_control == 1 ecu.update(GMLAN(service="ReturnToNormalOperation")) ecu.update(GMLAN(service="ReturnToNormalOperationPositiveResponse")) assert ecu.state.session == 1 = Craft GMLAN_DC req = GMLAN()/GMLAN_DC(CPIDNumber=0x11, CPIDControlBytes=b"\xbe\xefabc") assert bytes(req) == b"\xAE\x11\xbe\xefabc" req2 = GMLAN()/GMLAN_DC(CPIDNumber=0x12) assert bytes(req2) == b"\xAE\x12\x00\x00\x00\x00\x00" resp = GMLAN()/GMLAN_DCPR(CPIDNumber=0x11) assert bytes(resp) == b"\xEE\x11" assert resp.answers(req) assert not resp.answers(req2) = Dissect test GMLAN_DC req = GMLAN(b"\xAE\x14caffe") assert req.service == 0xAE assert req.CPIDNumber == 20 assert req.CPIDControlBytes == b"caffe" resp = GMLAN(b"\xEE\x14") assert resp.service == 0xEE assert resp.CPIDNumber == 20 assert resp.answers(req) assert resp.hashret() == req.hashret() = Logging tests def get_log(pkt): for layer in pkt.layers(): if not hasattr(layer, "get_log"): continue try: return layer.get_log(pkt) except TypeError: return layer.get_log.im_func(pkt) pkt = GMLAN()/GMLAN_RFRD(subfunction=1) log = get_log(pkt) assert len(log) == 2 assert log[1] == "readFailureRecordIdentifiers" assert log[0] == "ReadFailureRecordData" pkt = GMLAN()/GMLAN_RFRDPR(subfunction=1) log = get_log(pkt) assert len(log) == 2 assert log[1] == "readFailureRecordIdentifiers" assert log[0] == "ReadFailureRecordDataPositiveResponse" pkt = GMLAN()/GMLAN_RDBPI(identifiers=[5]) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == '[OBD_EngineCoolantTemperature]' assert log[0] == "ReadDataByParameterIdentifier" pkt = GMLAN()/GMLAN_RDBPIPR(parameterIdentifier=5) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == 'OBD_EngineCoolantTemperature' assert log[0] == "ReadDataByParameterIdentifierPositiveResponse" pkt = GMLAN()/GMLAN_RDBPKTI(subfunction=0) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == 'stopSending' assert log[0] == "ReadDataByPacketIdentifier" pkt = GMLAN()/GMLAN_RMBA(memoryAddress=0) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == '0x0' assert log[0] == "ReadMemoryByAddress" pkt = GMLAN()/GMLAN_RMBAPR(memoryAddress=0, dataRecord=b"deadbeef") log = get_log(pkt) print(log) assert len(log) == 2 assert log[1][0] == '0x0' assert log[1][1] == b'deadbeef' assert log[0] == "ReadMemoryByAddressPositiveResponse" pkt = GMLAN()/GMLAN_DDM(DPIDIdentifier=0, PIDData=b"deadbeef") log = get_log(pkt) print(log) assert len(log) == 2 assert log[1][0] == '0x0' assert log[1][1] == b'deadbeef' assert log[0] == "DynamicallyDefineMessage" pkt = GMLAN()/GMLAN_DDMPR(DPIDIdentifier=0) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == '0x0' assert log[0] == "DynamicallyDefineMessagePositiveResponse" pkt = GMLAN()/GMLAN_DPBA(parameterIdentifier=0, memoryAddress=1, memorySize=3) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1][0] == 0 assert log[1][1] == 1 assert log[1][2] == 3 assert log[0] == "DefinePIDByAddress" pkt = GMLAN()/GMLAN_DPBAPR(parameterIdentifier=0) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == 0 assert log[0] == "DefinePIDByAddressPositiveResponse" pkt = GMLAN()/GMLAN_WDBI(dataIdentifier=0, dataRecord=b"deadbeef") log = get_log(pkt) print(log) assert len(log) == 2 assert log[1][0] == "0x0" assert log[1][1] == b"deadbeef" assert log[0] == "WriteDataByIdentifier" pkt = GMLAN()/GMLAN_WDBIPR(dataIdentifier=0) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == "0x0" assert log[0] == "WriteDataByIdentifierPositiveResponse" pkt = GMLAN()/GMLAN_RDI(subfunction=0x80) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == "readStatusOfDTCByDTCNumber" assert log[0] == "ReadDiagnosticInformation" pkt = GMLAN()/GMLAN_DC(CPIDNumber=0x80) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == "0x80" assert log[0] == "DeviceControl" pkt = GMLAN()/GMLAN_DCPR(CPIDNumber=0x80) log = get_log(pkt) print(log) assert len(log) == 2 assert log[1] == "0x80" assert log[0] == "DeviceControlPositiveResponse"