# Lain_Br34kC0r3 V2 | Field | Value | |-------|-------| | Category | IoT | | Difficulty | Hard | | Points | 500 | | Author | Eun0us | | CTF | Espilon 2026 | --- ## Description **Chapter 2 — Core Analysis** After exploring the WIRED-MED therapy module through its UART interface, you successfully dumped the complete flash of the device. This dump contains the bootloader, the partition table, the NVS and the application firmware. Your mission: **reverse engineer the ESP32 firmware** to extract the encryption keys used to protect patient data, then decrypt the flag stored in the NVS partition. *"Close your eyes. Open The Wired. Analyze the core."* - **TX (read):** `nc CHALLENGE_HOST 1111` - **RX (write):** `nc CHALLENGE_HOST 2222` --- ## TL;DR Issue `dump_flash` over the RX UART port to receive a base64-encoded full flash dump on TX. Decode and use `binwalk` to locate the app firmware at offset 0x10000. Run `strings` on the binary to find the AES-256-CBC key (`W1R3D_M3D_TH3R4PY_K3Y_2024_L41N!`) and IV (`L41N_WIRED_IV_01`). Get the encrypted flag via the `encrypted_data` command, then AES-256-CBC decrypt it. --- ## Tools | Tool | Purpose | |------|---------| | `nc` | Split UART connection | | Python 3 | Base64 decode, data parsing | | `binwalk` / `esptool.py` | Parse the flash dump | | `strings` | Extract AES key and IV | | Ghidra (Xtensa) | Full reverse engineering if needed | | `pycryptodome` | AES-256-CBC decryption | --- ## Solution ### Step 1 — Dump the flash ```bash # Terminal 1 — TX (read) nc 1111 | tee flash_output.txt # Terminal 2 — RX (write) echo "dump_flash" | nc 2222 ``` The dump is sent as base64 between markers: ``` === BEGIN FLASH DUMP === === END FLASH DUMP === ``` Decode: ```python import base64 with open("flash_output.txt") as f: lines = f.readlines() b64_data = "" capture = False for line in lines: if "BEGIN FLASH DUMP" in line: capture = True continue if "END FLASH DUMP" in line: break if capture: b64_data += line.strip() flash = base64.b64decode(b64_data) with open("flash_dump.bin", "wb") as f: f.write(flash) ``` > 📸 `[screenshot: TX terminal showing the base64 flash dump streaming out]` ### Step 2 — Identify the flash structure ```bash binwalk flash_dump.bin ``` Expected structure: ``` 0x0000 Padding (0xFF) 0x1000 ESP32 bootloader (magic 0xE9) 0x8000 Partition table 0x9000 NVS partition (24 KiB) 0xF000 PHY init data 0x10000 Application firmware (magic 0xE9) ``` ### Step 3 — Extract and analyze the application firmware ```bash dd if=flash_dump.bin of=app_firmware.bin bs=1 skip=$((0x10000)) strings -n 10 app_firmware.bin | grep -i "key\|aes\|iv\|wired\|therapy" ``` Expected results: ``` W1R3D_M3D_TH3R4PY_K3Y_2024_L41N! # AES-256 key (32 bytes) L41N_WIRED_IV_01 # AES IV (16 bytes) WIRED-MED Therapy Module ``` > 📸 `[screenshot: strings output identifying the AES key and IV]` For full confirmation: open in Ghidra with **Xtensa:LE:32:default** architecture, find `app_main()` → `wired_med_crypto_init()` → `mbedtls_aes_setkey_enc()`. The key and IV are passed as arguments pointing into `.rodata`. ### Step 4 — Get the encrypted flag ciphertext On the RX port: ```text encrypted_data ``` Returns the ciphertext as a hex string on TX. Alternatively, extract from the NVS partition (namespace `wired_med`, key `encrypted_flag`, blob type) using `nvs_tool.py` from ESP-IDF. > 📸 `[screenshot: encrypted_data command returning the hex ciphertext]` ### Step 5 — Decrypt AES-256-CBC ```python from Crypto.Cipher import AES from Crypto.Util.Padding import unpad key = b"W1R3D_M3D_TH3R4PY_K3Y_2024_L41N!" # 32 bytes iv = b"L41N_WIRED_IV_01" # 16 bytes ciphertext = bytes.fromhex("...") # from encrypted_data output cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size) print(plaintext.decode()) # ESPILON{3sp32_fl4sh_dump_r3v3rs3d} ``` > 📸 `[screenshot: Python decryption script printing the flag]` ### Attack chain summary ``` dump_flash → base64 decode → binwalk → extract app @ 0x10000 → strings/Ghidra (Xtensa RE) → find AES key + IV in .rodata → encrypted_data (or NVS parse) → AES-256-CBC decrypt → FLAG ``` --- ## Flag `ESPILON{3sp32_fl4sh_dump_r3v3rs3d}`