c0rrupt: PNG Binary Specification & Hex Reconstruction

“We found this file. Recover the flag. You can also find the file in /problems/c0rrupt_0_1fcad1353b2255f250d60c14afed2100 on the shell server.”
picoCTF{...}💡 THE INTUITIVE ANALOGY (Why did the image break?)
Imagine receiving a sealed shipping container. The barcode on the outside is smudged, the label that says what is inside is torn off, and the weight sticker doesn't match the contents. The customs inspector immediately refuses to process it. That is exactly what happens when your OS tries to open mystery. The challenge creator took a legitimate PNG image and intentionally sabotaged 4 specific barcode and header bytes so every image viewer rejects it as corrupted.
1. The W3C PNG Binary Standard
To repair any damaged image file, you must master the binary architecture of the PNG (Portable Network Graphics) standard. Every valid PNG has two components:
1. The 8-Byte Magic Header (Official Signature):
Hex: 89 50 4E 47 0D 0A 1A 0A
ASCII: \x89 P N G \r \n \x1a \n
2. Sequential Data Chunks (Each chunk follows this exact 4-field rule):
┌──────────────────┬──────────────────┬──────────────────────────┬──────────────────┐
│ Length (4 Bytes) │ Type (4 Bytes) │ Data (Length Bytes) │ CRC32 (4 Bytes) │
├──────────────────┼──────────────────┼──────────────────────────┼──────────────────┤
│ 00 00 00 0D │ 49 48 44 52 │ Width, Height, Bit Depth │ 7C 8B AB 78 │
│ (13 bytes data) │ ("IHDR" ASCII) │ Color Type, Compression │ (Checksum test) │
└──────────────────┴──────────────────┴──────────────────────────┴──────────────────┘If the chunk name is misspelled or the Length doesn't match the number of data bytes, the CRC32 check fails, and the image viewer aborts rendering.
2. Diagnostic Reconnaissance with `pngcheck`
Before touching any bytes, we run the automated diagnostic utility pngcheck to pinpoint the exact failing offsets:
3. Manual Hex Surgery (Click-by-Click via Hex Editor)
Learn how to edit raw bytes manually using HexEd.it (in your browser) or HxD on Windows.
🛠️ Manual Setup Instructions:
- Open https://hexed.it/ in Chrome/Edge or open HxD.
- Click Open file and select
mystery. - CRITICAL RULE: Make sure the mode at the bottom says OVR (Overwrite), not INS (Insert). (Insert pushes old bytes and ruins the file size).
- Never press Spacebar! The editor automatically advances to the next box after every 2 characters.
Why it broke: The author replaced .PNG with .eN4.
Why it broke: Right after the 4-byte length 00 00 00 0D, the chunk type spells C"DR instead of IHDR.
Why it broke: The pHYs chunk defines physical pixels per meter ($5669 \times 5669$). An extra corrupted byte AA threw off the chunk length and CRC checksum.
Why it broke: The actual image pixel data chunk header was scrambled from IDAT into \xabDET with an invalid length prefix.
0x00031851 in hex.💾 In HexEd.it, click Export → Save as fixed.png → Open with Windows Photo Viewer!
4. The 0.1-Second Python Fixer (`solve.py`)
In competition environments, manually typing hex bytes is too slow. Once you know what chunks are broken, you write an automated Python script using bytearray to slice and replace the corrupted segments in memory in 1 millisecond:
# Open the corrupted mystery file as raw bytes
with open("mystery", "rb") as f:
data = bytearray(f.read())
# Fix 1: PNG Magic Header (Bytes 0 to 7)
data[0:8] = b"\x89PNG\r\n\x1a\n"
# Fix 2: First chunk name -> IHDR (Bytes 12 to 15)
data[12:16] = b"IHDR"
# Fix 3: pHYs chunk data (Offset 0x46)
data[0x46:0x4A] = b"\x00\x00\x16\x25"
# Fix 4: IDAT chunk length and name (Offset 0x53)
data[0x53:0x5B] = b"\x00\x03\x18\x51IDAT"
# Save the fully repaired image
with open("fixed.png", "wb") as f:
f.write(data)
print("🎉 Successfully repaired! fixed.png generated.")python -c "d=bytearray(open('mystery','rb').read()); d[0:8]=b'\x89PNG\r\n\x1a\n'; d[12:16]=b'IHDR'; d[0x46:0x4A]=b'\x00\x00\x16\x25'; d[0x53:0x5B]=b'\x00\x03\x18\x51IDAT'; open('fixed.png','wb').write(d); print('fixed.png generated!')"5. Restored Evidence & Extracted Flag
Visual Verification of Repaired Image (fixed.png):

6. DFIR Diagnostic Cheat Sheet
| Tool / Utility | Syntax | Purpose |
|---|---|---|
| pngcheck | pngcheck -v file.png | Verifies magic bytes, chunk sequence, CRC32 checksums, and reports offset of failure. |
| HexEd.it / HxD | GUI Hex Editor (OVR mode) | Allows manual byte-by-byte carving, patching, and binary inspection. |
| Python bytearray | data[start:end] = b"..." | Instant programmatic byte patching in memory without installing external tools. |
7. The Complete Investigation Path & Mental Roadmap
Here is the complete chronological path and thought process from the initial broken file to the final extracted flag:
Downloaded mystery. Opening it failed with “Invalid image format”. Running pngcheck -v mystery flagged invalid signature bytes at offset 0x00.
Opened file in HexEd.it. Discovered .eN4 instead of .PNG. Replaced bytes 0..7 with official PNG signature 89 50 4E 47 0D 0A 1A 0A.
Fixed corrupted chunk name C"DR back to IHDR. Removed extra stray byte AA from pHYs chunk to fix pixel resolution and restore CRC32 checksum.
Calculated exact remaining payload size (202,887 - 54 = 202,833 bytes = 0x00031851). Replaced corrupted \xabDET with 00 03 18 51 49 44 41 54.
Exported fixed.png. Double-clicked image to render the visual flag: picoCTF{c0rrupt10n_15_n3v3r_50_b4d_534e7cb8}.