PoliCTF Write-Up Forensics 200

November 19, 2012

The challenge was given as BMP-File and had the description:

The file is big 54+PixelArraySize.

The description is hinting at the wikipedia entry for the BMP file format. Although the category was called “Forensics”, this seemed like a steganography challenge right from the start. We opened the file in StegSolve to get a first look. What was visible quite soon was the fact that looking a the least significant bit-planes showed no discernible picture at all, whereas starting from bitplane 4, the original picture could be made out.

This leads us to believe that there might be some information hidden in the least significant 4bits of each byte. As it would be hard to hide information in the BMP header without destroying it, we assume that the information is only stored in the “data bytes”. Thus, we skip the header of 54 bytes and start extracting 4bits/byte from this. We did this using this script:
c = open("file.bmp","rb").read()[54:]
newfile = ""
for i in range(len(c)/2):
  first  = ord(c[2*i])   & 0xf;
  second = ord(c[2*i+1]) & 0xf;
  result = (first << 4) + (second)
  newfile += chr(result)
By doing this, we get a second picture.

Now, we look at the hint in the description again. It tells us that how the size of a BMP is calculated. The picture we just received is 500x277px, so based on the formula given by Wikipedia, we should have a file which is 415,554bytes. However, the BMP is 436,800bytes. So, lets look “behind” the BMP to figure out, what is there. It turns out, what is looking to be garbage at first glance, starts with 0x37 0x7a – which is “7z”. So, is there a 7z hidden behind the picture?
Appearantly, there is. We extracted the 7z and already thought “yeah, we found it!”. However, it asks us for a password and trying “Bitches, Bitches everywhere” did not work. The organizers gave out a hint stating that one should “Go deeper”. Opening the file in StegSolve again isn’t much help at first. However, if we take a closer look at the separate bitplanes, we can see one very interesting thing:
The fact of the matter is, that although the text in the BMP is all white, there is some noise in bitplanes 0 and 1. There is however no (or almost no) noise in the higher bitplanes. So, in a next step, let’s try to extract just 2bits/byte, again skipping the BMP header. This yields a third picture, which is the previous one –  just smaller.

Now, it’s time for the kids to ask “Are we there yet?” – and us to answer “No, not yet”. As one might have presumed, we now look at only the least significant bit in the new picture (first it was 4bits, then 2bits, so this makes sense). This gives us – no, not a Bitmap! It actually gives us text + garbage. The text states:
This is not the key you are looking for

This, however, is the key needed for the 7z. It reveals a file called “key”, which contains the string

This is the real key or anhoter part od challenge

So, we ask again “are we there yet?” – this time, we can answer with “Yes” and be very happy to have finished this onion challenge.

6 Responses to “PoliCTF Write-Up Forensics 200”

  1. Yo,

    Good write up ! But I was not able to repeat the first step. Could you help me ? I’m perfectly noob in forensic but that one seems interesting p:
    What do you mean with “skip the header of 54 bytes and start extracting 4bits/byte” ? What kind of operations are you doing here exactly ? Do you copy the same header and then just apply a mask on the others bytes keeping the last 4 bits ? Or is it a more complicated way like combining the last bits in different bytes or something else … ?

    Thanks and GG again !

  2. Hi,
    we can hardly hide any information in the header, as we would then break it. The BMP header at offset 0xA stores (in 4bytes) the offset of the actual data relative to the beginning of the file. If you look at the original file in a hex editor, you can see that its hex value (big-endian) is 0x00000036, which is 54 in decimal. This shows us where the actual pixel data is stored. It makes sense to try and hide stuff in there only as you can hardly notice a difference when the changes are small.

    For all subsequent pictures, the header always consumes the aforementioned 54b.

    Hope this helps 🙂

  3. In fact the part I didn’t understand is what operations did you do exactly on the data to extract the Toy Story picture from the first file. Is it a simple binary mask ? Something else ?

    Thx for helping 😉

  4. I posted an update showing the code 🙂 The same works in a similar manner for only 2bits and only the 1bit.

  5. Ok then I understand what is done. Thx a lot ! 🙂

  6. “This leads us to believe that there might be some information hidden in the least significant 4bits of each byte.” How do you know that ? Why it is 4bits and not for example 5bits ?

Leave a Reply