|
RomRaider
Documentation
Community
Developers
|
| Author |
Message |
|
Sasha_A80
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Mon May 25, 2020 11:14 am |
|
 |
| Senior Member |
Joined: Mon Jan 19, 2009 2:31 pm Posts: 1615 Location: Moscow, Russia
|
|
Most probably UDS service 23 was eliminated from the ecu code. And access to the ecu is to be provided thru kernel download secured UDS service.
|
|
| Top |
|
 |
|
VQ_Crazy!
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Mon May 25, 2020 1:23 pm |
|
 |
| Newbie |
Joined: Sat Apr 25, 2020 12:58 pm Posts: 75
|
Sasha_A80 wrote: Most probably UDS service 23 was eliminated from the ecu code. And access to the ecu is to be provided thru kernel download secured UDS service. I don't think UDS 0x23 has been removed, since it was used to dump "LeftoverPi" 2017 370z (Jan 25/2020) according to the Consult logs. I suspect 0x27 Security must be used now to read the memory. (which makes sense from security/hacking perspective) I will try to source a 2012+ ECU to test -OR- try to find a newer ROM (maybe use the 2017 370z ROM?) and use SHBootMode to flash my G37 bench top ECUs. Wait.... I just checked and they have different "Hardware IDs" between the 370z and the G37. BUT I am 99% certain the hardware is the same. Is it possible the "Hardware ID" is actually something else or part hardware and part configuration?
|
|
| Top |
|
 |
|
LeftoverPi
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Mon Jul 27, 2020 3:33 am |
|
 |
| Newbie |
Joined: Sat Nov 23, 2019 2:55 pm Posts: 21
|
|
"the tool" read my entire ECU 63bytes at a time with UDS 0x23. No security access requests were made
|
|
| Top |
|
 |
|
a33b
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Mon Dec 14, 2020 3:35 pm |
|
 |
| Experienced |
Joined: Sat Jun 24, 2017 2:23 pm Posts: 315
|
LeftoverPi wrote: "the tool" read my entire ECU 63bytes at a time with UDS 0x23. No security access requests were made This is correct. However, a diag FB "0x10 0xFB" session request is necessary to obtain permission to send UDS 0x23 requests. I'm currently trying to work out the calculation for the 16bit checksum sent with the rest of the encrypted payload. I'm not certain the bootloader even verifies it as the code for UDS 0x34 is rather messy... Has anybody happened to sort this out?
|
|
| Top |
|
 |
|
a33b
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Fri Dec 18, 2020 12:06 pm |
|
 |
| Experienced |
Joined: Sat Jun 24, 2017 2:23 pm Posts: 315
|
I figured it out. These bytes are required to satisfy the bootloader CRC check. The bootloader expects an identical CRC for each message received during the flash routine. The last 2 bytes of the payload sent are supplied with an official ".dat" file, but need to be calculated for custom payload. I wrote a routine that calculates the correct bytes; however, it is slow. This needs to be done for every 128 byte chunk of data. On my Arduino this takes an average of 150ms and would work out to ~20 minutes of time spent calculating these bytes if reflashing an entire 1MB ROM. It seems like must be a faster way, but I haven't thought of it yet. Code: #define CRC_16_CCITT_REVERSED 0x8408
uint16_t CRC_calc(char *msg_pntr, uint16_t msg_length, bool start, uint16_t prtl_CRC)
{ uint uVar1; uint8_t uVar2; uint16_t CRC; byte bVar4; uint uVar5;
if (start) CRC = 0xffff; //initial value for CRC else CRC = prtl_CRC; //the result of the payload CRC without the last two bytes uVar5 = 0; if (msg_length != 0) { do { uVar2 = msg_pntr[uVar5]; bVar4 = 0; do { uVar1 = CRC & 1; CRC >>= 1; if (uVar1 != (uVar2 & 1)) { //check the CRC and the rightmost bit of the data CRC = CRC ^ CRC_16_CCITT_REVERSED; } bVar4 += 1; uVar2 >>= 1; } while (bVar4 < 8); //for each bit uVar5 += 1; } while (uVar5 < msg_length); //for each byte } return CRC; //bootloader expects 0xF0B8 as result }
uint16_t bruteforce() { uint16_t reqd_CRC = 0xF0B8; uint16_t prtl_CRC; prtl_CRC = CRC_calc((char*)TxMsg.Buffer, TxMsg.len - 2, 1, 0xFFFF); //send UDS payload for CRC without last 2 bytes char trial_bytes[2] = {0, 0}; long start, elapsed; start = millis(); for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { if (CRC_calc(trial_bytes, 2, 0, prtl_CRC) == reqd_CRC) { elapsed = millis() - start; SerialUSB.print("Bruteforce time (ms): "); SerialUSB.println(elapsed,DEC); return (trial_bytes[0] << 8) | trial_bytes[1]; } trial_bytes[1] += 1; } trial_bytes[0] += 1; trial_bytes[1] = 0; } elapsed = millis() - start; SerialUSB.print("Fail to find bytes. Time (ms): "); SerialUSB.println(elapsed,DEC); return 0; //should probably return a bool and pass trial bytes as a pointer }
|
|
| Top |
|
 |
|
Pytrex
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sat Dec 19, 2020 3:50 pm |
|
 |
| RomRaider Donator |
 |
Joined: Fri Jul 26, 2019 3:35 am Posts: 789 Location: United States of America
|
|
| Top |
|
 |
|
fenugrec
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sat Dec 19, 2020 8:12 pm |
|
 |
| Experienced |
 |
Joined: Wed Jan 08, 2014 11:07 pm Posts: 652
|
Code: #define CRC_16_CCITT_REVERSED 0x8408 Heh, that's one of the first ones that should always be checked. Good work figuring it out. a33b wrote: I wrote a routine that calculates the correct bytes; however, it is slow. A) Why are you computing the CRC on the arduino ?? just have the host send proper 128-byte + CRC chunks ... B) you need to look at a table-based CRC16 implementation, even if you move the calculations to the PC. I have one (with a different polynomial though) in npkern, https://github.com/fenugrec/nisprog/blo ... end.c#L447There's also a nifty tool "pycrc" that generates CRC code according to the parameters you want, and you can select the implementation (per-bit, per-byte with table, etc)
_________________ If you like nisprog + npkern, you can support me via https://liberapay.com/fenugrec/ For sending me encrypted/secure messages, use PGP key 0xBAC61AEB3A3E6531 available from pool.sks-keyservers.net
|
|
| Top |
|
 |
|
a33b
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sat Dec 19, 2020 9:08 pm |
|
 |
| Experienced |
Joined: Sat Jun 24, 2017 2:23 pm Posts: 315
|
|
I'm running it on a Macchina M2. The Arduino is the host. Its functions are quite rudimentary at this point. I'm only using serial to watch what it's doing while I develop these functions.
|
|
| Top |
|
 |
|
fenugrec
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sat Dec 19, 2020 9:28 pm |
|
 |
| Experienced |
 |
Joined: Wed Jan 08, 2014 11:07 pm Posts: 652
|
|
| Top |
|
 |
|
a33b
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sun Dec 20, 2020 4:14 pm |
|
 |
| Experienced |
Joined: Sat Jun 24, 2017 2:23 pm Posts: 315
|
I've made enough progress on the CRC byte generator that it is tolerable for now. This subject can be confusing so I'll try and explain what's going on here. "CRC_calc" function (a few posts up) is lifted direct from Ghidra disassembly of the bootloader. Search for "0x8408" and you're bound to locate it. I've modified it to handle an extra 2 arguments for this "bruteforce" function. Within the bootloader, the CRC is given an initial register value of 0xFFFF. It then CRCs the entire UDS message, when flashing a 128 byte block of data the payload is 136 bytes total and is is typically </ 0x34, 0x82, 0xaddr[2], 0xaddr[1], 0xaddr[0], 0x80,...128 byte payload...,0xMB1, 0xMB2/>. Where we'll refer to MB as "magic byte". These bytes are NOT a CRC of the previous 134 bytes. They are the bytes required to force the CRC of the entire 136 byte message to equal 0xF0B8. So, my bruteforce byte generator sends the payload to CRC_calc to CRC the first 134 bytes of data. I refer to this as the partial CRC. The bruteforce function then sends the partial CRC to the CRC_calc as the initial register seed (rather than 0xFFFF) and completes the CRC calculation with 2 additional guessed bytes. bruteforce then checks if the result of the CRC is F0B8, if not, it simply increments the bytes by one until it is found. I've done some manual heuristics to improve the speed significantly, as seen below. Here's a valid message that could be sent: Find the missing bytes so that the CRC of the entire message is 0xF0B8! 34 82 02 FF 00 80 52 18 E3 C0 4F 16 4B E7 0A C3 F8 9B 3E 4F 49 B4 BC AC D3 F4 59 E5 F3 02 98 16 CB A4 EC BF DA 26 2A 78 75 2D 72 61 FD 2A 2F B6 5B 86 DB 00 EB BC C8 3C C2 FC 0C 5F 41 A5 F4 4F 4B 95 45 BA CD 15 94 F1 53 8A 46 7D F9 A0 4A 3E 5F 23 EF 6B 08 88 66 13 5F FA 86 B5 29 EC 55 51 31 77 DD 39 4D 60 FB D7 EB 49 5E 85 7D 58 41 E8 16 5C 56 FA 70 48 F4 8C EB 03 3C 77 78 AD 8F 6E 04 3A C2 E4 75 F2 XX XX Code: uint16_t bruteforce() { uint16_t reqd_CRC = 0xF0B8; uint16_t prtl_CRC; prtl_CRC = CRC_calc((char *)TxMsg.Buffer, TxMsg.len - 2, 1, 0xFFFF); //send UDS payload for CRC without last 2 bytes char trial_bytes[2] = {0, 0}; long start, elapsed; uint16_t result, guess; guess = (trial_bytes[0] << 8) | trial_bytes[1]; start = millis(); while (guess < 0xFFFF) //need a better condition here { result = CRC_calc(trial_bytes, 2, 0, prtl_CRC); //SerialUSB.print(guess, HEX); //SerialUSB.print(" "); //SerialUSB.println(result, HEX); if (result == reqd_CRC) { elapsed = millis() - start; SerialUSB.print("Bruteforce time (ms): "); SerialUSB.println(elapsed, DEC); return (trial_bytes[0] << 8) | trial_bytes[1]; } // check for a close result, we have last 3 bits correct when result is 0xF0Bx if ((result & 0xFFF0) == (reqd_CRC & 0xFFF0)) { switch (result & 0xf) { case 0: //F0B0 trial_bytes[0] ^= 0x88; trial_bytes[1] ^= 0x40; break; case 1: //F0B1 trial_bytes[0] ^= 0x99; trial_bytes[1] ^= 0x48; break; case 2: //F0B2 trial_bytes[0] ^= 0xAA; trial_bytes[1] ^= 0x50; break; case 3: //F0B3 trial_bytes[0] ^= 0xBB; trial_bytes[1] ^= 0x58; break; case 4: //F0B4 trial_bytes[0] ^= 0xCC; trial_bytes[1] ^= 0x60; break; case 5: //F0B5 trial_bytes[0] ^= 0xDD; trial_bytes[1] ^= 0x68; break; case 6: //F0B6 trial_bytes[0] ^= 0xEE; trial_bytes[1] ^= 0x70; break; case 7: //F0B7 trial_bytes[0] ^= 0xFF; trial_bytes[1] ^= 0x78; break; case 9: //F0B9 trial_bytes[0] ^= 0x11; trial_bytes[1] ^= 0x08; break; case 10: //F0BA trial_bytes[0] ^= 0x22; trial_bytes[1] ^= 0x10; break; case 11: //F0BB trial_bytes[0] ^= 0x33; trial_bytes[1] ^= 0x18; break; case 12: //F0BC trial_bytes[0] ^= 0x44; trial_bytes[1] ^= 0x20; break; case 13: //F0BD trial_bytes[0] ^= 0x55; trial_bytes[1] ^= 0x28; break; case 14: //F0BE trial_bytes[0] ^= 0x66; trial_bytes[1] ^= 0x30; break; case 15: //F0BF trial_bytes[0] ^= 0x77; trial_bytes[1] ^= 0x38; break; } elapsed = millis() - start; SerialUSB.print("Bruteforce time (ms): "); SerialUSB.println(elapsed, DEC); return (trial_bytes[0] << 8) | trial_bytes[1]; } else guess += 1; trial_bytes[0] = guess >> 8; trial_bytes[1] = guess & 0xff; } elapsed = millis() - start; SerialUSB.print("Fail to find bytes. Time (ms): "); SerialUSB.println(elapsed, DEC); return 0; //should probably return a bool and pass trial bytes as a pointer }
|
|
| Top |
|
 |
|
fenugrec
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sun Dec 20, 2020 10:23 pm |
|
 |
| Experienced |
 |
Joined: Wed Jan 08, 2014 11:07 pm Posts: 652
|
As could be expected the solution is simpler : 1) calculate crc16 with initvalue = 0xFFFF(exactly like your function, or as I suggested a table-based implementation would be way faster) on 134 bytes [34 82 .....] 2) bitwise invert the crc 3) store in little-endian So, your example would be 99 4B I think ? My test known-good packet was Code: const u8 testpkt[] = {0x34, 0x82, 0x03, 0x20, 0x80, 0x80, 0xD2, 0x85, 0x09, 0x27, 0x79, 0x09, 0xAB, 0x73, 0xE9, 0x76, 0xEE, 0x6E, 0xD8, 0xD6, 0xA9, 0x35, 0xBE, 0x0E, 0x14, 0xF4, 0xBA, 0x12, 0xD1, 0xE6, 0x59, 0x10, 0xB6, 0xD3, 0x9F, 0xEE, 0xEF, 0x66, 0x69, 0x37, 0x1C, 0xA5, 0x1B, 0xDF, 0xA3, 0x54, 0xFE, 0x95, 0xBD, 0xBF, 0xF3, 0xFF, 0x3A, 0xFE, 0x4D, 0x19, 0xE4, 0xA3, 0x84, 0xBD, 0x44, 0x79, 0xB9, 0xBB, 0x6F, 0xFD, 0xF2, 0x70, 0xFB, 0x01, 0x57, 0x58, 0xAC, 0xBB, 0xF6, 0xBF, 0xED, 0x48, 0x60, 0xC4, 0xF4, 0xD7, 0x65, 0xEC, 0xAA, 0xFA, 0x78, 0xCB, 0x41, 0x7D, 0xEA, 0x44, 0x2A, 0xF5, 0xC8, 0xA7, 0xCE, 0x17, 0xA7, 0xFA, 0x0A, 0x1C, 0x10, 0x33, 0x7A, 0xB2, 0x18, 0xB6, 0x07, 0xE6, 0xA4, 0x71, 0x98, 0x7B, 0xC5, 0xCE, 0xF2, 0xB4, 0x81, 0x1E, 0x55, 0xEA, 0xC7, 0xD7, 0xE0, 0x64, 0xB7, 0xA1, 0x10, 0x1A, 0xDB, 0xC7, 0x1C, 0x90, //these last 2 are the CRC16 0xD2, 0xFE }; crc16(testpkt, 134) = 0x012D ~crc = FED2 little-endian : D2 FE. Would you have time to describe the rest of the reflash procedure (any initdiag / special commands to fire up the bootloader etc) on the wiki ?
_________________ If you like nisprog + npkern, you can support me via https://liberapay.com/fenugrec/ For sending me encrypted/secure messages, use PGP key 0xBAC61AEB3A3E6531 available from pool.sks-keyservers.net
|
|
| Top |
|
 |
|
a33b
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sun Dec 20, 2020 10:50 pm |
|
 |
| Experienced |
Joined: Sat Jun 24, 2017 2:23 pm Posts: 315
|
fenugrec wrote: As could be expected the solution is simpler, your example would be 99 4B I think ? Yup! I knew there would be a smarter way! fenugrec wrote: Would you have time to describe the rest of the reflash procedure (any initdiag / special commands to fire up the bootloader etc) on the wiki ? Yeah, once I get the last few details worked out. The flash text log posted earlier in this thread was my basis for those special init commands. viewtopic.php?p=141718#p141718
|
|
| Top |
|
 |
|
dschultz
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sat Dec 26, 2020 10:25 am |
|
 |
| RomRaider Developer |
Joined: Wed May 20, 2009 9:49 pm Posts: 7314 Location: Canada eh!
|
|
CAN only ROM for a 2009 Altima QR25DE California edition 1ZN67A.
You do not have the required permissions to view the files attached to this post.
|
|
| Top |
|
 |
|
balrog
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sun Dec 19, 2021 10:46 am |
|
 |
| Newbie |
Joined: Sun Dec 19, 2021 10:20 am Posts: 2
|
Hi! I'm trying to dump the ROM from my 2013 Qashqai J10 and found this forum through the LeftOverPi blog I think... I looked at the log LeftOverPi captured of the UpRev ROM dump over CAN, which is actually pretty similar to what I'm seeing implemented in https://github.com/RomRaider/RomRaider/ ... tocol.javaApparently my ECU is different, there's no session mode 0xfb. Without it SID 0x23 returns error 0x7f (7f 23 7f) so I tried session 0xc0 and that seems to work, 0x23 now returns error 0x12 (I tried different addresses to dump from but no luck so far). This seems to indicate either SID 0x23 is disabled (i.e. it's there but it considers the ROM is empty or similar) or the command syntax is different. Commands 21 10 and 21 83 also fail here while they seem to succeed in other people's logs. Other SID 21 commands do work, even without the diagnostic session. What do you suggest trying? From the comments in the forum I see that nisprog is not expected to work over CAN either. FTR I'm documenting my car's CAN communications at https://github.com/balrog-kun/nissan-qashqai-can-info/
|
|
| Top |
|
 |
|
dschultz
|
Post subject: Re: CAN-only / "recent" ROMs Posted: Sun Dec 19, 2021 8:21 pm |
|
 |
| RomRaider Developer |
Joined: Wed May 20, 2009 9:49 pm Posts: 7314 Location: Canada eh!
|
|
| Top |
|
 |
Who is online |
Users browsing this forum: No registered users and 1 guest |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|