Swiss Hacking Challenge 2023 - white

Posted on Apr 24, 2023

Information

Challenge category: misc

Challenge Description

The picture that consists of only one color, white, would be a blank canvas with no visible markings or patterns. The white color would fill the entire surface area of the picture, giving it a clean and simple appearance. There would be no contrast or shading to create depth or texture, as white is a uniform color that reflects all light. The picture may evoke feelings of emptiness, and neutrality, as white is often associated with these concepts.

Files

We are given a white.zip file. It contains just a white picture, nothing else (at least that’s what they are wanting us to think).

After running file white.png, I got the following:

white.png: PNG image data, 255 x 255, 1-bit grayscale, non-interlaced

Analysis

When using FotoForensics, a free online tool, I noticed the following:

We have hidden columns?

Based off that, we have to add one pixel to the right end of the image. We could also just use the output from FotoForensics but we can do better.

Exploitation

Trying to modify the header using a hex editor

To modify the images width, we must understand the IHDR specification:

The IHDR chunk must appear FIRST. It contains:

   Width:              4 bytes
   Height:             4 bytes
   Bit depth:          1 byte
   Color type:         1 byte
   Compression method: 1 byte
   Filter method:      1 byte
   Interlace method:   1 byte

So I opened up the image in GHex and searched for the IHDR mark:

The IHDR, width and height in GHex

I changed the width value from 00 00 00 FF to 00 00 01 00 and saved the image.

Welp. It didn’t really work and even after calculating the CRC the image seemed corrupted. So I decided to go yet another way.

Using tweakpng

As the menace hex editing route didn’t work I downloaded tweakpng (which also runs under Linux using WINE) and changed the image size to 256x255 in the IHDR chunk. This worked just fine.

Exploitation

The last line seemed to be binary so I wrote the following script that reads the last pixel of every row and prints the decoded message in the end:

from PIL import ImageFile,Image
import sys
# Pillow would break without this
ImageFile.LOAD_TRUNCATED_IMAGES = True
# Load the image
im = Image.open("white.png")

# Get the image dimensions
width, height = im.size

# Empty array for binary numbers
binary_pixels = []
# Loop through every row
for h in range(height):
    pixels = im.getpixel((width-1,h))
    # Black pixels represent a 0
    if pixels > 0:
        binary_pixels.append(1)
    else:
        binary_pixels.append(0)

# Binary to ASCII
for i in range(0, len(binary_pixels), 8):
    byte = binary_pixels[i:i+8]
    print(chr(int(''.join([str(bit) for bit in byte]), 2)), end='')

Flag

The script prints the flag:

shc2023{y0u_guy5_ar3_da_b35t}

Conclusion

I actually only stumbled upon the FotoForensics page after searching throigh many other things. Resizing the PNG also proved to be a difficult task in the beginning, however after I understood the whole IHDR stuff it was relatively simple. Nice challenge but I wasted quite some time.

References

  1. https://fotoforensics.com/
  2. https://www.w3.org/TR/PNG-Chunks.html
  3. https://entropymine.com/jason/tweakpng/