Blog

Hackeando el CEM de Volvo: Cómo activar el control de crucero y programar mandos sin pasar por el taller

18/01/2026
Volvo
CEM
CAN bus
Flash Memory

Dominando el hardware de Volvo: Del bypass de seguridad en la Flash hasta la inyección de llaves mediante protocolo segmentado D2.

Volvo CEM opened on bench

Volvo P1: Control total sobre el CEM

Si en el post anterior logramos abrir la puerta del CEM extrayendo el PIN de la flash con el Teensy, hoy toca ver qué hay dentro de la habitación. Aquí es donde dejamos de “mirar” y empezamos a “tocar”. En esta entrada vamos a ensuciarnos las manos con lo que realmente hace que este módulo sea el cerebro del coche: la modificación de parámetros, la gestión de la EEPROM y el protocolo de inmovilizador. Aunque “tocar” siempre es mas caro.

💡 Materiales:
  • Carprog
  • Teensy
  • Interfaz OBD
  • VDash
  • VXDiag Nano
  • Drivers CAN bus
  • PC
⚠️ Atención
No me hago responsable de posibles daños en vehículos, centralitas, electrónica u otros componentes derivados de seguir o intentar reproducir los pasos descritos en este post. Manipular la electrónica y el software de un vehículo conlleva riesgos reales. Si no se sabe exactamente qué se está haciendo, es muy fácil provocar fallos graves o irreversibles. Quien continúe, lo hace bajo su propia responsabilidad.

Dos PIN, dos mundos distintos

El CEM (Central Electronic Module) separa claramente dos dominios de memoria y seguridad:

  • La Flash (Configuración): Aquí reside la Car Configuration File (CCF). Contiene los flags que habilitan extras como el control de crucero, tipo de faros o el ordenador de a bordo. Se protege con un PIN de configuración.
  • La EEPROM (Inmovilizador): Aquí se almacenan los datos críticos: IDs de llaves, secretos del mando remoto (RKE) y vectores de sincronización. Se protege con el PIN del inmovilizador.

Esta arquitectura implica que puedes tener acceso para “tunear” el coche, pero no para llevártelo. Son privilegios distintos que requieren ataques distintos.

Activación de extras: tocar flash sin romper nada

Con el PIN de la flash obtenido previamente, el objetivo era modificar la configuración del CEM. En este punto, hay que tener mucho cuidado. No basta con inyectar bytes a lo loco.

La Flash del CEM está protegida por un checksum global. Si modificas un solo bit para activar el control de crucero y no recalculas y corriges el checksum del bloque entero, el CEM detectará la corrupción al arrancar, entrará en Boot Mode y el coche se convertirá en un ladrillo muy caro.

La herramienta adecuada: VDASH

Aunque el Teensy hizo el trabajo de obtener la contraseña, para la escritura utilicé VDASH. Esta herramienta es fundamental porque:

  1. Gestiona la sesión de seguridad con el PIN extraído.
  2. Permite cambiar los flags de configuración de forma visual.
  3. Lo más importante: Recalcula automáticamente el checksum y reestructura la trama de escritura para evitar el brickeo. Silencia el bus can y modifica la flash sin riesgos.

Gracias a este acceso autorizado, activé:

  • Control de crucero: El coche ya tenía la lógica, solo faltaba el “check”.
  • Ordenador de a bordo: Consumo instantáneo, autonomía, etc.
  • Antinieblas delanteros: Habilitación del circuito lógico.

A partir de ahí, el resto es puramente mecánico: montar la botonera en el volante, instalar el mando de luces adecuado y conectar. El hardware “tonto” se conecta, y como el software del CEM ya está parcheado, todo funciona como si hubiera salido así de fábrica.

El otro PIN: inmovilizador y llaves

El PIN del inmovilizador es otro dolor de muelas. No viaja por el CANbus, no responde a latencias y no hay un “brute force” viable vía OBD. La única forma de conseguirlo es leer las EEPROM directamente de la placa.

Aquí surge una limitación técnica de las herramientas: CarProg (y similares) leen muy bien la EEPROM, pero no tocan la flash. Por eso el enfoque fue híbrido: lectura física en banco para obtener el secreto, y programación lógica vía OBD.

El CEM monta dos MCUs (microcontroladores). Hay que abrir la unidad, soldar los cables de lectura y volcar el contenido. De ese dump binario se extrae el PIN que nos autoriza el servicio de Key Programming.

Lectura CEM VOLVO P1

La llave: transponder vs. mando

La llave del Volvo P1 se compone de dos sistemas independientes:

  1. Transponder: Un chip pasivo que autoriza el arranque del motor. Que es un MEGAMOS ID48.
  2. Remote Control (RKE): La placa electrónica que gestiona el cierre centralizado.

En mi caso, el arranque funcionaba correctamente. Ya en el primer post se llevo a cabo esta tarea correctamente. El reto era programar una llave virgen (de AliExpress) para que el cierre centralizado funcionara. El hardware es compatible, pero el CEM no la conoce.

Programar la llave: el protocolo Volvo D2

LLave de volvo p1

Con el PIN de inmovilizador en mano, podemos autenticarnos. Pero escribir la llave no es enviar un comando simple. Volvo utiliza el protocolo D2, y la Seed (semilla criptográfica) de la llave es demasiado larga para caber en una trama CAN estándar.

Aquí es donde entra la segmentación manual. A diferencia de herramientas automáticas que ocultan esto, con el Teensy debemos gestionar nosotros mismos los bytes de control (PCI) para decirle al CEM cómo reconstruir el mensaje.

Anatomía de una escritura segmentada

El primer byte de cada trama CAN dicta el flujo:

  • 0xCF / 0x8F (First Frame): “Oye CEM, prepárate que viene un paquete de datos largo”.
  • 0x09 (Consecutive Frame): “Aquí va un trozo intermedio de datos”.
  • 0x49 (Final Frame): “Este es el último trozo. Cierra el buffer y valida el checksum”.

El código: inyectando la identidad

La secuencia lógica que implementé en C++ para el Teensy sigue este orden estricto (datos anonimizados con 0xXX):

  // 1. Login con PIN de inmovilizador (Servicio 0xA3)
  // Usamos PCI 0xCF para iniciar sesión
  uint8_t login[8] = { 0xCF, 0x40, 0xA3, 0x02, 0X0D, 0xXX, 0xXX, 0xXX };
  canMsgSend(CAN_LS, RAWCAN_BROADCAST_ID, login, RAWCAN_VERBOSE);

  // 2. Escritura de la Seed del mando (Fragmentada en 3 tramas)
  // Trama 1: Inicio (0x8F) - Apuntamos al registro de escritura 0xB8
  uint8_t t1[8] = { 0x8F, 0x40, 0xB8, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
  canMsgSend(CAN_LS, RAWCAN_BROADCAST_ID, t1, RAWCAN_VERBOSE);

  // Trama 2: Continuación (0x09) - Cuerpo de la Seed
  uint8_t t2[8] = { 0x09, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
  canMsgSend(CAN_LS, RAWCAN_BROADCAST_ID, t2, RAWCAN_VERBOSE);

  // Trama 3: Final (0x49) - Cierre y validación
  uint8_t t3[8] = { 0x49, 0xXX, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  canMsgSend(CAN_LS, RAWCAN_BROADCAST_ID, t3, RAWCAN_VERBOSE);

Conclusión: El RELOCK

Tras la inyección, verificamos con una lectura de diagnóstico (0xB9) que el nuevo ID aparece en la lista de llaves aceptadas. Pero cuidado, no hemos terminado.

En este punto, los datos están viviendo en la memoria volátil (RAM) del CEM. Si desconectas la batería o el OBD ahora, perderás la programación. Para que los cambios se guarden de forma permanente en la EEPROM, es obligatorio enviar el comando de RELOCK:

  // 0xCB (Trama simple), 0xA3 0x00 (Comando de cierre/Relock)
  uint8_t relock[8] = { 0xCB, 0x40, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00 };
  canMsgSend(CAN_LS, RAWCAN_BROADCAST_ID, relock, RAWCAN_VERBOSE);

Este comando cierra la sesión de seguridad y fuerza al CEM a hacer el “commit” de los datos a la memoria persistente. Sin esto, la llave nueva es efímera.

Al final, hackear el CEM del Volvo P1 no ha sido cuestión de magia negra ni de fuerza bruta, sino de entender la arquitectura dual del módulo (Flash vs EEPROM) y aprender a hablar el dialecto D2 del bus CAN con la misma fluidez y jerarquía que una herramienta de fábrica.

¿Será este el final de la serie?
O quizá solo sea un capítulo intermedio… 👀

Se rumorea que algunas piezas podrían terminar hablando con pantallas aftermarket, y que los botones que ya conocemos podrían tener sorpresas guardadas.

Lo que está claro es que todavía quedan secretos por explorar, y quien se atreva a seguir leyendo descubrirá que cada byte en el CEM tiene su historia.