Link: https://score.ctf.westerns.tokyo/problems/22 (only for logged in users)
Points: 100
Category: Misc
Description
This problem is not image based on steganography.
tl;dr
Take data from IDAT chunk, decompress it and grep for TWCTF.
Solution explanation
The first step in every image based challenge is to look at its metadata:
1 2 3 4 5 6 7 8 |
$ identify -verbose ninth.png Image: ninth.png Format: PNG (Portable Network Graphics) (...) Geometry: 1200x848+0+0 (...) identify: Extra compressed data. `ninth.png' @ warning/png.c/MagickPNGWarningHandler/1671. identify: Extra compression data. `ninth.png' @ warning/png.c/MagickPNGWarningHandler/1671. |
We can notice two important things while solving this task:
- image size is 1200x848px
- identify notices some Extra compressed/compression data – the flag?
To understand what it means, basic knowledge of PNG “backstage” is required.
PNG data is organized as chunks. A chunk is a set of bytes containing the following information:
- Length – 4 bytes
- Chunk type – 4 bytes
- Chunk data – Length bytes
- CRC – 4 bytes
One of chunks type is
IDAT. There can be many of them in one PNG file.
IDAT chunks contain compressed information about pixels in the image.
We can get this information with simple
Python script:
1 2 3 4 5 6 7 8 |
import png import zlib def get_decompressed_data(filename): img = png.Reader(filename) for chunk in img.chunks(): if chunk[0] == "IDAT": return zlib.decompress(chunk[1]) |
This function returns 4071274 bytes. They are organized in scanlines which represent information about pixels in each line of an image (3 bytes per pixel) with one additional byte representing filter applied to this line. Knowing that, we can calculate how many bytes we should have and remove them (we are only interested in that “additional compressed data”).
9 10 11 12 13 14 15 |
data = get_decompressed_data("ninth.png") image_width = 1200 image_height = 848 bytes_per_pixel = 3 bytes_per_filter = 1 data = data[(image_width * bytes_per_pixel + bytes_per_filter) * image_height:] print ''.join([x for x in data if x in string.printable]) |
1 2 |
$ python solve.py TWCTF{WAMP_Are_You_Ready?} |
Leave a Reply
You must be logged in to post a comment.