MEfactory
Author: 0xIDA
Platform: FlagYard · Category: forensics · Difficulty: Hard
Solvers
Summary
SPI flash dump of a synthetic Intel ME-style image. The factory provisioning secret is AES-128-CBC ciphertext stored in a custom ME page; the real 16-byte key lives in another page. Planted KEY=/ALGO= strings and dozens of not_flagY{...} decoys are red herrings.
Solution
Step 1: Triage the flash image
unzip MEfactory.zip
7z x MEfactory/flash.bin.7z
file flash.bin # Intel serial flash for PCH ROM, 8 MiB
strings -n 8 flash.bin | head
Notable planted strings:
ME Firmware Version 12.0.0.1/[Network]/[System]config pages- Many
not_flagY{...}decoys scattered in high-entropy filler # Intel ME debug build - DO NOT SHIP+KEY=e9f1fcde30c2d63+ second hex line +ALGO=AES-128-CBC(decoy key material; ECB with that key even yieldsnot_flagY{recove...})
Step 2: Parse the custom ME-like page FS
Sparse pages every 0x2000 from 0x21000 use a simple header (id, sequential type 0x10.., 0xfffffffe marker) and a length-prefixed record at +0x80:
u16 unk | u16 length | u16 flags (0xffff = clear payload) | u16 pad | payload[length]
Important records:
| Offset | Length | Role |
|---|---|---|
0x2b088 | 16 | AES-128 key (binary) |
0x31088 | 48 | AES-128-CBC ciphertext (3 blocks, PKCS#7) |
0x29088 | 40 | Cleartext [Network] config |
0x2d088 | 42 | Cleartext [System] config |
Step 3: Decrypt with the page key (IV = zeros)
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
data = open("flash.bin", "rb").read()
key = data[0x2B088:0x2B098]
ct = data[0x31088:0x31088 + 48]
pt = unpad(AES.new(key, AES.MODE_CBC, iv=b"\x00" * 16).decrypt(ct), 16)
print(pt.decode())
# FlagY{8b4e2d7c9f1a6e3b5d0f8c4a7e2b9d6f}
Key: 4b0d0ef612000d6a50179b71dbd2450a
IV: 16 zero bytes
Ciphertext: b3ea48d570e1c5b47cf0405a2ee8296b1f37f22345c0848869703ca9b39b2d2db30fe6081ab1ecf865e576f7f4e128f4
Flag
FlagY{8b4e2d7c9f1a6e3b5d0f8c4a7e2b9d6f}
Live submit: success (lab 14 / b7208a95-3615-419a-9361-4390d635033b).
Tools
file,7z,strings,xxd,ifdtool(descriptor is largely fake/zeroed)- Python 3 +
pycryptodome(AES-CBC + PKCS#7 unpad)
Pitfalls
- Do not submit any
not_flagY{...}string. - The
KEY=/ALGO=AES-128-CBCdebug block is intentional bait; combining its hex lines into a 16-byte key decrypts garbage / decoy text, not the flag. - Real IFD parsing (
ifdtool -d) is noisy here — FRMAP fields are zeroed; treat the image as a challenge-specific layout, not production ME firmware.