Add 107 terminal screenshots and replace all 📸 placeholders

- 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
This commit is contained in:
Eun0us 2026-03-27 00:34:47 +00:00
parent 2d7aaf794d
commit ac82d8367e
142 changed files with 93 additions and 95 deletions

View File

@ -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

View File

@ -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 (585 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)
---

View File

@ -57,7 +57,7 @@ nc <host> 3600
nc <host> 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

View File

@ -48,7 +48,7 @@ arm and trigger, then read the maintenance token from the unlocked debug console
nc <host> 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

View File

@ -50,7 +50,7 @@ Use the key to decrypt the EEPROM contents and recover the flag.
nc <host> 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

View File

@ -51,7 +51,7 @@ reassemble the flag.
nc <host> 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

View File

@ -53,7 +53,7 @@ nc <host> 1111
nc <host> 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

View File

@ -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

View File

@ -55,7 +55,7 @@ nc <host> 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

View File

@ -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

View File

@ -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 <HOST> -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 <HOST> -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

View File

@ -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

View File

@ -57,7 +57,7 @@ nc <host> 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)
---

View File

@ -50,7 +50,7 @@ to wake the module and receive the flag.
nc <host> 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 <MODULE_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)
---

View File

@ -60,7 +60,7 @@ Returns a comma-separated list of resource links (RFC 6690 format):
</maintenance/unlock>
```
> 📸 `[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://<HOST>/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)
---

View File

@ -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)
---

View File

@ -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

View File

@ -105,7 +105,7 @@ SUBMIT <decoded>
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=<plaintext>`
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)
---

View File

@ -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)
---

View File

@ -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

View File

@ -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)
---

View File

@ -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)
---

View File

@ -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

View File

@ -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

BIN
screens/accela_decoder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/accela_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
screens/accela_nc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/aether_mqtt_rsa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
screens/aether_notes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
screens/aether_sqli.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
screens/aether_ssh_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
screens/airwave_decode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
screens/airwave_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
screens/airwave_nc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
screens/can_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
screens/can_seed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
screens/can_sniff.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
screens/can_terminals.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
screens/coap_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
screens/coap_observe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
screens/coap_wellknown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
screens/cyberia_calc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
screens/cyberia_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/cyberia_tags.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
screens/fw_reg_asm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/fw_reg_exploit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/fw_reg_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
screens/fw_reg_fuzz.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
screens/gantz_bytecode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
screens/gantz_decompile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
screens/gantz_deploy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
screens/gantz_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
screens/glitch_banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/glitch_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/glitch_observe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
screens/glitch_unlock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
screens/hate_uart_boot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
screens/hate_uart_mem.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
screens/hate_uart_nvs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
screens/i2c_decrypt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
screens/i2c_key.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
screens/i2c_prompt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
screens/i2c_scan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
screens/jnouned_console.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
screens/jnouned_flag3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
screens/jnouned_jmp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
screens/jnouned_login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
screens/jtag_banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
screens/jtag_idcode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/jtag_mem_read.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
screens/jtag_unlock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
screens/knights_exploit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
screens/knights_scan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
screens/lain_decrypt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/lain_strings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
screens/lain_terminals.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
screens/lain_v2_decrypt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
screens/lain_v2_dump.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
screens/lain_v2_strings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
screens/lain_xor_key.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
screens/layer_autocorr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
screens/layer_injection.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
screens/layer_stego.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
screens/layer_web.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
screens/love_uart_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
screens/mqtt_firmware.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
screens/mqtt_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
screens/mqtt_topics.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
screens/nurse_flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
screens/nurse_log.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Some files were not shown because too many files have changed in this diff Show More