Important
Disclaimer: This project was done with explicit permission from the device owner. I do not encourage or condone accessing hardware or software that you do not have permission to work on.
Showcasing how I managed to unlock a cr-902 stereo when the code was lost by dumping the internal memory and analyzing its content.
When my brother received his car from our grandfather, the battery had been drained. As a result of the battery drainage, the anti-theft mechanism on the stereo was activated, and upon startup it prompted for a code. This code could not be found, and the only official way to obtain it was to contact a certified Volvo reseller, who, after a fee and following the proper procedure, may have access to the code in a registry. After contacting a reseller, he was informed that they could not retrieve the code and were unable to assist him.
A few days later he decided that the most practical option was to buy a new stereo with an adapter for the car and dispose of the old one. Knowing that I have experience in this area, he gave the stereo to me and told me I could tinker with it as I wished. Being curious and willing to take on the challenge, I accepted the challenge and got to work.
I did not know much at the start. The unit asked for a code on startup, so the code had to be stored somewhere on the device, either inside the MCU or in some external memory. I looked for manuals and datasheets but could not find anything useful, so I opened the stereo to see for myself. This was what I saw:
The first thing I noticed was a large chip near the center bottom of the board. The marking on it read M38254M6D150FP. A quick search pointed me to this document that lists this part as the MCU used in the stereo. Next to the MCU in the document there was a column for EEPROM showing 3132 24C02. On the board I found an 8 pin SMD chip marked 3132 539 that matched the package for that EEPROM. Following the traces showed the chip was connected to the MCU, which is a common setup for storing user settings and, in some units, codes.
Based on that I concluded the EEPROM was the most likely place to find the code. The next step was to dump the contents of that chip and analyze the data.
The first step was figuring out which pins were which. A quick search told me the chip worked over I²C. Looking at the board, I noticed it was write-protected, so I couldn’t accidentally overwrite any data. I decided to connect the EEPROM to a Raspberry Pi Pico using debugging probes, and program the Pico to read the EEPROM and print the data over serial.
After searching GitHub, I found this library, which was exactly what I needed. Using it, I wrote the following Arduino code and uploaded it to the Pico:
#include <Wire.h>
#include <at24c02.h> // The library compatible with 24C02
void setup() {
Serial.begin(115200);
while(!Serial){};
// Make sure it uses the pins I have connected it to
Wire1.setSDA(2);
Wire1.setSCL(3);
Wire1.begin();
Serial.println("Starting EEPROM scan...");
// We are not sure of the I2C address, so try all of the common ones for EEPROM
for (uint8_t addr = 0x50; addr <= 0x57; addr++) {
Wire1.beginTransmission(addr);
if (Wire1.endTransmission() == 0) {
Serial.print("Found EEPROM at address 0x");
Serial.println(addr, HEX);
AT24C02 eeprom(addr, Wire1);
dumpEEPROM(eeprom);
break;
}
}
Serial.println("Scan complete.");
}
void loop() {
}
void dumpEEPROM(AT24C02 &eeprom) {
// Automatically find the full length of the EEPROM
int EEPROM_SIZE = eeprom.length(); // 256 Bytes is default for 24C02
Serial.println("Dumping EEPROM contents:");
for (int i = 0; i < EEPROM_SIZE; i++) {
byte val = eeprom.read(i);
if (i % 16 == 0) Serial.println();
Serial.print(val, HEX);
Serial.print(" ");
}
Serial.println("\n--- End of dump ---");
}After joining EEPROM and Pico GND, and connecting EEPROM VCC to Pico 3.3V output, I plugged it in, and opened the serial connection in PuTTY, I see this being printed:
Starting EEPROM scan...
Found EEPROM at address 0x50
Dumping EEPROM contents:
4 56 56 56 2 56 56 56 1 56 56 56 5 56 56 56
3 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56
D E2 1 52 31 E4 2 52 5F E2 3 52 8B E4 24 52
B8 E2 20 52 C6 E2 41 52 14 EF 24 52 97 51 FF 52
87 E7 24 52 0 56 56 56 0 56 56 56 0 56 56 56
0 56 56 56 9 56 56 56 35 56 56 56 80 56 56 56
88 56 56 56 8C 56 56 56 56 56 56 56 56 56 56 56
56 56 56 56 56 56 56 56 50 52 56 41 41 54 56 41
4 56 56 56 2 56 56 56 1 56 56 56 5 56 56 56
3 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56
D E2 1 52 31 E4 2 52 5F E2 3 52 8B E4 24 52
B8 E2 20 52 C6 E2 41 52 14 EF 24 52 97 51 FF 52
87 E7 24 52 0 56 56 56 0 56 56 56 0 56 56 56
0 56 56 56 9 56 56 56 35 56 56 56 80 56 56 56
88 56 56 56 8C 56 56 56 56 56 56 56 56 56 56 56
56 56 56 56 56 56 56 56 50 52 56 41 41 54 56 41
--- End of dump ---
Scan complete.
The content of the EEPROM was sucessfully dumped, and we can start analyzing it.
Looking at the dump, there were a lot of 0x56 values. This is likely what the EEPROM was filled with before any real data was written. The data also repeats halfway through, which suggested that there were two copies of the same data. That meant we only needed to search through the first 128 bytes.
We were looking for a four-digit code with digits between 1–6. The values could appear either as ASCII (0x31-0x36) or as raw numbers (0x01-0x06). There were no values in the ASCII range, but plenty in the raw number range. Right at the start, there was a noticeable pattern: a digit between 0x01-0x06 followed by three bytes of 0x56. That made me suspect this was the code.
I powered up the stereo, entered the code 4, 2, 1, 5, and it unlocked!
It was extremely satisfying to see that my experience in circuit design, as well as practice in online hacking challenges and CTFs actually paid off in real life.