User Space Diagnostics Challenge

User Space Diagnostics Challenge

These challenges are driven over UDS on vcan0 using python-can and the can-isotp library. The ECU answers on arbitration ID 0x7E8 for requests sent to 0x7E0.

Read Data By Identifier (75 points)


Routine Control (100 points)


Security Access Level 1 (150 points)


Read Memory By Address (150 points)

Can you dump the ECU’s memory and find the hidden flag?
Service 0x23 (Read Memory By Address) reads raw memory once you are unlocked. The flag lives somewhere in the readable region between 0x400000 and 0x500000.

Walkthrough

  1. Open an ISO-TP/UDS session to the ECU (requests on 0x7E0, responses on 0x7E8).
  2. Unlock Security Access first - this region is only readable after the seed/key exchange. Send the known level 1 key 0x20202020 (four spaces) using the send-key sub-function 0x27 0x02.
  3. Read the memory with Read Memory By Address (service 0x23). Use Address and Length Format Identifier 0x44, which declares a 4-byte memory address followed by a 4-byte size, then supply the start address and the number of bytes to read.
  4. Sweep the readable region from 0x400000 to 0x500000 in 0x400-byte chunks, advancing the address each request and collecting every response into a single buffer.
  5. Save the collected bytes to a file and search it for the flag{...} marker (for example with strings firmware.bin | grep -i flag).
ANSWER
TODO
Unlock first, then sweep 0x4000000x500000 with service 0x23 and grep the dump for flag{...}.

Security Access Level 3 (250 points)


Security Access Level 5 (1000 points)

The level 5 seed looks random - can you predict the next one?
The seed is not as random as it looks. 624 observed outputs is a magic number for a reason - it is exactly the internal state size of a Mersenne Twister (MT19937).

Walkthrough

  1. Request the level 5 seed with the request-seed sub-function 0x27 0x05 and inspect the values. The seed is produced by a Mersenne Twister (MT19937) PRNG, which is fully predictable once enough of its output is observed.
  2. Because MT19937 holds 624 32-bit words of internal state, collect 624 consecutive seeds by repeatedly requesting the level 5 seed.
  3. “Untemper” each observed output to reverse the four tempering operations MT19937 applies, recovering the generator’s internal state.
  4. Reproduce the generator from the recovered state and compute the next 32-bit output - the value the ECU will use for the next seed/key check.
  5. Submit that predicted value as the key with the send-key sub-function 0x27 0x06. A positive 0x67 0x06 response confirms level 5 is unlocked.
ANSWER
TODO
A predictable PRNG is not a secret. Recover the MT19937 state from 624 seeds, predict the next output, and send it back as the key.

Custom Firmware (1000 points)

Can you flash your own firmware and gain code execution?
If you can upload code, you can run code. The uploaded image runs in user space, so the smallest useful payload is a reverse shell.

Walkthrough

  1. The challenge accepts an arbitrary firmware image over the UDS download services and then executes it. Because the image runs in user space, a small reverse shell is enough - a program that connects back to 127.0.0.1:9999, redirects standard input/output/error to that socket, and execs /bin/sh.
  2. Compile the payload and append an MD5 checksum of the binary to the end of the image; the loader validates the upload with MD5.
  3. Begin the upload with Request Download (service 0x34), declaring the target address and the total image size (Address and Length Format Identifier 0x44 for a 4-byte address and 4-byte size).
  4. Stream the image with Transfer Data (service 0x36) in 0x700-byte blocks, incrementing the block counter on each request until the whole image (binary plus checksum) has been sent.
  5. Start a listener on port 9999 first, then run the uploaded firmware with Routine Control - start routine (0x31 0x01) on routine ID 0xA5A5.
  6. Catch the incoming shell on your listener and read the flag from the ECU’s filesystem.
ANSWER
TODO
Upload a reverse shell as firmware, start it with Routine Control 0xA5A5, catch the connection on port 9999, and read the flag.

Proving Grounds - Course Completion 60%
Last updated on