We get a file called
file ./intro-forensics-3
./intro-forensics-3: data
Since the challenge talks about messed up image files, I started by checking for familiar signatures and embedded data.
binwalk -e ./intro-forensics-3
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
622927 0x9814F Zlib compressed data, best compression
Looking closer at the bytes, the file is still structured like a PNG. It has normal PNG chunks such as
So we can parse the chunks, sort the
import struct
import zlib
def extract_chunks(filename):
with open(filename, "rb") as f:
data = f.read()
chunks = []
offset = 8
while offset < len(data):
length = int.from_bytes(data[offset:offset+4], "big")
chunk_type = data[offset+4:offset+8]
chunk_data = data[offset:offset+8+length+4]
crc_value = int.from_bytes(data[offset+8+length:offset+8+length+4], "big")
chunks.append((chunk_type, crc_value, chunk_data))
offset += 8 + length + 4
return chunks
chunks = extract_chunks("intro-forensics-3")
ihdr = [data for typ, _, data in chunks if typ == b"IHDR"][0]
chrm = [data for typ, _, data in chunks if typ == b"cHRM"][0]
bkgd = [data for typ, _, data in chunks if typ == b"bKGD"][0]
iend = [data for typ, _, data in chunks if typ == b"IEND"][0]
idats = sorted(
[(crc, data) for typ, crc, data in chunks if typ == b"IDAT"],
key=lambda x: x[0],
)
with open("recovered.png", "wb") as f:
f.write(b"\x89PNG\r\n\x1a\n")
def write_chunk(chunk):
typ = chunk[4:8]
data = chunk[8:-4]
real_crc = zlib.crc32(typ + data) & 0xffffffff
f.write(chunk[:-4] + struct.pack(">I", real_crc))
for chunk in [ihdr, chrm, bkgd]:
write_chunk(chunk)
for _, chunk in idats:
write_chunk(chunk)
write_chunk(iend)
Opening the recovered image shows the flag:

CSCG{space_space_spaaaace_space!!!}