⬅ go back

Unknown Soldier 2

Published on Mar 22, 2024 by Kalitsune.

#

steganography

#

ctf

Original Challenge description 🇫🇷
En ouvrant la boîte du soldat inconnu, qui n'est plus si inconnu que ça, vous tombez sur une image. Selon la description, il s'agit d'une photo du soldat fraîchement enrôlé. Vous vous dites que cela serait un beau geste que de l'envoyer à sa famille en tant que dernier souvenir. Malheureusement, elle a été endommagée, essayez de la réparer avant de l'envoyer.
Challenge description 🇺🇸
When you open the box of the not-so-unknown soldier, you come across an image. According to the description, it's a photo of the freshly enlisted soldier. You think it would be a nice gesture to send it to his family as a last memento. Unfortunately, it's been damaged, so you try to repair it before sending it.
# Write up

Challenge inspection

The challenge isn’t necessarily provided with any file, however, in Unknown Soldier (1) we got a file named picture_of_me.png. This file appears to be an image, however there’s one small issue: the file is not readable.



The photo

Meme computer guy thinking

This is strange but not unexpected, we’re in a challenge of steganography after all. I continue my inspection by using pngcheck to try to find the issue.

 pngcheck picture_of_me.png 
picture_of_me.png  invalid IHDR image dimensions (25231972x0)
ERROR: picture_of_me.png

It appears that the image has invalid dimensions.

Investigating the issue with the image header

To check what’s wrong with the header, you’ll need to open the file using an hex editor.

I’m personally using GHex, a GNOME hex editor.

The first line of our file looks like this:

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 01 81 02 64 00 00 00 00 08 06 00 00 00 F7 38 9D 88 00 00 00 04 67



Meme stressing out that we don't have much time left to solve this challenge

I took the liberty to color the bits of data that are relevant.

Okay so, what are we seeing?

According to https://en.wikipedia.org/wiki/List_of_file_signatures, the signature for the PNG file format is 89 50 4E 47 0D 0A 1A 0A. Which is great because that’s exactly what we have! This mean that we are indeed looking at a PNG file.

After googling for a bit I also found the PNG Format Specifications according to which, a PNG chunk of data is organised this way:

[Length (4 byte)] [Chunk Type (4 byte)] [Data (any)] [CRC (4 byte)]

The length value is not really useful for now so let’s skip it and check what’s the chunk type. I was able to find that the signature of my chunk ( 49 48 44 52 ), matched the signature of an IHDR Image header. Which is really interesting because according to the [PNG Format Specs](http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html, the IHDR chunk is the one containing the image size information.

Let’s take a closer look to the data in this chunk then:

DATA Width Height Bit depth Color type Compression method Filter method Interlace method
Bytes 4 4 1 1 1 1 1

In this field we find that the dimensions of this file are indeed corrupted. The rest of the data looks fine.

To fix them we’ll have to use the CRC bytes which allows partial repair in case of damage.



Always read the docs

Getting the headers dimensions back

As mentioned earlier, the CRC field may just be able to help us repair this image as it is just like a hash and we only have two values to find.

We’ll just have to brute force the Height and Width of the image until we find a CRC that match:

from binascii import crc32

# Put your CRC as bytes here:
correct_crc = int.from_bytes(b'÷8ˆ',byteorder='big')

for h in range(2000):
    for w in range(2000):
	    #      IHDR HEADER               WIDTH                        HEIGHT               REMAINING DATA (healthy)
        crc=b"IHDR"+w.to_bytes(4,byteorder='big')+h.to_bytes(4,byteorder='big')+b""
	    # If it match the CRC
        if crc32(crc) % (1<<32) == correct_crc:
            print ('FOUND!')
            print ('Width: ',end="")
            print (hex(w))
            print ('Height :',end="")
            print (hex(h))
            exit()

And hooray! We found something:

FOUND!
Width: 0x181
Height :0x264

This mean that by jumping back into the hex editor and editing the Width and Height fields, we can finally fix this image! Let’s edit our header right away:

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 01 81 00 00 02 64 08 06 00 00 00 F7 38 9D 88 00 00 00 04 67



We fixed it!

The only thing left to do is save.

I ran a quick pngcheck just to be sure:

 pngcheck fixed.png 
OK: fixed.png (385x612, 32-bit RGB+alpha, non-interlaced, 55.7%).

And everything seemed good!

I then opened the file and was greeted by this:

The image obtained

Awesome! We did it! The flag is:

NBCTF{m0n_b3ll3_un1f0rm3}

As we say in french: Champagne!

champagne!