diff --git a/ESP/ESP_Start/README.md b/ESP/ESP_Start/README.md index 0de6a2c..37cf2b0 100644 --- a/ESP/ESP_Start/README.md +++ b/ESP/ESP_Start/README.md @@ -60,7 +60,7 @@ On Linux, add your user to the `dialout` group first if you get a permission err sudo usermod -a -G dialout $USER ``` -> ðŸ“ļ `[screenshot: esptool.py flashing — progress bar reaching 100%]` +![esptool.py flashing — progress bar reaching 100%](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/esptool_flash.png) ### Step 2 — Connect to the UART console @@ -82,7 +82,7 @@ Encrypted flag: 09 12 19 07 00 0E 07 35 3F 35 7D 3C 38 1E 3D 26 7F 1E 3E 7F 3E 7 XOR Key: 4C 41 49 4E ``` -> ðŸ“ļ `[screenshot: serial terminal showing the encrypted flag and XOR key on boot]` +![serial terminal showing the encrypted flag and XOR key on boot](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/esp_start_uart.png) ### Step 3 — Identify the XOR key @@ -114,7 +114,7 @@ print(flag.decode()) Output: `ESPILON{st4rt_th3_w1r3}` -> ðŸ“ļ `[screenshot: Python decryption script running and printing the flag]` +![Python decryption script running and printing the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/esp_start_decrypt.png) ### Key concepts diff --git a/ESP/Jnouner_Router/README.md b/ESP/Jnouner_Router/README.md index de47c90..a64c859 100644 --- a/ESP/Jnouner_Router/README.md +++ b/ESP/Jnouner_Router/README.md @@ -75,12 +75,11 @@ Open the UART console: screen /dev/ttyUSB0 115200 ``` -> ðŸ“ļ `[screenshot: UART console showing jnoun-console> prompt]` +![UART console showing jnoun-console> prompt](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jnouned_console.png) --- ### Flag 1 — Console Access -![UART admin console authentication](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jnouned_uart.png) (100 pts) The UART console presents a `jnoun-console>` prompt requiring a password. @@ -101,12 +100,11 @@ admin_login jnoun-admin-2022 Flag 1 is printed on success. -> ðŸ“ļ `[screenshot: successful admin_login command printing Flag 1]` +![successful admin_login command printing Flag 1](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jnouned_login.png) --- ### Flag 2 — 802.11 TX -![802.11 frame capture with flag payload](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jnouned_wifi.png) (200 pts) From the admin console, read device settings: @@ -138,7 +136,8 @@ tshark -i wlan0mon -w capture.pcap Among the random noise frames, one frame emitted at a random time (5–85 seconds) contains Flag 2 as cleartext in its 802.11 data payload. -> ðŸ“ļ `[screenshot: Wireshark frame showing Flag 2 in the payload field]` + +![Wireshark frame showing Flag 2 in the payload field](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jnouned_wifi.png) --- @@ -163,7 +162,7 @@ Decoded: `target=x; flag` Flag 3 prints to the UART console via `ESP_LOGE`. -> ðŸ“ļ `[screenshot: UART console showing Flag 3 output after injection]` +![UART console showing Flag 3 output after injection](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jnouned_flag3.png) --- @@ -228,7 +227,7 @@ for block_id in range(10): print(flag.decode()) ``` -> ðŸ“ļ `[screenshot: Python JMP client printing the final flag after block reassembly]` +![Python JMP client printing the final flag after block reassembly](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jnouned_jmp.png) --- diff --git a/ESP/Phantom_Byte/README.md b/ESP/Phantom_Byte/README.md index c96361e..76c8c4f 100644 --- a/ESP/Phantom_Byte/README.md +++ b/ESP/Phantom_Byte/README.md @@ -86,7 +86,7 @@ echo "RVNQSU9Me3U0cnRfczMzc180bGx9" | base64 -d # ESPILON{u4rt_s33s_4ll} ``` -> ðŸ“ļ `[screenshot: UART terminal showing the base64 diagnostic line on boot]` +![UART terminal showing the base64 diagnostic line on boot](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/phantom_uart.png) Submit over TCP: @@ -122,7 +122,7 @@ ph> wire >> ESPILON{h1dd3n_c0nf1g} ``` -> ðŸ“ļ `[screenshot: wire command revealing the hidden config cache contents]` +![wire command revealing the hidden config cache contents](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/phantom_wire.png) Submit: @@ -168,7 +168,7 @@ The trace output shows each out-of-bounds byte read from the adjacent `config_ca Convert the oob bytes to ASCII: `ESPILON{ph4nt0m_byt3_h34p_l34k}` -> ðŸ“ļ `[screenshot: trace output showing oob bytes reading the flag from heap]` +![trace output showing oob bytes reading the flag from heap](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/phantom_trace.png) --- @@ -200,7 +200,7 @@ are read from the adjacent flag buffer. Reconstruct: `ESPILON{bl1nd_str4ddl3}` -> ðŸ“ļ `[screenshot: inject command returning TS values that decode to flag bytes]` +![inject command returning TS values that decode to flag bytes](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/phantom_inject.png) Automated solver: diff --git a/Hardware/CAN_Bus_Implant/README.md b/Hardware/CAN_Bus_Implant/README.md index 63f9617..c10cfe8 100644 --- a/Hardware/CAN_Bus_Implant/README.md +++ b/Hardware/CAN_Bus_Implant/README.md @@ -57,7 +57,7 @@ nc 3600 nc 3601 ``` -> ðŸ“ļ `[screenshot: two terminal windows showing sniff output and inject prompt]` +![two terminal windows showing sniff output and inject prompt](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/can_terminals.png) ### Step 2 — Observe the traffic @@ -72,7 +72,7 @@ Watch the sniff port. The following patterns emerge: The `0x7E0`/`0x7E8` pair is the UDS diagnostic channel. -> ðŸ“ļ `[screenshot: sniff output showing the 0x7E0/0x7E8 request/response pattern]` +![sniff output showing the 0x7E0/0x7E8 request/response pattern](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/can_sniff.png) ### Step 3 — Enter extended diagnostic session @@ -94,7 +94,7 @@ send 7E0 02 27 01 00 00 00 00 00 The response contains a 4-byte seed: `67 01 XX XX XX XX` -> ðŸ“ļ `[screenshot: seed bytes visible in the 0x7E8 response]` +![seed bytes visible in the 0x7E8 response](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/can_seed.png) ### Step 5 — Compute the key and authenticate @@ -123,7 +123,7 @@ send 7E0 03 22 FF 01 00 00 00 00 The response on `0x7E8` contains the flag. -> ðŸ“ļ `[screenshot: 0x7E8 response containing the flag bytes after successful security access]` +![0x7E8 response containing the flag bytes after successful security access](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/can_flag.png) ### Key concepts diff --git a/Hardware/Glitch_The_Wired/README.md b/Hardware/Glitch_The_Wired/README.md index fa0e2b0..52e5468 100644 --- a/Hardware/Glitch_The_Wired/README.md +++ b/Hardware/Glitch_The_Wired/README.md @@ -48,7 +48,7 @@ arm and trigger, then read the maintenance token from the unlocked debug console nc 3700 ``` -> ðŸ“ļ `[screenshot: glitch lab banner and prompt]` +![glitch lab banner and prompt](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/glitch_banner.png) ### Step 2 — Observe the boot sequence @@ -68,7 +68,7 @@ LAUNCH_KERNEL [3400 – 5000] The signature verification phase runs between cycles 3200 and 3400. -> ðŸ“ļ `[screenshot: observe output showing all boot phases and cycle ranges]` +![observe output showing all boot phases and cycle ranges](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/glitch_observe.png) ### Step 3 — Configure glitch parameters @@ -101,7 +101,7 @@ LAUNCH_KERNEL ......... OK [DEBUG SHELL ACTIVATED] ``` -> ðŸ“ļ `[screenshot: boot log showing SIG_VERIFY SKIPPED and debug shell prompt]` +![boot log showing SIG_VERIFY SKIPPED and debug shell prompt](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/glitch_unlock.png) ### Step 5 — Read the maintenance token @@ -111,7 +111,7 @@ read_console The debug console outputs the maintenance token containing the flag. -> ðŸ“ļ `[screenshot: read_console output displaying the flag]` +![read_console output displaying the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/glitch_flag.png) ### Key concepts diff --git a/Hardware/NAVI_I2C_Sniff/README.md b/Hardware/NAVI_I2C_Sniff/README.md index 43e7c8a..c8dd9cc 100644 --- a/Hardware/NAVI_I2C_Sniff/README.md +++ b/Hardware/NAVI_I2C_Sniff/README.md @@ -50,7 +50,7 @@ Use the key to decrypt the EEPROM contents and recover the flag. nc 3300 ``` -> ðŸ“ļ `[screenshot: I2C bus interface prompt]` +![I2C bus interface prompt](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/i2c_prompt.png) ### Step 2 — Scan the bus @@ -66,7 +66,7 @@ I2C Address 0x48 [Temperature Sensor] I2C Address 0x60 [Crypto IC] ``` -> ðŸ“ļ `[screenshot: scan output listing three I2C devices]` +![scan output listing three I2C devices](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/i2c_scan.png) ### Step 3 — Read the temperature sensor's hidden register @@ -108,7 +108,7 @@ read 0x60 0x10 32 Now returns the actual 32-byte key: `NAVI_WIRED_I2C_CRYPTO_KEY_2024!!` -> ðŸ“ļ `[screenshot: crypto IC returning the key after unlock]` +![crypto IC returning the key after unlock](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/i2c_key.png) ### Step 7 — Read the EEPROM @@ -128,7 +128,7 @@ flag = bytes(b ^ key[i % len(key)] for i, b in enumerate(enc)) print(flag.rstrip(b'\x00').decode()) ``` -> ðŸ“ļ `[screenshot: Python decryption script printing the flag]` +![Python decryption script printing the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/i2c_decrypt.png) ### Key concepts diff --git a/Hardware/Phantom_JTAG/README.md b/Hardware/Phantom_JTAG/README.md index a21ce54..3cac49c 100644 --- a/Hardware/Phantom_JTAG/README.md +++ b/Hardware/Phantom_JTAG/README.md @@ -51,7 +51,7 @@ reassemble the flag. nc 3400 ``` -> ðŸ“ļ `[screenshot: JTAG port banner showing TAP controller information]` +![JTAG port banner showing TAP controller information](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jtag_banner.png) ### Step 2 — Reset the TAP controller @@ -72,7 +72,7 @@ dr 00000000 32 Returns `0x4BA00477` — an ARM Cortex-M style IDCODE. -> ðŸ“ļ `[screenshot: IDCODE read returning 0x4BA00477]` +![IDCODE read returning 0x4BA00477](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jtag_idcode.png) ### Step 4 — Unlock the debug interface @@ -91,7 +91,7 @@ state Output should now show: `Debug: UNLOCKED` -> ðŸ“ļ `[screenshot: state command showing Debug: UNLOCKED]` +![state command showing Debug: UNLOCKED](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jtag_unlock.png) ### Step 5 — Load the memory read instruction @@ -113,7 +113,7 @@ Repeat for addresses 0x1004, 0x1008, etc. until the flag is complete. Convert each little-endian 32-bit word to 4 ASCII bytes and concatenate. -> ðŸ“ļ `[screenshot: dr reads returning flag bytes as 32-bit little-endian words]` +![dr reads returning flag bytes as 32-bit little-endian words](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/jtag_mem_read.png) ### Key concepts diff --git a/Hardware/Serial_Experimental_00/README.md b/Hardware/Serial_Experimental_00/README.md index a9cef55..876b030 100644 --- a/Hardware/Serial_Experimental_00/README.md +++ b/Hardware/Serial_Experimental_00/README.md @@ -53,7 +53,7 @@ nc 1111 nc 2222 ``` -> ðŸ“ļ `[screenshot: two terminals open, TX showing boot messages and RX ready for input]` +![two terminals open, TX showing boot messages and RX ready for input](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/serial_exp_terminals.png) ### Step 2 — Query the diagnostic commands @@ -103,7 +103,7 @@ frag_c_hex=3030 Decode: `bytes.fromhex("3030").decode()` → `00` -> ðŸ“ļ `[screenshot: TX output showing all three fragment values from diagnostics]` +![TX output showing all three fragment values from diagnostics](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/serial_exp_diag.png) ### Step 4 — Build the maintenance token @@ -123,7 +123,7 @@ unlock LAIN-SERIAL-00 The flag is returned on the TX terminal. -> ðŸ“ļ `[screenshot: TX terminal printing the flag after successful unlock]` +![TX terminal printing the flag after successful unlock](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/serial_exp_flag.png) ### Key concepts diff --git a/Hardware/Signal_Tap_Lain/README.md b/Hardware/Signal_Tap_Lain/README.md index e2215e2..7749b0f 100644 --- a/Hardware/Signal_Tap_Lain/README.md +++ b/Hardware/Signal_Tap_Lain/README.md @@ -69,7 +69,7 @@ Channels: 3 Sample rate: 1 MHz ``` -> ðŸ“ļ `[screenshot: info command output listing the three channels]` +![info command output listing the three channels](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/signal_tap_info.png) ### Step 3 — Analyze channel 1 @@ -90,7 +90,7 @@ Baud rate = 1 / 0.00010417 ≈ 9600 baud A 10-bit UART frame (1 start + 8 data + 1 stop) = ~1041.67 Ξs. -> ðŸ“ļ `[screenshot: Python script measuring bit periods from ch1 transitions]` +![Python script measuring bit periods from ch1 transitions](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/signal_tap_measure.png) ### Step 5 — Decode UART 8N1 @@ -133,7 +133,7 @@ print("".join(chars)) The decoded message contains the flag repeated three times. -> ðŸ“ļ `[screenshot: decoded UART output showing the flag repeated]` +![decoded UART output showing the flag repeated](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/signal_tap_decode.png) ### Key concepts diff --git a/Hardware/Wired_SPI_Exfil/README.md b/Hardware/Wired_SPI_Exfil/README.md index 7f0db2f..ec17d88 100644 --- a/Hardware/Wired_SPI_Exfil/README.md +++ b/Hardware/Wired_SPI_Exfil/README.md @@ -55,7 +55,7 @@ nc 3500 cs 0 ``` -> ðŸ“ļ `[screenshot: SPI probe interface ready with CS asserted]` +![SPI probe interface ready with CS asserted](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/spi_probe.png) ### Step 2 — Read the chip ID @@ -79,7 +79,7 @@ tx 5A 00 00 00 00 The SFDP header shows 2 parameter tables. The first is the standard JEDEC table; the second is a vendor-specific table at offset 0x80. -> ðŸ“ļ `[screenshot: SFDP header output showing two parameter table entries]` +![SFDP header output showing two parameter table entries](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/spi_sfdp.png) ### Step 4 — Read the vendor SFDP table @@ -97,7 +97,7 @@ Size: 4096 bytes This partition does not appear in the normal partition table. -> ðŸ“ļ `[screenshot: vendor SFDP data revealing hidden partition at 0x030000]` +![vendor SFDP data revealing hidden partition at 0x030000](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/spi_vendor.png) ### Step 5 — Read the hidden partition @@ -122,7 +122,7 @@ flag = bytes(b ^ key[i % len(key)] for i, b in enumerate(encrypted)) print(flag.rstrip(b'\x00').decode()) ``` -> ðŸ“ļ `[screenshot: Python decryption script printing the recovered flag]` +![Python decryption script printing the recovered flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/spi_decrypt_flag.png) ### Key concepts diff --git a/Intro/The_Wired/README.md b/Intro/The_Wired/README.md index eef1643..19c684d 100644 --- a/Intro/The_Wired/README.md +++ b/Intro/The_Wired/README.md @@ -79,7 +79,7 @@ Directories present: `notes/`, `comms/`, `dumps/`, `logs/`, `tools/`, `journal/` confirms the key `Xt9Lm2Qw7KjP4rNvB8hYc3fZ0dAeU6sG` is planted bait - `tools/devices.json` — lists all known device IDs with roles -> ðŸ“ļ `[screenshot: notes/protocol.txt showing the frame format]` +![notes/protocol.txt showing the frame format](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/thewired_protocol.png) ### Step 2 — Identify the target device @@ -94,7 +94,7 @@ Status: quarantine Regular devices receive a `heartbeat` response. Only `ce4f626b` triggers the flag path. -> ðŸ“ļ `[screenshot: devices.json showing the Eiri_Master entry with root-coordinator role]` +![devices.json showing the Eiri_Master entry with root-coordinator role](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/thewired_devices.png) ### Step 3 — Understand the handshake @@ -117,7 +117,7 @@ strings dumps/7f3c9a12/bot-lwip.elf | grep -E '^[A-Za-z0-9]{12}$' Do **not** use the key found in `notes/hardening.txt` — it is a honeypot. -> ðŸ“ļ `[screenshot: strings output showing the real 32-character key]` +![strings output showing the real 32-character key](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/thewired_strings.png) ### Step 5 — Send the two-message handshake @@ -184,7 +184,7 @@ Command { } ``` -> ðŸ“ļ `[screenshot: solver output showing the decrypted flag response]` +![solver output showing the decrypted flag response](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/thewired_solver.png) ### Things that will get you silently dropped diff --git a/IoT/Anesthesia_Gateway/README.md b/IoT/Anesthesia_Gateway/README.md index 06e58b8..9a62ffa 100644 --- a/IoT/Anesthesia_Gateway/README.md +++ b/IoT/Anesthesia_Gateway/README.md @@ -45,7 +45,6 @@ publishing a base64-encoded blob every 45 seconds. Reverse the encoding chain --- ## Solution -![MQTT subscribe capturing all topics including admin/config](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_sub.png) ### Step 1 — Connect and discover topics @@ -54,7 +53,7 @@ publishing a base64-encoded blob every 45 seconds. Reverse the encoding chain mosquitto_sub -h -t "sainte-mika/#" -v ``` -> ðŸ“ļ `[screenshot: mosquitto_sub output listing all discovered topics and their messages]` +![mosquitto_sub output listing all discovered topics and their messages](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_topics.png) Topics discovered: @@ -73,7 +72,7 @@ Wait for a message on `debug/firmware` (up to 45 seconds). Save the base64 strin Note the `"network": "WIRED-MED"` in the alarms topic — this is the XOR key hint. -> ðŸ“ļ `[screenshot: debug/firmware topic publishing the base64-encoded blob]` +![debug/firmware topic publishing the base64-encoded blob](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_firmware.png) ### Step 3 — Reverse the encoding chain @@ -102,7 +101,7 @@ config = json.loads(decompressed.decode()) print(config) ``` -> ðŸ“ļ `[screenshot: Python script printing the decoded JSON configuration]` +![Python script printing the decoded JSON configuration](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_config_json.png) ### Step 4 — Extract the maintenance key @@ -128,7 +127,7 @@ Subscribe to the flag topic: mosquitto_sub -h -t "sainte-mika/or13/maintenance/flag" ``` -> ðŸ“ļ `[screenshot: flag topic publishing the ESPILON flag after unlock]` +![flag topic publishing the ESPILON flag after unlock](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/mqtt_flag.png) ### Key insights diff --git a/IoT/Cr4cK_w1f1/README.md b/IoT/Cr4cK_w1f1/README.md index fa1e02b..0d26367 100644 --- a/IoT/Cr4cK_w1f1/README.md +++ b/IoT/Cr4cK_w1f1/README.md @@ -54,7 +54,7 @@ nc 1111 nc 2222 ``` -> ðŸ“ļ `[screenshot: two terminals showing TX output and RX prompt]` +![two terminals showing TX output and RX prompt](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/wifi_terminals.png) ### Step 2 — Start the sniffer and force a deauth @@ -84,7 +84,7 @@ Copy the base64 lines to a file and decode: base64 -d handshake.b64 > handshake.pcap ``` -> ðŸ“ļ `[screenshot: TX output showing the PCAP_BASE64 markers]` +![TX output showing the PCAP_BASE64 markers](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/wifi_pcap.png) ### Step 4 — Crack the WPA2 handshake @@ -98,7 +98,7 @@ Output: KEY FOUND! [ sunshine ] ``` -> ðŸ“ļ `[screenshot: aircrack-ng finding the key]` +![aircrack-ng finding the key](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/wifi_aircrack.png) ### Step 5 — Connect and read the flag @@ -109,7 +109,7 @@ connect TestNet sunshine cat /flag.txt ``` -> ðŸ“ļ `[screenshot: RX terminal returning the flag after connecting to the network]` +![RX terminal returning the flag after connecting to the network](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/wifi_flag_rx.png) --- diff --git a/IoT/Lain_Br34kC0r3/README.md b/IoT/Lain_Br34kC0r3/README.md index 7e53e1f..95d98ce 100755 --- a/IoT/Lain_Br34kC0r3/README.md +++ b/IoT/Lain_Br34kC0r3/README.md @@ -52,7 +52,7 @@ nc 1111 nc 2222 ``` -> ðŸ“ļ `[screenshot: both terminals open, TX showing the device banner]` +![both terminals open, TX showing the device banner](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/lain_terminals.png) ### Step 2 — List available commands @@ -70,7 +70,7 @@ settings Returns the XOR key used to obfuscate the firmware dump. -> ðŸ“ļ `[screenshot: settings command returning the XOR key]` +![settings command returning the XOR key](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/lain_xor_key.png) ### Step 4 — Dump and deobfuscate the firmware @@ -99,7 +99,7 @@ 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`. -> ðŸ“ļ `[screenshot: strings output showing the AES key and IV]` +![strings output showing the AES key and IV](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/lain_strings.png) ### Step 6 — Get the encrypted flag @@ -124,7 +124,7 @@ plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size) print(plaintext.decode()) ``` -> ðŸ“ļ `[screenshot: Python script printing the decrypted flag]` +![Python script printing the decrypted flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/lain_decrypt.png) --- diff --git a/IoT/Lain_Br34kC0r3_V2/README.md b/IoT/Lain_Br34kC0r3_V2/README.md index 808c152..f4bf092 100644 --- a/IoT/Lain_Br34kC0r3_V2/README.md +++ b/IoT/Lain_Br34kC0r3_V2/README.md @@ -94,7 +94,7 @@ with open("flash_dump.bin", "wb") as f: f.write(flash) ``` -> ðŸ“ļ `[screenshot: TX terminal showing the base64 flash dump streaming out]` +![TX terminal showing the base64 flash dump streaming out](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/lain_v2_dump.png) ### Step 2 — Identify the flash structure @@ -128,7 +128,7 @@ L41N_WIRED_IV_01 # AES IV (16 bytes) WIRED-MED Therapy Module ``` -> ðŸ“ļ `[screenshot: strings output identifying the AES key and IV]` +![strings output identifying the AES key and IV](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/lain_v2_strings.png) For full confirmation: open in Ghidra with **Xtensa:LE:32:default** architecture, find `app_main()` → `wired_med_crypto_init()` → `mbedtls_aes_setkey_enc()`. The @@ -146,7 +146,7 @@ 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]` +![encrypted_data command returning the hex ciphertext](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/lain_v2_enc_data.png) ### Step 5 — Decrypt AES-256-CBC @@ -165,7 +165,7 @@ print(plaintext.decode()) # ESPILON{3sp32_fl4sh_dump_r3v3rs3d} ``` -> ðŸ“ļ `[screenshot: Python decryption script printing the flag]` +![Python decryption script printing the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/lain_v2_decrypt.png) ### Attack chain summary diff --git a/IoT/Lain_VS_Knights/README.md b/IoT/Lain_VS_Knights/README.md index 090ee51..f432b39 100755 --- a/IoT/Lain_VS_Knights/README.md +++ b/IoT/Lain_VS_Knights/README.md @@ -90,7 +90,7 @@ def scan_nodes(host, tx_port=1111, rx_port=2222, node_min=1, node_max=1200): Example result: Knights at nodes 0067, 0113, 0391, 0529, 0619, 0901, 0906. Founder at 0311. -> ðŸ“ļ `[screenshot: scanner output listing discovered Knight and Founder node IDs]` +![scanner output listing discovered Knight and Founder node IDs](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/knights_scan.png) ### Step 2 — Get the assembly order from Lain nodes @@ -173,7 +173,7 @@ node.inject 2 0x08 # fragment fault_injection=2_08 ``` -> ðŸ“ļ `[screenshot: each Knight node returning its fragment after successful puzzle]` +![each Knight node returning its fragment after successful puzzle](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/knights_fragments.png) ### Step 4 — Verify fragment collection @@ -220,7 +220,7 @@ node.flag # ESPILON{0nlY_L41N_C4N_S0lv3} ``` -> ðŸ“ļ `[screenshot: Founder node accepting the exploit and printing the flag]` +![Founder node accepting the exploit and printing the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/knights_exploit.png) --- diff --git a/IoT/Lets_All_Hate_UART/README.md b/IoT/Lets_All_Hate_UART/README.md index 89d6fe8..52f5790 100644 --- a/IoT/Lets_All_Hate_UART/README.md +++ b/IoT/Lets_All_Hate_UART/README.md @@ -57,7 +57,7 @@ nc 2222 Read the ESP32 boot sequence on TX carefully — it contains hints. -> ðŸ“ļ `[screenshot: TX terminal showing ESP32 boot sequence with diagnostic messages]` +![TX terminal showing ESP32 boot sequence with diagnostic messages](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/hate_uart_boot.png) ### Step 2 — Discover hidden commands @@ -98,7 +98,7 @@ base64.b64decode("dGgzcmFweV9tMGR1bGU9") # b'th3rapy_m0dule=' ``` -> ðŸ“ļ `[screenshot: mem read output showing base64 token in ASCII column]` +![mem read output showing base64 token in ASCII column](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/hate_uart_mem.png) ### Step 4 — Authenticate as debug user @@ -126,7 +126,7 @@ nvs read crypto_flag Returns a hexdump of the XOR-encrypted flag blob. -> ðŸ“ļ `[screenshot: nvs read showing the encrypted flag hexdump]` +![nvs read showing the encrypted flag hexdump](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/hate_uart_nvs.png) ### Step 6 — Decrypt with XOR key WIRED @@ -141,7 +141,7 @@ print(flag.decode()) # ESPILON{u4rt_nvs_fl4sh_d1sc0v3ry} ``` -> ðŸ“ļ `[screenshot: Python decryption script printing the flag]` +![Python decryption script printing the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/hate_uart_decrypt.png) --- diff --git a/IoT/Lets_All_Love_UART/README.md b/IoT/Lets_All_Love_UART/README.md index 50e8c3c..ec49e77 100755 --- a/IoT/Lets_All_Love_UART/README.md +++ b/IoT/Lets_All_Love_UART/README.md @@ -50,7 +50,7 @@ nc 1111 nc 2222 ``` -> ðŸ“ļ `[screenshot: two terminal windows open, TX showing the device banner]` +![two terminal windows open, TX showing the device banner](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/love_uart_terminals.png) ### Step 2 — Request the flag @@ -68,7 +68,7 @@ In Terminal 1 (TX): ESPILON{LAIN_TrUsT_U4RT} ``` -> ðŸ“ļ `[screenshot: TX terminal printing the flag immediately after the flag command is sent]` +![TX terminal printing the flag immediately after the flag command is sent](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/love_uart_flag.png) ### Automated solver diff --git a/IoT/Nurse_Call/README.md b/IoT/Nurse_Call/README.md index 3fa28e3..11df606 100644 --- a/IoT/Nurse_Call/README.md +++ b/IoT/Nurse_Call/README.md @@ -50,7 +50,7 @@ to wake the module and receive the flag. nc 1337 ``` -> ðŸ“ļ `[screenshot: maintenance terminal with open session from the previous technician]` +![maintenance terminal with open session from the previous technician](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/nurse_maint.png) ### Step 2 — Read the call log @@ -64,7 +64,7 @@ The log shows repeated phantom calls from Room 013. The last line: [ALERT] Room 013 — unknown payload: 0x4c41494e ``` -> ðŸ“ļ `[screenshot: appels.log showing the phantom call with hex payload]` +![appels.log showing the phantom call with hex payload](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/nurse_log.png) ### Step 3 — Decode the payload @@ -104,7 +104,7 @@ Shows exact syntax: `reveil.sh --id ` ./tools/reveil.sh --id LAIN ``` -> ðŸ“ļ `[screenshot: reveil.sh printing the flag after receiving the LAIN module ID]` +![reveil.sh printing the flag after receiving the LAIN module ID](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/nurse_flag.png) --- diff --git a/IoT/Observe_The_Wired/README.md b/IoT/Observe_The_Wired/README.md index 123fb54..95ca348 100644 --- a/IoT/Observe_The_Wired/README.md +++ b/IoT/Observe_The_Wired/README.md @@ -60,7 +60,7 @@ Returns a comma-separated list of resource links (RFC 6690 format): ``` -> ðŸ“ļ `[screenshot: .well-known/core response listing all CoAP resources]` +![.well-known/core response listing all CoAP resources](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/coap_wellknown.png) ### Step 2 — Get fragment A @@ -92,7 +92,7 @@ Among the periodic notifications, one JSON payload contains: {"fragment_c": "23", "node": "013"} ``` -> ðŸ“ļ `[screenshot: observable stream notification containing fragment_c value]` +![observable stream notification containing fragment_c value](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/coap_observe.png) ### Step 5 — Build the XOR key @@ -135,7 +135,7 @@ print(config["maintenance_key"]) # 0BS3RV3-L41N-23 ``` -> ðŸ“ļ `[screenshot: Python script printing the maintenance key from the decoded firmware blob]` +![Python script printing the maintenance key from the decoded firmware blob](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/coap_firmware_key.png) ### Step 7 — Unlock and get the flag @@ -145,7 +145,7 @@ coap-client -m post -e "0BS3RV3-L41N-23" coap:///maintenance/unlock The response contains the flag. -> ðŸ“ļ `[screenshot: CoAP POST response returning the flag]` +![CoAP POST response returning the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/coap_flag.png) --- diff --git a/IoT/Wired_Airwave_013/README.md b/IoT/Wired_Airwave_013/README.md index 8a3a489..3610b9b 100644 --- a/IoT/Wired_Airwave_013/README.md +++ b/IoT/Wired_Airwave_013/README.md @@ -63,7 +63,7 @@ IQ stream — int8 interleaved, samplerate=200000, encoding=2-FSK After the banner, raw binary IQ data follows. Save after the newline. -> ðŸ“ļ `[screenshot: nc output showing the IQ stream banner before binary data]` +![nc output showing the IQ stream banner before binary data](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/airwave_nc.png) ### Step 2 — Demodulate the 2-FSK signal @@ -93,7 +93,7 @@ for i in range(0, len(bits_raw) - SAMPLES_PER_SYMBOL, SAMPLES_PER_SYMBOL): Look for the preamble pattern (eight `1`s then a sync marker). Once found, read the 20-byte obfuscated payload. -> ðŸ“ļ `[screenshot: spectrogram of IQ data showing FSK burst patterns]` +![spectrogram of IQ data showing FSK burst patterns](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/airwave_spectrogram.png) ### Step 4 — XOR-deobfuscate and verify CRC @@ -131,7 +131,7 @@ Telemetry frames (type=0x01) are noise for this challenge. Token = `0BS3RV3-L41N-868` -> ðŸ“ļ `[screenshot: decoded frame output showing the two token parts]` +![decoded frame output showing the two token parts](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/airwave_decode.png) ### Step 6 — Submit to the console @@ -145,7 +145,7 @@ unlock 0BS3RV3-L41N-868 The server returns the flag. -> ðŸ“ļ `[screenshot: maintenance console returning the flag after unlock]` +![maintenance console returning the flag after unlock](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/airwave_flag.png) --- diff --git a/Misc/AETHER_NET/README.md b/Misc/AETHER_NET/README.md index 557e5ae..d95634f 100644 --- a/Misc/AETHER_NET/README.md +++ b/Misc/AETHER_NET/README.md @@ -57,7 +57,7 @@ cat ~/.bash_history `network.log` lists all five nodes and their ports. `.bash_history` shows partial MQTT credentials and previous curl commands. -> ðŸ“ļ `[screenshot: notes.txt showing network topology map]` +![notes.txt showing network topology map](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/aether_notes.png) --- @@ -100,7 +100,7 @@ curl "http://:8080/docs?file=../../var/aether/config.json" Returns the full instance config with all credentials. -> ðŸ“ļ `[screenshot: SQLi response returning mqtt_pass and admin_token from system_config]` +![SQLi response returning mqtt_pass and admin_token from system_config](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/aether_sqli.png) --- @@ -139,7 +139,7 @@ SUBSCRIBE wired/knights/ Response (base64-decoded): *"e=3. No padding. The plaintext is short. Cube root gives the key."* -> ðŸ“ļ `[screenshot: MQTT response with RSA public key and ciphertext]` +![MQTT response with RSA public key and ciphertext](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/aether_mqtt_rsa.png) --- @@ -166,7 +166,7 @@ deus_pass = m.to_bytes(20, 'big').rstrip(b'\x00').decode() print(f"SSH password: {deus_pass}") ``` -> ðŸ“ļ `[screenshot: Python script computing the cube root and printing the SSH password]` +![Python script computing the cube root and printing the SSH password](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/aether_cube_root.png) --- @@ -178,7 +178,7 @@ ssh deus@ -p 22 cat flag.txt ``` -> ðŸ“ļ `[screenshot: SSH session showing the flag in flag.txt]` +![SSH session showing the flag in flag.txt](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/aether_ssh_flag.png) --- diff --git a/Misc/Accela_Signal/README.md b/Misc/Accela_Signal/README.md index 77d4bf8..fae89ac 100644 --- a/Misc/Accela_Signal/README.md +++ b/Misc/Accela_Signal/README.md @@ -63,7 +63,7 @@ IQ baseband, 8000 sps, int16 LE interleaved Chirp Spread Spectrum detected. N=128. ``` -> ðŸ“ļ `[screenshot: nc output showing the IQ stream banner]` +![nc output showing the IQ stream banner](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/accela_nc.png) ### Step 2 — Analyze the spectrogram @@ -75,7 +75,7 @@ Load the IQ data in inspectrum or plot with matplotlib. You see: This is **Chirp Spread Spectrum (CSS)**, identical in principle to LoRa. -> ðŸ“ļ `[screenshot: spectrogram showing upchirp preamble and downchirp sync patterns]` +![spectrogram showing upchirp preamble and downchirp sync patterns](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/accela_spectrogram.png) ### Step 3 — Determine parameters @@ -135,7 +135,7 @@ def symbols_to_bytes(symbols): return bytes(int(bits[i:i+8], 2) for i in range(0, len(bits) - 7, 8)) ``` -> ðŸ“ļ `[screenshot: Python decoder output showing decoded symbols and CRC16 validation pass]` +![Python decoder output showing decoded symbols and CRC16 validation pass](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/accela_decoder.png) ### Step 7 — Parse frame payload and decrypt @@ -159,7 +159,7 @@ for frame_type, data, crc in decoded_frames: print(flag.rstrip(b'\x00').decode()) ``` -> ðŸ“ļ `[screenshot: script printing the decrypted flag from the data frame]` +![script printing the decrypted flag from the data frame](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/accela_flag.png) ### Key insights diff --git a/Misc/LAYER_ZERO/README.md b/Misc/LAYER_ZERO/README.md index c812db0..0c0b136 100644 --- a/Misc/LAYER_ZERO/README.md +++ b/Misc/LAYER_ZERO/README.md @@ -105,7 +105,7 @@ SUBMIT Server responds with token `L01:xxxxxxxxxx`. -> ðŸ“ļ `[screenshot: Python script printing the 3-character steganographic code]` +![Python script printing the 3-character steganographic code](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/layer_stego.png) --- @@ -138,7 +138,7 @@ Submit: `/submit?code=` Server responds with token `L03:xxxxxxxxxx`. -> ðŸ“ļ `[screenshot: web response returning the L03 token after submitting the decrypted code]` +![web response returning the L03 token after submitting the decrypted code](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/layer_web.png) --- @@ -167,7 +167,7 @@ for w3, w4 in itertools.product(WORD3, WORD4): break ``` -> ðŸ“ļ `[screenshot: brute-force script finding the correct word pair and printing the L07 token]` +![brute-force script finding the correct word pair and printing the L07 token](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/layer_bruteforce.png) --- @@ -212,7 +212,7 @@ SUBMIT <code> Server responds with token `L13:xxxxxxxxxx`. -> ðŸ“ļ `[screenshot: autocorrelation peaks confirming echo delays and decoded token]` +![autocorrelation peaks confirming echo delays and decoded token](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/layer_autocorr.png) --- @@ -237,7 +237,7 @@ Exploit via command injection — the binary calls `system()` with unsanitised i $(cat /root/flag.txt) ``` -> ðŸ“ļ `[screenshot: eiri_validator printing the flag via command injection]` +![eiri_validator printing the flag via command injection](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/layer_injection.png) --- diff --git a/Misc/Last_Train_451/README.md b/Misc/Last_Train_451/README.md index 65949af..e8c1275 100644 --- a/Misc/Last_Train_451/README.md +++ b/Misc/Last_Train_451/README.md @@ -51,7 +51,7 @@ nc <host> 4545 The challenge server code is not yet publicly available. Full solution will be written once the server is deployed. -> ðŸ“ļ `[screenshot: challenge banner on port 4545]` +![challenge banner on port 4545](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/train_banner.png) --- diff --git a/Misc/Patient_Portal/README.md b/Misc/Patient_Portal/README.md index 06d36e0..7177d20 100644 --- a/Misc/Patient_Portal/README.md +++ b/Misc/Patient_Portal/README.md @@ -83,7 +83,7 @@ Results: Key finding: `ssh_passphrase = wired-med-013` -> ðŸ“ļ `[screenshot: SQLi response showing the admin hash and ssh_passphrase rows]` +![SQLi response showing the admin hash and ssh_passphrase rows](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/patient_sqli.png) **Crack the admin password:** @@ -105,7 +105,7 @@ Log in at `/login`: The admin panel reveals: SSH port 2222, user `webadmin`. -> ðŸ“ļ `[screenshot: admin panel after login showing report links and system info]` +![admin panel after login showing report links and system info](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/patient_admin.png) --- @@ -127,7 +127,7 @@ The `/admin/reports?file=` endpoint is vulnerable to path traversal. Save the key to `id_rsa` locally. -> ðŸ“ļ `[screenshot: path traversal response returning the id_rsa private key]` +![path traversal response returning the id_rsa private key](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/patient_lfi.png) --- @@ -160,7 +160,7 @@ strings /opt/navi-monitor/vital-check | grep logger The binary calls `system("logger -t vital-check 'check complete'")` using a **relative path** for `logger`. -> ðŸ“ļ `[screenshot: strings output confirming the relative logger call]` +![strings output confirming the relative logger call](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/patient_strings.png) **Exploit via PATH hijacking:** @@ -180,7 +180,7 @@ export PATH=/tmp:$PATH cat /root/root.txt ``` -> ðŸ“ļ `[screenshot: root shell reading /root/root.txt with the flag]` +![root shell reading /root/root.txt with the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/patient_root.png) --- diff --git a/OT/Cyberia_Grid/README.md b/OT/Cyberia_Grid/README.md index 0783ace..b2cc135 100644 --- a/OT/Cyberia_Grid/README.md +++ b/OT/Cyberia_Grid/README.md @@ -70,7 +70,7 @@ with device(host="<HOST>", port=44818) as via: psyche_st = via.read("Psyche_Status") # = "DORMANT" ``` -> ðŸ“ļ `[screenshot: cpppo client output listing all tag values including hidden ones]` +![cpppo client output listing all tag values including hidden ones](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/cyberia_tags.png) **Observation:** `Zone_Basement_Power = 0` — the basement is OFF. This is the first hint that something is hidden underground. @@ -93,7 +93,7 @@ Each `Psyche_Processor` value is derived from existing infrastructure tags: | 2 | `sum(Lighting_Main) % 256` | `1065 % 256` | 17 | | 3 | `0x1337` (hacker constant) | `4919` | 4919 | -> ðŸ“ļ `[screenshot: Python calculation showing the four derived activation values]` +![Python calculation showing the four derived activation values](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/cyberia_calc.png) ### Step 4 — Activate the Psyche Processor @@ -120,7 +120,7 @@ with device(host="<HOST>", port=44818) as via: # Also: Knights_Cipher[3] is now populated: 0x67 = 'g' → key = "Knig" ``` -> ðŸ“ļ `[screenshot: Decoded_Output tag returning the flag after Psyche Processor activation]` +![Decoded_Output tag returning the flag after Psyche Processor activation](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/cyberia_flag.png) ### Key concepts diff --git a/OT/Operating_Room/README.md b/OT/Operating_Room/README.md index 1f289d1..1486add 100644 --- a/OT/Operating_Room/README.md +++ b/OT/Operating_Room/README.md @@ -85,7 +85,7 @@ Key registers: | 110 | write target | Trigger register | | 200-215 | zeros → flag | Populated after completion | -> ðŸ“ļ `[screenshot: register dump highlighting XOR key at reg 19 and 105, and state machine at 100-105]` +![register dump highlighting XOR key at reg 19 and 105, and state machine at 100-1](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/oproom_regs.png) ### Step 3 — Decode the state machine logic @@ -125,7 +125,7 @@ for expected_state in range(6): time.sleep(0.3) ``` -> ðŸ“ļ `[screenshot: script executing each transition and state advancing from 0 to 6]` +![script executing each transition and state advancing from 0 to 6](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/oproom_transitions.png) ### Step 5 — Read the flag @@ -141,7 +141,7 @@ for val in regs: print(flag) ``` -> ðŸ“ļ `[screenshot: flag registers decoded to ASCII]` +![flag registers decoded to ASCII](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/oproom_flag.png) --- diff --git a/OT/Protocol_Seven/README.md b/OT/Protocol_Seven/README.md index 297febc..899714a 100644 --- a/OT/Protocol_Seven/README.md +++ b/OT/Protocol_Seven/README.md @@ -93,7 +93,7 @@ for i in range(8): **XOR key = `Eiri_Key`** -> ðŸ“ļ `[screenshot: BACnet read output showing the 8 harmonic float values]` +![BACnet read output showing the 8 harmonic float values](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/p7_bacnet.png) ### Layer 2 — OPC-UA payload extraction @@ -119,7 +119,7 @@ payload_bytes, iv_hint = asyncio.run(get_payload()) # iv_hint: "Rotation offset from CIP controller — read NONCE tag" ``` -> ðŸ“ļ `[screenshot: OPC-UA browse showing Protocol7_Vault contents and hints]` +![OPC-UA browse showing Protocol7_Vault contents and hints](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/p7_opcua.png) ### Layer 3 — EtherNet/IP nonce extraction @@ -150,7 +150,7 @@ flag = flag_bytes.rstrip(b'\x00').decode() print(flag) ``` -> ðŸ“ļ `[screenshot: Python decryption script printing the reconstructed flag]` +![Python decryption script printing the reconstructed flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/p7_decrypt.png) --- diff --git a/OT/Schumann_Resonance/README.md b/OT/Schumann_Resonance/README.md index 36a1179..a7dffe5 100644 --- a/OT/Schumann_Resonance/README.md +++ b/OT/Schumann_Resonance/README.md @@ -61,7 +61,7 @@ bacnet.whois() Device instance **783** → 7.83 Hz → **Schumann Resonance**. -> ðŸ“ļ `[screenshot: BACnet WhoIs response showing Device:783]` +![BACnet WhoIs response showing Device:783](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/schumann_whois.png) ### Step 2 — Enumerate objects @@ -76,7 +76,7 @@ Read the object-list from Device:783: | BinaryValue:100 | Resonance_Lock | inactive | | CharStringValue:200 | Research_Log | "Access Denied" | -> ðŸ“ļ `[screenshot: object list showing Fragment objects and their hex descriptions]` +![object list showing Fragment objects and their hex descriptions](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/schumann_fragments.png) ### Step 3 — Identify the XOR key @@ -101,7 +101,7 @@ flag = "".join(fragments) print(flag) ``` -> ðŸ“ļ `[screenshot: decoded fragment strings concatenating into the flag]` +![decoded fragment strings concatenating into the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/schumann_decode.png) ### Step 5 — Activate (alternative path) @@ -121,7 +121,7 @@ flag = bacnet.read(f"783 characterstringValue 200 presentValue") print(flag) ``` -> ðŸ“ļ `[screenshot: Research_Log returning the flag after Resonance_Lock activation]` +![Research_Log returning the flag after Resonance_Lock activation](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/schumann_flag.png) ### Key concepts diff --git a/OT/Tachibana_SCADA/README.md b/OT/Tachibana_SCADA/README.md index 86da7b7..534afaf 100644 --- a/OT/Tachibana_SCADA/README.md +++ b/OT/Tachibana_SCADA/README.md @@ -67,7 +67,7 @@ async def exploit(): 'urn:tachibana:eiri:kids'] ← HIDDEN namespace ``` -> ðŸ“ļ `[screenshot: NamespaceArray showing the hidden eiri:kids namespace at index 3]` +![NamespaceArray showing the hidden eiri:kids namespace at index 3](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/tachibana_ns.png) ### Step 2 — Browse the public namespace (ns=2) @@ -95,7 +95,7 @@ async with Client("opc.tcp://<HOST>:4840/tachibana/") as c: extract_method = await bkdr.get_child(f"{ns}:ExtractResearchData") ``` -> ðŸ“ļ `[screenshot: browse output showing EiriMasami folder with KIDS_Project and Backdoor subfolders]` +![browse output showing EiriMasami folder with KIDS_Project and Backdoor subfolder](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/tachibana_browse.png) ### Step 4 — Read method argument descriptions @@ -116,7 +116,7 @@ import hashlib key_hash = hashlib.sha256(b"KIDS").digest()[:16] ``` -> ðŸ“ļ `[screenshot: key_hash computation in Python REPL]` +![key_hash computation in Python REPL](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/tachibana_keyhash.png) ### Step 6 — Authenticate @@ -142,7 +142,7 @@ async with Client("opc.tcp://<HOST>:4840/tachibana/") as c: print(data[0]) # ESPILON{31r1_k1ds_pr0t0c0l_s3v3n} ``` -> ðŸ“ļ `[screenshot: ExtractResearchData method call returning the flag]` +![ExtractResearchData method call returning the flag](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/tachibana_flag.png) ### Key insights diff --git a/Web3/GANTZ_BALL_CONTRACT/README.md b/Web3/GANTZ_BALL_CONTRACT/README.md index 0b9f23a..398d4f1 100644 --- a/Web3/GANTZ_BALL_CONTRACT/README.md +++ b/Web3/GANTZ_BALL_CONTRACT/README.md @@ -56,7 +56,7 @@ nc <host> 1337 bytecode ``` -> ðŸ“ļ `[screenshot: console showing the deployed bytecode hex]` +![console showing the deployed bytecode hex](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/gantz_bytecode.png) ### Step 2 — Decompile @@ -80,7 +80,7 @@ Recovered functions: and `_rewardLock` (protecting `claimReward`). During `unstake()`, `_stakeLock=1` but `_rewardLock=0` — the window for cross-function reentrancy. -> ðŸ“ļ `[screenshot: decompiler output showing two separate reentrancy guard variables]` +![decompiler output showing two separate reentrancy guard variables](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/gantz_decompile.png) ### Step 3 — Find the mission proof preimages @@ -164,7 +164,7 @@ cast send <EXPLOIT_ADDR> 'exploit()' \ --private-key <PLAYER_KEY> ``` -> ðŸ“ļ `[screenshot: forge deploy and cast send commands completing successfully]` +![forge deploy and cast send commands completing successfully](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/gantz_deploy.png) ### Step 5 — Get the flag @@ -173,7 +173,7 @@ nc <host> 1337 check ``` -> ðŸ“ļ `[screenshot: console printing the flag after successful reentrancy exploit]` +![console printing the flag after successful reentrancy exploit](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/gantz_flag.png) ### Key concepts diff --git a/Web3/TACHIBANA_FIRMWARE_REGISTRY/README.md b/Web3/TACHIBANA_FIRMWARE_REGISTRY/README.md index b2b79e0..717459d 100644 --- a/Web3/TACHIBANA_FIRMWARE_REGISTRY/README.md +++ b/Web3/TACHIBANA_FIRMWARE_REGISTRY/README.md @@ -74,7 +74,7 @@ When `firmwareHashes.length == 0`, calling `auditFirmware()` sets the length to This makes `modifyFirmware(index, value)` able to write to any storage slot via the dynamic array element storage formula. -> ðŸ“ļ `[screenshot: assembly code showing the unchecked sub(len, 1) line]` +![assembly code showing the unchecked sub(len, 1) line](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/fw_reg_asm.png) ### Step 2 — Fuzz to discover the invariant violation @@ -109,7 +109,7 @@ contract FirmwareRegistryFuzz is Test { Running `forge test --fuzz-runs 1000` triggers the invariant failure on the `auditFirmware()` + `modifyFirmware(target_index, player_bytes32)` sequence. -> ðŸ“ļ `[screenshot: forge fuzz output showing invariant_ownerIsDeployer failure]` +![forge fuzz output showing invariant_ownerIsDeployer failure](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/fw_reg_fuzz.png) ### Step 3 — Compute the target storage index @@ -162,7 +162,7 @@ tx = registry.functions.triggerEmergency().build_transaction({...}) w3.eth.send_raw_transaction(acct.sign_transaction(tx).rawTransaction) ``` -> ðŸ“ļ `[screenshot: Python exploit script completing all four transactions]` +![Python exploit script completing all four transactions](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/fw_reg_exploit.png) ### Step 5 — Get the flag @@ -171,7 +171,7 @@ nc <host> 1337 check ``` -> ðŸ“ļ `[screenshot: console printing the flag after triggerEmergency succeeds]` +![console printing the flag after triggerEmergency succeeds](https://git.espilon.net/Eun0us/ESPILON-CTF-2026-Writeups/raw/branch/main/screens/fw_reg_flag.png) ### Key concepts diff --git a/screens/accela_decoder.png b/screens/accela_decoder.png new file mode 100644 index 0000000..564bedf Binary files /dev/null and b/screens/accela_decoder.png differ diff --git a/screens/accela_flag.png b/screens/accela_flag.png new file mode 100644 index 0000000..4eefe1e Binary files /dev/null and b/screens/accela_flag.png differ diff --git a/screens/accela_nc.png b/screens/accela_nc.png new file mode 100644 index 0000000..8a29fa4 Binary files /dev/null and b/screens/accela_nc.png differ diff --git a/screens/accela_spectrogram.png b/screens/accela_spectrogram.png new file mode 100644 index 0000000..c8fbacb Binary files /dev/null and b/screens/accela_spectrogram.png differ diff --git a/screens/aether_cube_root.png b/screens/aether_cube_root.png new file mode 100644 index 0000000..2224455 Binary files /dev/null and b/screens/aether_cube_root.png differ diff --git a/screens/aether_mqtt_rsa.png b/screens/aether_mqtt_rsa.png new file mode 100644 index 0000000..bb0a131 Binary files /dev/null and b/screens/aether_mqtt_rsa.png differ diff --git a/screens/aether_notes.png b/screens/aether_notes.png new file mode 100644 index 0000000..929dd88 Binary files /dev/null and b/screens/aether_notes.png differ diff --git a/screens/aether_sqli.png b/screens/aether_sqli.png new file mode 100644 index 0000000..79a4b16 Binary files /dev/null and b/screens/aether_sqli.png differ diff --git a/screens/aether_ssh_flag.png b/screens/aether_ssh_flag.png new file mode 100644 index 0000000..4137c28 Binary files /dev/null and b/screens/aether_ssh_flag.png differ diff --git a/screens/airwave_decode.png b/screens/airwave_decode.png new file mode 100644 index 0000000..2368e8e Binary files /dev/null and b/screens/airwave_decode.png differ diff --git a/screens/airwave_flag.png b/screens/airwave_flag.png new file mode 100644 index 0000000..69fea4c Binary files /dev/null and b/screens/airwave_flag.png differ diff --git a/screens/airwave_nc.png b/screens/airwave_nc.png new file mode 100644 index 0000000..21f75f3 Binary files /dev/null and b/screens/airwave_nc.png differ diff --git a/screens/airwave_spectrogram.png b/screens/airwave_spectrogram.png new file mode 100644 index 0000000..87573e4 Binary files /dev/null and b/screens/airwave_spectrogram.png differ diff --git a/screens/can_flag.png b/screens/can_flag.png new file mode 100644 index 0000000..fca0ecd Binary files /dev/null and b/screens/can_flag.png differ diff --git a/screens/can_seed.png b/screens/can_seed.png new file mode 100644 index 0000000..d8b1f94 Binary files /dev/null and b/screens/can_seed.png differ diff --git a/screens/can_sniff.png b/screens/can_sniff.png new file mode 100644 index 0000000..e393739 Binary files /dev/null and b/screens/can_sniff.png differ diff --git a/screens/can_terminals.png b/screens/can_terminals.png new file mode 100644 index 0000000..8677876 Binary files /dev/null and b/screens/can_terminals.png differ diff --git a/screens/coap_firmware_key.png b/screens/coap_firmware_key.png new file mode 100644 index 0000000..24c3d56 Binary files /dev/null and b/screens/coap_firmware_key.png differ diff --git a/screens/coap_flag.png b/screens/coap_flag.png new file mode 100644 index 0000000..ecfa54e Binary files /dev/null and b/screens/coap_flag.png differ diff --git a/screens/coap_observe.png b/screens/coap_observe.png new file mode 100644 index 0000000..ac54189 Binary files /dev/null and b/screens/coap_observe.png differ diff --git a/screens/coap_wellknown.png b/screens/coap_wellknown.png new file mode 100644 index 0000000..534aa70 Binary files /dev/null and b/screens/coap_wellknown.png differ diff --git a/screens/cyberia_calc.png b/screens/cyberia_calc.png new file mode 100644 index 0000000..8c1fe9b Binary files /dev/null and b/screens/cyberia_calc.png differ diff --git a/screens/cyberia_flag.png b/screens/cyberia_flag.png new file mode 100644 index 0000000..ebf6a8a Binary files /dev/null and b/screens/cyberia_flag.png differ diff --git a/screens/cyberia_tags.png b/screens/cyberia_tags.png new file mode 100644 index 0000000..17e405d Binary files /dev/null and b/screens/cyberia_tags.png differ diff --git a/screens/fw_reg_asm.png b/screens/fw_reg_asm.png new file mode 100644 index 0000000..02ac146 Binary files /dev/null and b/screens/fw_reg_asm.png differ diff --git a/screens/fw_reg_exploit.png b/screens/fw_reg_exploit.png new file mode 100644 index 0000000..a51bf31 Binary files /dev/null and b/screens/fw_reg_exploit.png differ diff --git a/screens/fw_reg_flag.png b/screens/fw_reg_flag.png new file mode 100644 index 0000000..4eafc06 Binary files /dev/null and b/screens/fw_reg_flag.png differ diff --git a/screens/fw_reg_fuzz.png b/screens/fw_reg_fuzz.png new file mode 100644 index 0000000..5cb95dc Binary files /dev/null and b/screens/fw_reg_fuzz.png differ diff --git a/screens/gantz_bytecode.png b/screens/gantz_bytecode.png new file mode 100644 index 0000000..a78a340 Binary files /dev/null and b/screens/gantz_bytecode.png differ diff --git a/screens/gantz_decompile.png b/screens/gantz_decompile.png new file mode 100644 index 0000000..5de7fd3 Binary files /dev/null and b/screens/gantz_decompile.png differ diff --git a/screens/gantz_deploy.png b/screens/gantz_deploy.png new file mode 100644 index 0000000..ac5cf99 Binary files /dev/null and b/screens/gantz_deploy.png differ diff --git a/screens/gantz_flag.png b/screens/gantz_flag.png new file mode 100644 index 0000000..154ee21 Binary files /dev/null and b/screens/gantz_flag.png differ diff --git a/screens/glitch_banner.png b/screens/glitch_banner.png new file mode 100644 index 0000000..0be9fbb Binary files /dev/null and b/screens/glitch_banner.png differ diff --git a/screens/glitch_flag.png b/screens/glitch_flag.png new file mode 100644 index 0000000..003d169 Binary files /dev/null and b/screens/glitch_flag.png differ diff --git a/screens/glitch_observe.png b/screens/glitch_observe.png new file mode 100644 index 0000000..0859521 Binary files /dev/null and b/screens/glitch_observe.png differ diff --git a/screens/glitch_unlock.png b/screens/glitch_unlock.png new file mode 100644 index 0000000..dd36f83 Binary files /dev/null and b/screens/glitch_unlock.png differ diff --git a/screens/hate_uart_boot.png b/screens/hate_uart_boot.png new file mode 100644 index 0000000..c68e484 Binary files /dev/null and b/screens/hate_uart_boot.png differ diff --git a/screens/hate_uart_decrypt.png b/screens/hate_uart_decrypt.png new file mode 100644 index 0000000..5de9f35 Binary files /dev/null and b/screens/hate_uart_decrypt.png differ diff --git a/screens/hate_uart_mem.png b/screens/hate_uart_mem.png new file mode 100644 index 0000000..741e93a Binary files /dev/null and b/screens/hate_uart_mem.png differ diff --git a/screens/hate_uart_nvs.png b/screens/hate_uart_nvs.png new file mode 100644 index 0000000..c8a038f Binary files /dev/null and b/screens/hate_uart_nvs.png differ diff --git a/screens/i2c_decrypt.png b/screens/i2c_decrypt.png new file mode 100644 index 0000000..11f4911 Binary files /dev/null and b/screens/i2c_decrypt.png differ diff --git a/screens/i2c_key.png b/screens/i2c_key.png new file mode 100644 index 0000000..ac4cc89 Binary files /dev/null and b/screens/i2c_key.png differ diff --git a/screens/i2c_prompt.png b/screens/i2c_prompt.png new file mode 100644 index 0000000..8585e63 Binary files /dev/null and b/screens/i2c_prompt.png differ diff --git a/screens/i2c_scan.png b/screens/i2c_scan.png new file mode 100644 index 0000000..425fb89 Binary files /dev/null and b/screens/i2c_scan.png differ diff --git a/screens/jnouned_console.png b/screens/jnouned_console.png new file mode 100644 index 0000000..b6a0f2a Binary files /dev/null and b/screens/jnouned_console.png differ diff --git a/screens/jnouned_flag3.png b/screens/jnouned_flag3.png new file mode 100644 index 0000000..864824d Binary files /dev/null and b/screens/jnouned_flag3.png differ diff --git a/screens/jnouned_jmp.png b/screens/jnouned_jmp.png new file mode 100644 index 0000000..2486c4e Binary files /dev/null and b/screens/jnouned_jmp.png differ diff --git a/screens/jnouned_login.png b/screens/jnouned_login.png new file mode 100644 index 0000000..54ed382 Binary files /dev/null and b/screens/jnouned_login.png differ diff --git a/screens/jtag_banner.png b/screens/jtag_banner.png new file mode 100644 index 0000000..f9e2b66 Binary files /dev/null and b/screens/jtag_banner.png differ diff --git a/screens/jtag_idcode.png b/screens/jtag_idcode.png new file mode 100644 index 0000000..6b2e215 Binary files /dev/null and b/screens/jtag_idcode.png differ diff --git a/screens/jtag_mem_read.png b/screens/jtag_mem_read.png new file mode 100644 index 0000000..7d1efbb Binary files /dev/null and b/screens/jtag_mem_read.png differ diff --git a/screens/jtag_unlock.png b/screens/jtag_unlock.png new file mode 100644 index 0000000..38f1890 Binary files /dev/null and b/screens/jtag_unlock.png differ diff --git a/screens/knights_exploit.png b/screens/knights_exploit.png new file mode 100644 index 0000000..959b01b Binary files /dev/null and b/screens/knights_exploit.png differ diff --git a/screens/knights_fragments.png b/screens/knights_fragments.png new file mode 100644 index 0000000..bb956d3 Binary files /dev/null and b/screens/knights_fragments.png differ diff --git a/screens/knights_scan.png b/screens/knights_scan.png new file mode 100644 index 0000000..a15af10 Binary files /dev/null and b/screens/knights_scan.png differ diff --git a/screens/lain_decrypt.png b/screens/lain_decrypt.png new file mode 100644 index 0000000..9244389 Binary files /dev/null and b/screens/lain_decrypt.png differ diff --git a/screens/lain_strings.png b/screens/lain_strings.png new file mode 100644 index 0000000..d9ec1fe Binary files /dev/null and b/screens/lain_strings.png differ diff --git a/screens/lain_terminals.png b/screens/lain_terminals.png new file mode 100644 index 0000000..f4de389 Binary files /dev/null and b/screens/lain_terminals.png differ diff --git a/screens/lain_v2_decrypt.png b/screens/lain_v2_decrypt.png new file mode 100644 index 0000000..b66df48 Binary files /dev/null and b/screens/lain_v2_decrypt.png differ diff --git a/screens/lain_v2_dump.png b/screens/lain_v2_dump.png new file mode 100644 index 0000000..6b4372f Binary files /dev/null and b/screens/lain_v2_dump.png differ diff --git a/screens/lain_v2_enc_data.png b/screens/lain_v2_enc_data.png new file mode 100644 index 0000000..59d03da Binary files /dev/null and b/screens/lain_v2_enc_data.png differ diff --git a/screens/lain_v2_strings.png b/screens/lain_v2_strings.png new file mode 100644 index 0000000..78c2559 Binary files /dev/null and b/screens/lain_v2_strings.png differ diff --git a/screens/lain_xor_key.png b/screens/lain_xor_key.png new file mode 100644 index 0000000..aafa461 Binary files /dev/null and b/screens/lain_xor_key.png differ diff --git a/screens/layer_autocorr.png b/screens/layer_autocorr.png new file mode 100644 index 0000000..eb3b32f Binary files /dev/null and b/screens/layer_autocorr.png differ diff --git a/screens/layer_bruteforce.png b/screens/layer_bruteforce.png new file mode 100644 index 0000000..d4f48dc Binary files /dev/null and b/screens/layer_bruteforce.png differ diff --git a/screens/layer_injection.png b/screens/layer_injection.png new file mode 100644 index 0000000..2eff8b4 Binary files /dev/null and b/screens/layer_injection.png differ diff --git a/screens/layer_stego.png b/screens/layer_stego.png new file mode 100644 index 0000000..c366010 Binary files /dev/null and b/screens/layer_stego.png differ diff --git a/screens/layer_web.png b/screens/layer_web.png new file mode 100644 index 0000000..eda98f5 Binary files /dev/null and b/screens/layer_web.png differ diff --git a/screens/love_uart_flag.png b/screens/love_uart_flag.png new file mode 100644 index 0000000..dfc8132 Binary files /dev/null and b/screens/love_uart_flag.png differ diff --git a/screens/love_uart_terminals.png b/screens/love_uart_terminals.png new file mode 100644 index 0000000..e2b25f1 Binary files /dev/null and b/screens/love_uart_terminals.png differ diff --git a/screens/mqtt_config_json.png b/screens/mqtt_config_json.png new file mode 100644 index 0000000..ba4474b Binary files /dev/null and b/screens/mqtt_config_json.png differ diff --git a/screens/mqtt_firmware.png b/screens/mqtt_firmware.png new file mode 100644 index 0000000..34b6a39 Binary files /dev/null and b/screens/mqtt_firmware.png differ diff --git a/screens/mqtt_flag.png b/screens/mqtt_flag.png new file mode 100644 index 0000000..c3b5024 Binary files /dev/null and b/screens/mqtt_flag.png differ diff --git a/screens/mqtt_topics.png b/screens/mqtt_topics.png new file mode 100644 index 0000000..6d93136 Binary files /dev/null and b/screens/mqtt_topics.png differ diff --git a/screens/nurse_flag.png b/screens/nurse_flag.png new file mode 100644 index 0000000..b4e4c21 Binary files /dev/null and b/screens/nurse_flag.png differ diff --git a/screens/nurse_log.png b/screens/nurse_log.png new file mode 100644 index 0000000..5c63398 Binary files /dev/null and b/screens/nurse_log.png differ diff --git a/screens/nurse_maint.png b/screens/nurse_maint.png new file mode 100644 index 0000000..e9f9956 Binary files /dev/null and b/screens/nurse_maint.png differ diff --git a/screens/oproom_flag.png b/screens/oproom_flag.png new file mode 100644 index 0000000..7902a96 Binary files /dev/null and b/screens/oproom_flag.png differ diff --git a/screens/oproom_regs.png b/screens/oproom_regs.png new file mode 100644 index 0000000..fb9f2b2 Binary files /dev/null and b/screens/oproom_regs.png differ diff --git a/screens/oproom_transitions.png b/screens/oproom_transitions.png new file mode 100644 index 0000000..d225271 Binary files /dev/null and b/screens/oproom_transitions.png differ diff --git a/screens/p7_bacnet.png b/screens/p7_bacnet.png new file mode 100644 index 0000000..2115392 Binary files /dev/null and b/screens/p7_bacnet.png differ diff --git a/screens/p7_decrypt.png b/screens/p7_decrypt.png new file mode 100644 index 0000000..14fb106 Binary files /dev/null and b/screens/p7_decrypt.png differ diff --git a/screens/p7_opcua.png b/screens/p7_opcua.png new file mode 100644 index 0000000..6e8dfdc Binary files /dev/null and b/screens/p7_opcua.png differ diff --git a/screens/patient_admin.png b/screens/patient_admin.png new file mode 100644 index 0000000..0c9f18f Binary files /dev/null and b/screens/patient_admin.png differ diff --git a/screens/patient_lfi.png b/screens/patient_lfi.png new file mode 100644 index 0000000..dbb5675 Binary files /dev/null and b/screens/patient_lfi.png differ diff --git a/screens/patient_root.png b/screens/patient_root.png new file mode 100644 index 0000000..54a1c82 Binary files /dev/null and b/screens/patient_root.png differ diff --git a/screens/patient_sqli.png b/screens/patient_sqli.png new file mode 100644 index 0000000..24172f0 Binary files /dev/null and b/screens/patient_sqli.png differ diff --git a/screens/patient_strings.png b/screens/patient_strings.png new file mode 100644 index 0000000..90b9708 Binary files /dev/null and b/screens/patient_strings.png differ diff --git a/screens/phantom_inject.png b/screens/phantom_inject.png new file mode 100644 index 0000000..62861b2 Binary files /dev/null and b/screens/phantom_inject.png differ diff --git a/screens/phantom_trace.png b/screens/phantom_trace.png new file mode 100644 index 0000000..e08c456 Binary files /dev/null and b/screens/phantom_trace.png differ diff --git a/screens/phantom_wire.png b/screens/phantom_wire.png new file mode 100644 index 0000000..6ee1df8 Binary files /dev/null and b/screens/phantom_wire.png differ diff --git a/screens/schumann_decode.png b/screens/schumann_decode.png new file mode 100644 index 0000000..7cdc343 Binary files /dev/null and b/screens/schumann_decode.png differ diff --git a/screens/schumann_flag.png b/screens/schumann_flag.png new file mode 100644 index 0000000..0659e0d Binary files /dev/null and b/screens/schumann_flag.png differ diff --git a/screens/schumann_fragments.png b/screens/schumann_fragments.png new file mode 100644 index 0000000..5ed2491 Binary files /dev/null and b/screens/schumann_fragments.png differ diff --git a/screens/schumann_whois.png b/screens/schumann_whois.png new file mode 100644 index 0000000..274cac8 Binary files /dev/null and b/screens/schumann_whois.png differ diff --git a/screens/serial_exp_diag.png b/screens/serial_exp_diag.png new file mode 100644 index 0000000..855fed3 Binary files /dev/null and b/screens/serial_exp_diag.png differ diff --git a/screens/serial_exp_flag.png b/screens/serial_exp_flag.png new file mode 100644 index 0000000..1b27f4b Binary files /dev/null and b/screens/serial_exp_flag.png differ diff --git a/screens/serial_exp_terminals.png b/screens/serial_exp_terminals.png new file mode 100644 index 0000000..7a32aa3 Binary files /dev/null and b/screens/serial_exp_terminals.png differ diff --git a/screens/signal_tap_decode.png b/screens/signal_tap_decode.png new file mode 100644 index 0000000..b37d64d Binary files /dev/null and b/screens/signal_tap_decode.png differ diff --git a/screens/signal_tap_info.png b/screens/signal_tap_info.png new file mode 100644 index 0000000..c37e6cb Binary files /dev/null and b/screens/signal_tap_info.png differ diff --git a/screens/signal_tap_measure.png b/screens/signal_tap_measure.png new file mode 100644 index 0000000..f75c6bc Binary files /dev/null and b/screens/signal_tap_measure.png differ diff --git a/screens/spi_decrypt_flag.png b/screens/spi_decrypt_flag.png new file mode 100644 index 0000000..5e1548f Binary files /dev/null and b/screens/spi_decrypt_flag.png differ diff --git a/screens/spi_probe.png b/screens/spi_probe.png new file mode 100644 index 0000000..f18e3ca Binary files /dev/null and b/screens/spi_probe.png differ diff --git a/screens/spi_sfdp.png b/screens/spi_sfdp.png new file mode 100644 index 0000000..e12196b Binary files /dev/null and b/screens/spi_sfdp.png differ diff --git a/screens/spi_vendor.png b/screens/spi_vendor.png new file mode 100644 index 0000000..337631d Binary files /dev/null and b/screens/spi_vendor.png differ diff --git a/screens/tachibana_browse.png b/screens/tachibana_browse.png new file mode 100644 index 0000000..b917e2d Binary files /dev/null and b/screens/tachibana_browse.png differ diff --git a/screens/tachibana_flag.png b/screens/tachibana_flag.png new file mode 100644 index 0000000..3926511 Binary files /dev/null and b/screens/tachibana_flag.png differ diff --git a/screens/tachibana_keyhash.png b/screens/tachibana_keyhash.png new file mode 100644 index 0000000..dd17eb8 Binary files /dev/null and b/screens/tachibana_keyhash.png differ diff --git a/screens/tachibana_ns.png b/screens/tachibana_ns.png new file mode 100644 index 0000000..e74db3b Binary files /dev/null and b/screens/tachibana_ns.png differ diff --git a/screens/thewired_devices.png b/screens/thewired_devices.png new file mode 100644 index 0000000..3e03686 Binary files /dev/null and b/screens/thewired_devices.png differ diff --git a/screens/thewired_protocol.png b/screens/thewired_protocol.png new file mode 100644 index 0000000..01128ed Binary files /dev/null and b/screens/thewired_protocol.png differ diff --git a/screens/thewired_solver.png b/screens/thewired_solver.png new file mode 100644 index 0000000..5047362 Binary files /dev/null and b/screens/thewired_solver.png differ diff --git a/screens/thewired_strings.png b/screens/thewired_strings.png new file mode 100644 index 0000000..cf99e71 Binary files /dev/null and b/screens/thewired_strings.png differ diff --git a/screens/train_banner.png b/screens/train_banner.png new file mode 100644 index 0000000..ec79c6e Binary files /dev/null and b/screens/train_banner.png differ diff --git a/screens/wifi_aircrack.png b/screens/wifi_aircrack.png new file mode 100644 index 0000000..1fc14a2 Binary files /dev/null and b/screens/wifi_aircrack.png differ diff --git a/screens/wifi_flag_rx.png b/screens/wifi_flag_rx.png new file mode 100644 index 0000000..ec3abdf Binary files /dev/null and b/screens/wifi_flag_rx.png differ diff --git a/screens/wifi_pcap.png b/screens/wifi_pcap.png new file mode 100644 index 0000000..1d4ad40 Binary files /dev/null and b/screens/wifi_pcap.png differ diff --git a/screens/wifi_terminals.png b/screens/wifi_terminals.png new file mode 100644 index 0000000..dc2b168 Binary files /dev/null and b/screens/wifi_terminals.png differ