Magic Ways
Magic Ways
Platform: CUSTOM | Category: Forensics | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: chunk_crc_recalculation, ihdr_height_recovery, ocr, png_signature_repair
Summary
Walkthrough of the CUSTOM Forensics Magic Ways. Task: a corrupted challenge.png that no viewer can open, with a wiped PNG signature, zeroed IHDR height, and invalid chunk CRCs. Solution: restore the 8-byte magic signature, derive the missing height
Description
I rubbed this lamp and out came challenge.png. But, I can't open it for some reason. Help me out and maybe I'll grant you a wish (flag).
A file challenge.png is provided but cannot be opened by any image viewer. The
goal is to repair the corrupted PNG and read the flag rendered inside it.
Analysis
The title "Magic Ways" is a semantic clue pointing at PNG magic bytes
(the file signature). The flag bronco{REDACTED} confirms this.
file challenge.png reports only data, not a PNG image, so the header is
broken. A hex dump of the first bytes reveals the exact damage:
$ xxd -l 64 challenge.png
00000000: dead beef 0000 0000 0000 000d 4948 4452 ............IHDR
00000010: 0000 01f4 0000 0000 0802 0000 00... ................
Findings:
- PNG signature destroyed — the first 8 bytes are
de ad be ef 00 00 00 00instead of the correct89 50 4e 47 0d 0a 1a 0a. Thedeadbeefmarker is a classic "I was corrupted on purpose" tell. - IHDR chunk otherwise intact — length
00 00 00 0d= 13, typeIHDR.- Width =
00 00 01 f4= 500. - Height =
00 00 00 00= 0 (zeroed — this is invalid, a PNG cannot have height 0). - Bit depth = 8, color type =
02(truecolor RGB).
- Width =
- Chunk CRCs zeroed / invalid — the IHDR CRC and other chunk CRC fields were
wiped, so even after fixing the signature
pngcheckstill complains. - First IDAT length =
00 00 19 3d= 6461 bytes, zlib header78 9c.
So three things must be repaired: the signature, the IHDR height, and every chunk CRC.
Recovering the height from IDAT geometry
The width (500) is known; only the height is missing. Concatenating and inflating all IDAT streams with zlib yields exactly 300,200 bytes.
For an 8-bit RGB (3 bytes/pixel) non-interlaced PNG, each scanline is:
1 filter byte + width * 3 = 1 + 500 * 3 = 1501 bytes
Therefore the number of rows is 300200 / 1501 = 200. Cross-checking, every
inferred scanline starts with a valid PNG filter byte (0–4), confirming the
geometry is 500 × 200, so the missing height is 200.
Solution
- Restore the 8-byte PNG signature to
89 50 4e 47 0d 0a 1a 0a. - Parse the chunk stream (each chunk = length + type + data + CRC).
- Patch the IHDR height field to 200.
- Recompute the CRC32 of every chunk over
chunk-type + chunk-dataand rebuild the file with correct CRCs.
python read-only • copy allowed#!/usr/bin/env python3 import binascii import struct data = open("challenge.png", "rb").read() offset = 8 # skip the (broken) 8-byte signature chunks = [] while offset + 12 <= len(data): length = struct.unpack(">I", data[offset:offset + 4])[0] kind = data[offset + 4:offset + 8] payload = bytearray(data[offset + 8:offset + 8 + length]) chunks.append((kind, payload)) offset += 12 + length if kind == b"IEND": break # The IDAT inflates to exactly 200 scanlines of (filter + 500 RGB pixels). ihdr = chunks[0][1] ihdr[4:8] = struct.pack(">I", 200) # fix zeroed height out = bytearray(b"\x89PNG\r\n\x1a\n") # restore magic bytes for kind, payload in chunks: out += struct.pack(">I", len(payload)) + kind + payload out += struct.pack(">I", binascii.crc32(kind + payload) & 0xffffffff) open("repaired.png", "wb").write(out)
The result validates cleanly:
$ file repaired.png
repaired.png: PNG image data, 500 x 200, 8-bit/color RGB, non-interlaced
$ pngcheck repaired.png
OK: repaired.png (500x200, 8-bit/color RGB, non-interlaced)
The image renders the flag as text. Extract it with OCR:
$ tesseract repaired.png stdout
bronco{REDACTED}
Key Takeaways / Lessons
- Mastering chunk_crc_recalculation, ihdr_height_recovery, ocr, png_signature_repair was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-07-11 • CUSTOM • Magic Ways • Difficulty: Easy