vtl / volvo-cem-cracker

Volvo central electronic module pin cracker via OBD for P1, P2 and P3 platforms
GNU General Public License v3.0
106 stars 46 forks source link

Volvo CEM pin cracker via OBD

A research project grown out of curiosity. Cracks 6 bytes of pin code via High Speed CAN-bus in under 20 minutes.

Supported platforms:

Earlier P2 1999-2004 can be supported as well, CEM donation is welcome.

Find us at Matthew's Volvo Site for support: https://www.matthewsvolvosite.com/forums/viewtopic.php?f=10&t=85611

Big thanks to an unidentified hacker from western Germany for hints!

Image

An optional LCD display can be added for stand-alone operation.

Image

Image

Cracking CEM pin in about 10 minutes (video):

Image

Possible issues and fixes

Depending on your CEM model, you may face some issues with PIN decoding. Here are some examples and recommendations.

CEM 30786889

Unable to decode 3rd byte.

Cracker decodes first 2 bytes, but the third byte is always different so PIN cannot be decoded. For example:

Attempt 1:
21:54:30.212 -> Candidate PIN 32 78 79 -- -- -- : brute forcing bytes 3 to 5 (3 bytes), will take up to 646 seconds
...
Attempt 2:
22:30:45.288 -> Candidate PIN 32 78 78 -- -- -- : brute forcing bytes 3 to 5 (3 bytes), will take up to 646 seconds

Attempt 3:
23:06:12.024 -> Candidate PIN 32 78 02 -- -- -- : brute forcing bytes 3 to 5 (3 bytes), will take up to 646 seconds

Attempt 4:
14:26:13.327 -> Candidate PIN 32 78 41 -- -- -- : brute forcing bytes 3 to 5 (3 bytes), will take up to 646 seconds

There are two possible solutions that may help:

  1. Use brute force for rest of bytes - it may take 18-20 hours. To do it, change the following tunable parameter value to 2:

    #define CALC_BYTES     3     /* how many PIN bytes to calculate (1 to 4), the rest is brute-forced */
  2. Another solution that may help - comment out the following line:

    set_arm_clock (180000000);

And to avoid time waste, hardcode the first two bytes that you already know:

  /* try and crack each PIN position */

  // Add lines to skip first known bytes */
  pin[0] = 0x32; // Known first byte example
  pin[1] = 0x78; // Known second byte example

  // Change initial value of i from 0 to 2
  for (i = 2; i < maxBytes; i++) {
    crackPinPosition (pin, i, verbose);
  }