Products > Thermal Imaging

Autoliv NV3 unlock

(1/2) > >>

tmbinc:
I know there is the wonderful OpenIRV project, and it's way more impressive than anything I've ever done.

However, given the difficulty in getting parts, it may not be entirely unreasonable to try doing something with the stock hardware (Altera FPGA). Contrary to the NV2 though, the NV3 uses a more complicated physical layer (MAX9259's "Gigabit Multimedia Serial Link" with a ~650 MHz 8B10B signal, including bidirectional communication), and the MAX9260 (deserializer) was pretty hard to get, and there was little chance of implementing it in an FPGA. So I've never really looked at it.

This all changed when somebody sent me a Flash image of the ECU (thanks again, so much!). I was blindly disassembling around when I found an HMAC-MD5 function, the same one that was used for the NV2 authentication (remember, to enable the NV2, you need to do a security challenge; it involves receiving a seed, and responding with a HMAC of that). The key was "obfuscated" with a XOR table, and after un-XORing, I received a warm hello from Johan and Lennie!

I've traced around and, while I couldn't make much sense of the code, I saw that it sends a command of "65" to read a serial number, a command "42" to receive a seed, and "41" to send back the HMAC. From the functions, it looks exactly like the auth protocol on NV2, except it doesn't seem to involve CAN. (Remember, the NV2 camera had a CAN-Link plus the LVDS downstream link; the NV3 only has the LVDS link, but with the ability for low-speed bidirectional communication).

I've guessed around and though that they probably use UART mode (the MAX9259/9260 can tunnel UART and I2C over the LVDS link), and simply injected some characters on pin 36 of the MAX9259 (there's a 50 Ohm resistor conveniently placed so you can override the MAX9259 TX signal). And, after sending a bunch of random data, I received a message on pin 35 at 115200 baud: "70 05 00 00 00 00 66 CB 00 00".

I could send that message back and would get a "70 04 00 00 00 00 CC 9A 00 00 ". Changing any bit gives the "70 05" message, but replaying either of the received messages gives the "70 04" message. 66CB / CC9A seemed to be some kind of CRC so this behavior makes sense: These two messages have a correct CRC, but are likely otherwise invalid (when sent to the camera), so they return 70 05, likely "invalid message structure". Everything else results in 70 04, "invalid CRC". Being a bit creative, I found that Xmodem_CRC16(70 04 00 00 00 00 ) == 0xcc9a. That still didn't explain the trailing "00 00", but allows me to craft other messages that are not rejected for their CRC. Still, most everything got me "70 04". However, by brute-forcing (i.e. sending random data), I finally got some other looking responses whenever I start with "6E". Sending "6e0000650000af200000" for example would return in "700000650008b40f00112fda00112fda06e1", and - behold - I previously identified command "65" as "read serial number". It also shows a bit more structure of the messagees:

bytes 0..3: command
bytes 4..5: length
bytes 6..7: crc16 of the first 6 bytes
bytes 8..n: data
bytes n..n+2: crc(data)

This was promising. By sending "6e0000420000ac760000" (42 - "Read Seed") it would return "70000042001024605dc17d9dd786bebdf1a2e14300112fda704e" (16 bytes of random data! as expected!), and now I could apply the HMAC(key, seed) and send that back with command "41". Doing that with incorrect data returns "ffff" (=failed), but doing it with the right HMAC returns "0001", and the shutter clicks and the camera consumes (a bit) more current! Just as for the NV2!

I still can't receive the pixel data, but I'm sure if I had a MAX9260, it would deserialize it just fine. I could probe one of the higher bit parallel data pins, see a line being transmitted, and if I would put my finger in front of the lens (so creating "left cold, right warm" image) I would see the appropriate digital response on the scope!

In an act second to Icarus, I continued to brute-force commands, and eventually bricked the camera, likely by sending some command that would erase the flash. Meh. (But I have a backup of the flash somwhere.). So be aware!


import serial, crcmod, os, hmac, hashlib

xmodem_crc_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0x0000, xorOut=0x0000)

s = serial.Serial("/dev/ttyUSB0", 115200, timeout=0.01)

def check_crc(buf):
    len = 6
    assert xmodem_crc_func(buf[:len]) == int.from_bytes(buf[len : len + 2], "big")
    datalen = buf[5]
    assert xmodem_crc_func(buf[8 : 8 + datalen]) == int.from_bytes(
        buf[8 + datalen : 8 + datalen + 2], "big"
    )

def cap(x, data):
    assert len(x) == 4
    x += len(data).to_bytes(2, "big")
    return (
        x
        + xmodem_crc_func(x).to_bytes(2, "big")
        + data
        + xmodem_crc_func(data).to_bytes(2, "big")
    )


def cmd(x, data=b""):
    w = cap(x, data)
    check_crc(w)

    s.write(w)
    r = s.read(100)
    check_crc(r)

    if r[:2] == bytes([0x70, 0x4]):
        print(" (CRC wrong)")

    datalen = int.from_bytes(r[4:6], "big")
    return r[:6], r[8 : 8 + datalen]


_, seed = cmd(bytes([0x6E, 0, 0, 0x42]))

key = <you know the key>
res = hmac.new(key, seed, digestmod=hashlib.md5).digest()

a, b = cmd(bytes([0x6E, 0, 0, 0x41]), res)
assert b == bytes([0, 1]), "unlock failed"

railrun:

--- Quote from: tmbinc on March 24, 2023, 09:57:03 pm ---This all changed when somebody sent me a Flash image of the ECU (thanks again, so much!).

--- End quote ---

No problem  ;)
I will try to upload some pictures from the ECU

newex:
Excellent work! How did you connect to communicate with the camera? I can't get any response from the uart MAX 9259.

tmbinc:
MAX9259 has two pins, pin 35 (RX) and pin 36 (TX).

RX is input to MAX9259, so FPGA's UART TX. That signal you can just tap.

TX is output from MAX9259, but there's a series resistor to the FPGA, which means you can conveniently tap it after the resistor (i.e. directly to the FPGA side).

Then it's just a normal UART (I forgot the exact voltage) and the script below should work. If not, scope and see what's happening.

mzg2000:
how to find the key? We know that using data2mem to find the key from microblaze bin code. But to NV3, it is the FPGA from Intel, which tool could be used to do that thing?

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod