- Generated screenshots for all 33 challenges (ESP, Hardware, IoT, OT, Misc, Web3) - Replaced all 123 placeholder lines with actual PNG image references - Cleaned duplicate images from previously partial updates - All write-ups now have full illustrated solutions
3.0 KiB
Executable File
Lain_Br34kC0r3
| Field | Value |
|---|---|
| Category | IoT |
| Difficulty | Medium |
| Points | 500 |
| Author | neverhack |
| CTF | Espilon 2026 |
Description
This challenge emulates a UART interface on a Lain router. Open both connections, interact as if it was real hardware.
- TX: Read only
- RX: Write only
Maybe Lain can help you?
TL;DR
Connect to the split UART interface. Use settings to get the XOR key, dump_bin to get
the obfuscated firmware, de-obfuscate to extract the AES key and IV from .rodata, then
use flag to get the ciphertext and AES-CBC decrypt it to recover the flag.
Tools
| Tool | Purpose |
|---|---|
nc |
Split UART connection |
Python 3 + pycryptodome |
XOR decoding and AES-CBC decryption |
strings / Ghidra |
Static analysis of deobfuscated firmware |
Solution
Step 1 — Connect
# Terminal 1 — TX (read output)
nc <host> 1111
# Terminal 2 — RX (send commands)
nc <host> 2222
Step 2 — List available commands
help
Commands available: help, flag, dump_bin, settings, whoami, show config
Step 3 — Get the XOR key
settings
Returns the XOR key used to obfuscate the firmware dump.
Step 4 — Dump and deobfuscate the firmware
dump_bin
Save the hex output from TX, then deobfuscate:
key = bytes.fromhex("<key_from_settings>")
firmware_enc = bytes.fromhex("<dump_from_dump_bin>")
firmware = bytes(b ^ key[i % len(key)] for i, b in enumerate(firmware_enc))
with open("firmware.bin", "wb") as f:
f.write(firmware)
Step 5 — Extract AES key and IV from firmware
Quick method:
strings -n 10 firmware.bin | grep -iE "key|iv|aes|lain"
Or open in Ghidra with Xtensa architecture, navigate to app_main() → AES setup
functions → locate therapy_aes_key and associated IV in .rodata.
Step 6 — Get the encrypted flag
flag
Returns the ciphertext as a hex string on TX.
Step 7 — Decrypt the flag
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
key = b"<key_from_firmware>" # 16 or 32 bytes
iv = b"<iv_from_firmware>" # 16 bytes
ciphertext = bytes.fromhex("<hex_from_flag_command>")
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
print(plaintext.decode())
Flag
ECW{LAIN_Br34k_CryPT0}



