RomRaider Logo

RomRaider

Open Source ECU Tools
 FAQ •  Register •  Login 

RomRaider

Documentation

Community

Developers

It is currently Sun Dec 28, 2025 12:00 pm

All times are UTC - 5 hours [ DST ]





Post new topic Reply to topic  [ 94 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7  Next
Author Message
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Mon May 25, 2020 11:14 am 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Mon May 25, 2020 1:23 pm 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Mon Jul 27, 2020 3:33 am 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Mon Dec 14, 2020 3:35 pm 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Fri Dec 18, 2020 12:06 pm 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sat Dec 19, 2020 3:50 pm 
Offline
RomRaider Donator
User avatar

Joined: Fri Jul 26, 2019 3:35 am
Posts: 789
Location: United States of America
Wow, that’s some incredible progress A33B! Are you using a CAN shield with your arduino?

_________________
NissanDefinitions Repository


Top
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sat Dec 19, 2020 8:12 pm 
Offline
Experienced
User avatar

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#L447

There'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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sat Dec 19, 2020 9:08 pm 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sat Dec 19, 2020 9:28 pm 
Offline
Experienced
User avatar

Joined: Wed Jan 08, 2014 11:07 pm
Posts: 652
Also, for the "last two bytes" and CRC residue, check
https://stackoverflow.com/questions/492 ... iven-value

reveng (https://reveng.sourceforge.io/) might also help to test various parameters and algos.

_________________
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sun Dec 20, 2020 4:14 pm 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sun Dec 20, 2020 10:23 pm 
Offline
Experienced
User avatar

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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sun Dec 20, 2020 10:50 pm 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sat Dec 26, 2020 10:25 am 
Offline
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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sun Dec 19, 2021 10:46 am 
Offline
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.java

Apparently 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
 Profile  
 
 Post subject: Re: CAN-only / "recent" ROMs
PostPosted: Sun Dec 19, 2021 8:21 pm 
Offline
RomRaider Developer

Joined: Wed May 20, 2009 9:49 pm
Posts: 7314
Location: Canada eh!
Did you try this?
viewtopic.php?f=65&t=19033


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 94 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7  Next

All times are UTC - 5 hours [ DST ]


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

Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Style based on FI Subsilver by phpBBservice.nl