TekOnline

Discovery 3 CAN Bus, Part 9: Building Our Own UDS Diagnostic Tool

The Discovery 3 CAN bus journey continues. With the LilyGO TX fix working, the Ford security algorithm cracked, and the RLM diagnostic keys extracted from SDD, it was time to tie everything together into a single tool.

Previously in this series: Part 6 — Reverse Engineering JLR SDD. Part 7 — Cracking the Ford Security Algorithm. Part 8 — Fixing the LilyGO CAN TX Hardware Bug. Now: software to bring it all to life.

We needed a Python tool that could:

  1. Connect to the LilyGO ESP32 serial port
  2. Send ISO-TP (multi-frame CAN) diagnostic messages
  3. Handle UDS (ISO 14229) request/response sessions
  4. Auto-scan for the RLM’s CAN ID across both CAN buses
  5. Unlock security access with the extracted RLM keys
  6. Read and write diagnostic data interactively

So we built uds_rlm.py — now the core of our reverse-engineering toolkit.


Architecture

The tool is organised in three layers, each handling a specific protocol level:

uds_rlm.py
  ├─ LilyGOCAN          — serial to CAN bridge (tx command)
  ├─ ISOTP              — ISO 15765-2 transport (multi-frame)
  └─ UDSClient          — ISO 14229 service layer
       ├─ DiagnosticSessionControl (0x10)
       ├─ SecurityAccess (0x27)
       ├─ ReadDataByIdentifier (0x22)
       ├─ IOControlById (0x2F)
       └─ TesterPresent (0x3E)

The tool communicates with the LilyGO’s custom firmware over serial at 115200 baud. The firmware accepts simple text commands:

tx 740 02 3E 00 AA AA AA AA AA    send 8-byte CAN frame

The UDS layer handles all the protocol complexity: building ISO-TP single and multi-frame messages, managing flow control sequences, handling timeouts, and parsing responses back into structured data.


Key Features

CAN ID Auto-Scanner

Finding the RLM’s diagnostic CAN ID is not trivial. The module uses different IDs depending on the bus speed (HS-CAN at 500 kbps or MS-CAN at 125 kbps) and the addressing scheme (11-bit vs 29-bit). Our scanner tries seven different CAN ID combinations automatically:

DIAGNOSTIC_CAN_IDS = [
    (0x18DA2B33, 0x18DA332B, True,  "29-bit from VERONA config"),
    (0x742,      0x74A,      False, "RLM on MS-CAN 125kbps"),
    (0x740,      0x748,      False, "Common Ford/JLR physical"),
    (0x7E0,      0x7E8,      False, "Standard OBD-II"),
    (0x18DA2BF1, 0x18DAF12B, True,  "Extended diagnostic 29-bit #1"),
    (0x18DA2BF2, 0x18DAF22B, True,  "Extended diagnostic 29-bit #2"),
    (0x18DA2BF3, 0x18DAF32B, True,  "Extended diagnostic 29-bit #3"),
]

For each candidate pair, the scanner sends a TesterPresent (0x3E) and looks for a valid response. Once found, the tool remembers the winning CAN ID and bus configuration for the rest of the session.

Security Auto-Unlock

Most UDS services on the RLM require an extended diagnostic session and a successful security access handshake. Using the keys we extracted from SDD (detailed in Part 7), the tool handles both steps automatically:

# From Security.exml, DC0032
RLM_DIAG_KEY = [0x78, 0x77, 0x68, 0x6B, 0x53]
RLM_PROG_KEY = [0x77, 0x87, 0xA5, 0x86, 0xA3]

The security exchange follows the standard Ford KeyGenMkI challenge-response protocol: the RLM sends a seed, our tool computes the key using the 24-bit LFSR (seeded with 0xC541A9), and returns it to unlock the ECU.

DID Scanner

After unlocking, the tool can scan over 200 Data Identifiers (DIDs) across six ranges, reading live data and configuration values from the RLM:

  • 0x3Bxx — suspension status and height sensor data
  • 0xD1xx — ECU operating parameters
  • 0xF1xx — Ford engineering DIDs (calibration data lives here!)
  • 0xE4xx — calibration and configuration values
  • 0xD9xx — extended diagnostic data
  • 0x02xx — service routine identifiers

Each scan produces a table of DID, value, and response status — invaluable for mapping out the RLM’s diagnostic interface.


Usage

The tool supports two modes: one-shot scanning and interactive shell.

# Full auto-discovery and scan
python uds_rlm.py --port COM23 --scan-all

# Interactive diagnostic shell
python uds_rlm.py --port COM23 --shell
uds> session extended
uds> unlock
uds> read F190
uds> ioctl 3B56 03 01

In shell mode you can walk through diagnostic sessions step by step, read individual DIDs, send IO control commands, and experiment with UDS services in real time — all without touching SDD.


Also Built: J2534 Pass-Thru Proxy DLL

While our Python tool gives us full control, we also needed a way to capture the exact UDS command sequences that SDD sends to the RLM during real calibration procedures. For this, we compiled a J2534 proxy DLL.

When placed inside the SDD virtual machine, this proxy intercepts every PassThruWriteMsgs call — the Windows API that SDD uses to send CAN frames through a J2534 device — and logs the raw CAN frames to C:\j2534_proxy_log.txt. This gives us the precise sequence SDD uses for procedures like air suspension calibration, with no guesswork required.

J2534 Proxy DLL
  SDD.exe → PassThruConnect() → Our Proxy DLL
                                 ├─ Log: C:\j2534_proxy_log.txt
                                 └─ Forward to real J2534 hardware

Combined with the EXML file analysis (which we cover in Part 10), the proxy DLL provides the ground truth we need to validate our understanding of the RLM’s diagnostic protocol.


What’s Next

With the UDS tool working and the J2534 proxy capturing real SDD sessions, the next step is to decode the EXML configuration files that define diagnostic routines, data identifiers, and calibration parameters. Part 10 covers what we found inside those files — including a Triple DES encryption layer that protects the calibration data, and our approach to cracking it.

Continue reading: Part 10 — EXML Files, Triple DES Encryption, and the Complete RLM Diagnostic Data Map.


Disclaimer: The information in this article is provided for educational and research purposes. Modifying vehicle ECU firmware or calibration data can affect safety, emissions compliance, and vehicle warranty. All testing was performed on a bench ECU, not a road-registered vehicle. Proceed at your own risk and consult a qualified automotive technician before making any changes to your vehicle.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *