Skip to main content

c0rrupt picoCTF 2019 Solution

Repair a corrupted image file by identifying and fixing structural errors in its raw bytes.

Published: April 2, 2026Updated: August 13, 2026

Description

Fix this corrupted PNG file and read the flag: c0rrupt.png.

Download the file and inspect it with pngcheck and a hex editor.

bash
wget <url>/c0rrupt.png
bash
pngcheck c0rrupt.png
bash
xxd c0rrupt.png | head -4

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Identify corruption with pngcheck
    Observation
    The file is described as corrupted. That calls for a structured validator that reports exactly which chunks and fields break the PNG specification, before touching any bytes by hand.
    Run pngcheck on the file to see which parts are corrupt. It will report errors such as bad magic bytes, invalid chunk signatures, incorrect chunk lengths, or failed CRC checks.
    bash
    pngcheck -v c0rrupt.png

    Expected output

    c0rrupt.png  CRC error in chunk hIHD (computed 6efeef73, expected 51490945)
    ERROR: c0rrupt.png
      invalid chunk name "CgBI" (43 67 42 49)
    FATAL: c0rrupt.png is not a PNG image
    What didn't work first

    Tried: Open the file directly in an image viewer to see what is broken

    Most image viewers either refuse a corrupted PNG or quietly show a blank or partial image, with no diagnostics. They will not tell you which bytes are wrong or which chunk failed. pngcheck reads the raw structure and names the exact offset and field for each violation, which is what targeted edits need.

    Tried: Run 'file c0rrupt.png' to diagnose what is wrong with the file

    The file command only reads the magic bytes to guess a type, so it happily reports 'PNG image data' even when every internal chunk is broken. It catches nothing about bad CRCs, invalid chunk names, or a corrupted IHDR. pngcheck does the full structural validation instead.

    Learn more

    A valid PNG file has a specific structure: 8 magic bytes at the start (89 50 4E 47 0D 0A 1A 0A), followed by chunks. Each chunk has a 4-byte length, a 4-byte type name (like IHDR, IDAT, IEND), the data, and a 4-byte CRC32 checksum.

    pngcheck validates all of these fields and reports exactly where the file deviates from the PNG specification.

  2. Step 2Fix the magic bytes
    Observation
    pngcheck reports an invalid file type before it even reaches the chunks. That points at the first 8 bytes, which need overwriting with the canonical PNG magic number.
    Use a hex editor (ghex, hexedit, or bless) to open c0rrupt.png. Check bytes 0-7. If they do not match 89 50 4E 47 0D 0A 1A 0A, overwrite them with the correct values.
    bash
    hexedit c0rrupt.png
    What didn't work first

    Tried: Use 'strings c0rrupt.png' to find the correct magic bytes

    strings only prints printable ASCII runs above a minimum length. The PNG magic bytes include non-printable control characters (0x89, 0x0D, 0x0A, 0x1A) that strings skips entirely. Use a hex editor such as hexedit or xxd to view and edit raw bytes at specific offsets.

    Tried: Patch the magic bytes with sed or a text editor

    Text editors and sed work in text mode and can silently alter or strip non-printable bytes on save. The PNG header contains bytes outside printable ASCII, so any text-mode tool will damage it. Use a binary-aware tool: hexedit, ghex, or a Python script opening the file with 'rb'.

    Learn more

    The PNG magic number is deliberately chosen to be hard to confuse with text files: byte 0x89 is non-ASCII, the next four bytes spell PNG in ASCII, and the remaining bytes include CR, LF, and SUB control characters that behave differently across text-mode file transfers - helping detect corruption.

  3. Step 3Fix chunk signatures and CRCs
    Observation
    pngcheck lists a CRC mismatch in the hIHD chunk alongside an invalid chunk name. So the chunk type bytes and their checksums were both tampered with, and both need correcting with zlib.crc32.
    After fixing the magic bytes, run pngcheck again. Fix any remaining chunk type name errors (e.g., a corrupted IHDR signature). Recompute and fix any CRC32 values using Python.
    python
    python3 -c "
    import struct, zlib
    # To compute correct CRC for a chunk:
    # chunk_type = b'IHDR'
    # chunk_data = b'...'  # chunk data bytes
    # crc = zlib.crc32(chunk_type + chunk_data) & 0xFFFFFFFF
    # print(hex(crc))
    "
    What didn't work first

    Tried: Compute the CRC with zlib.crc32(chunk_data) without including the chunk type bytes

    The PNG spec computes each CRC over the chunk type and the chunk data joined together, not the data alone. Pass only the data to zlib.crc32 and you get a checksum pngcheck rejects. Use zlib.crc32(chunk_type + chunk_data), where chunk_type is the 4-byte name like b'IHDR'.

    Tried: Skip fixing CRC values and just open the PNG, hoping the viewer ignores checksum errors

    Lenient viewers like eog may render the image despite bad CRCs, but pngcheck still fails it and the file is technically invalid. More to the point, a wrong IHDR CRC makes some decoders reject the file outright before they read the dimensions. Fixing the CRCs is also how you confirm the chunk data is right: if the recomputed value matches nothing, the data is still corrupted.

    Learn more

    CRC32 (Cyclic Redundancy Check) is a hash function used to detect accidental changes. The PNG spec requires that each chunk's CRC be computed over the chunk type and data bytes combined. If the data is correct but the CRC is wrong, recomputing and overwriting fixes the error.

    In Python, zlib.crc32(data) computes the CRC32 value. Always AND with 0xFFFFFFFF to get an unsigned 32-bit result, then pack with struct.pack('>I', crc) for big-endian byte order.

  4. Step 4Open the repaired PNG
    Observation
    pngcheck reports no errors once the magic bytes and CRCs are fixed. The structure is valid again, so the image will decode and display the flag.
    Once pngcheck reports no errors, open the file in an image viewer. The flag will be visible in the image.
    bash
    xdg-open c0rrupt.png
Interactive tools
  • File Magic IdentifierIdentify file types from magic numbers. Paste hex bytes or drop a file to detect PNG, JPEG, ZIP, PDF, ELF, PCAP, SQLite, and dozens of other formats.

Flag

Reveal flag

picoCTF{c0rrupt10n_...}

Fix the PNG magic bytes and repair chunk CRC values with a hex editor to restore the image.

Key takeaway

Binary formats encode their structure in fixed-position magic bytes, chunk headers, and integrity checksums, and knowing those specs lets you repair or forge a file by hand. PNG stores a CRC32 with every chunk so parsers can spot corruption, but anyone who controls the data can recompute valid checksums and make a malformed file look intact. The same skill carries into ZIP, ELF, PDF, and PE, where magic bytes and header fields are the first thing analysts and exploits both inspect.

Related reading

Tools used in this challenge

Where to go next