From 19d6a48c85fe931f71a45afe608995f73d91437d Mon Sep 17 00:00:00 2001 From: Eun0us Date: Thu, 26 Mar 2026 17:33:27 +0000 Subject: [PATCH] write-up: Hardware/Wired_SPI_Exfil/README.md --- Hardware/Wired_SPI_Exfil/README.md | 131 ++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 22 deletions(-) diff --git a/Hardware/Wired_SPI_Exfil/README.md b/Hardware/Wired_SPI_Exfil/README.md index 5814f2e..12fa35d 100644 --- a/Hardware/Wired_SPI_Exfil/README.md +++ b/Hardware/Wired_SPI_Exfil/README.md @@ -1,53 +1,140 @@ -# Wired SPI Exfil — Solution +# Wired SPI Exfil -## Overview +| Field | Value | +|-------|-------| +| Category | Hardware | +| Difficulty | Medium-Hard | +| Points | 500 | +| Author | Eun0us | +| CTF | Espilon 2026 | -Simulated SPI flash chip from a WIRED-MED module. Standard SPI flash commands are used to read chip contents. A hidden partition not listed in the normal partition table contains the XOR-encrypted flag. The SFDP table has vendor-specific parameters that reveal the hidden sector. +--- -## Steps +## Description -1. Connect and assert CS: +A WIRED-MED module's SPI flash chip is accessible via a probe station. +Issue standard SPI commands to read the flash contents. + +- SPI Probe: `tcp/:3500` + +Not all partitions are listed. Dig deeper. + +Format: **ESPILON{...}** + +--- + +## TL;DR + +Use standard SPI flash opcodes (RDID, SFDP, READ) to identify the chip, discover a hidden +partition at 0x030000 via vendor-specific SFDP parameters, read the hidden partition contents, +and XOR-decrypt the data with key `WIRED_SPI` to recover the flag. + +--- + +## Tools + +| Tool | Purpose | +|------|---------| +| `nc` | Connect to the SPI probe interface | +| Python 3 | XOR decryption | +| SPI flash opcode reference | RDID=0x9F, READ=0x03, SFDP=0x5A | + +--- + +## Solution + +### Step 1 — Connect and assert chip select ```bash nc 3500 +``` + +```text cs 0 ``` -2. Read chip ID: +> 📸 `[screenshot: SPI probe interface ready with CS asserted]` -``` +### Step 2 — Read the chip ID + +Send RDID opcode 0x9F: + +```text tx 9F ``` -Returns `EF 40 18` = Winbond W25Q128. +Response: `EF 40 18` — Winbond W25Q128 (128 Mbit SPI flash). -3. Read the SFDP table to discover hidden sectors: +### Step 3 — Read the SFDP header -``` +SFDP (Serial Flash Discoverable Parameters) reveals flash capabilities. +Send SFDP opcode 0x5A with 3-byte address and 1 dummy byte: + +```text tx 5A 00 00 00 00 ``` -SFDP header shows 2 parameter tables. Read vendor table at offset 0x80: +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]` + +### Step 4 — Read the vendor SFDP table + +```text tx 5A 00 00 80 00 ``` -Vendor data shows a hidden partition at `0x030000` labeled "HIDDEN". - -4. Read the hidden partition: +The vendor table data includes a hidden partition entry: ``` +Offset: 0x030000 +Label: HIDDEN +Size: 4096 bytes +``` + +This partition does not appear in the normal partition table. + +> 📸 `[screenshot: vendor SFDP data revealing hidden partition at 0x030000]` + +### Step 5 — Read the hidden partition + +Use the READ opcode 0x03 with 3-byte address: + +```text tx 03 03 00 00 ``` -Data starts with `WIRED_HIDDEN_PARTITION` header, followed by encrypted bytes. +The response starts with the ASCII header `WIRED_HIDDEN_PARTITION` followed by +XOR-encrypted bytes. -5. XOR the encrypted data with key `WIRED_SPI` to get the flag. +### Step 6 — Decrypt the flag -## Key Concepts +The data is XOR'd with the repeating key `WIRED_SPI`: -- **SPI flash commands**: Standard opcodes (RDID, READ, SFDP) work across most flash chips -- **SFDP**: Serial Flash Discoverable Parameters — a standardized way to query flash capabilities. Vendor extensions can hide extra information -- **Hidden partitions**: Not all storage areas appear in standard partition tables — manual probing or SFDP analysis reveals them -- **Data at rest encryption**: Simple XOR protection on stored secrets +```python +# data_hex = hex bytes from the tx read response after the header +key = b"WIRED_SPI" +encrypted = bytes.fromhex("...") # from response +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]` + +### Key concepts + +- **SPI flash commands**: Standard opcodes work across most vendors: + `0x9F` = RDID, `0x03` = READ, `0x5A` = SFDP +- **SFDP**: Serial Flash Discoverable Parameters standardises capability discovery; + vendor-specific extensions can hide extra metadata, including non-standard partition info +- **Hidden partitions**: Not all sectors appear in standard partition tables — manual + probing or SFDP analysis is required to find them +- **Data at rest XOR**: Simple XOR protection on stored secrets is common in + embedded firmware; knowing the plaintext structure (header magic bytes) allows key recovery + +--- + +## Flag + +`ESPILON{sp1_fl4sh_3xf1ltr4t3d}`