Pictorial mess

Pragyan CTF 2018 - Steganography (300 pts).

Pragyan CTF 2018: Pictorial mess

Challenge details

Event Challenge Category Points Solves
Pragyan CTF 2018 Pictorial mess Steganography 300 66

Download: files.zip - md5: 7b9178aa713d584c7811725a1289dda9

Description

Johnny had an image that he was going to use for a very important purpose. Someone had hacked into his system and tampered with the image. Help him recover it.

TL;DR

In this task we had analyze 7 images. Both of them had messages hidden in their LSB (discovered with Stegsolve By Caesum). The extracted message was “Make me Tall”. Due to this message, we increased the images height of 25px. This task has been accomplished with TweakPng but could be accomplished by editing the hexa of the file. Increasing the size show us 7 new line with white and black square (0 and 1). We extracted the 7 line and took each first square then each second square… The flag was coded in the extracted coloumns, in ascii (7 bits).

Methology

Looking at the files

The first thing we did was opening the files contained in files.zip. The archive was containing 7 images named 0.png to 6.png :

0.png 1.png 2.png 3.png 4.png 5.png 6.png

… Nothing apparent there. We decided to do some stega research on it.

LSB

LSB is the most common Steganography technic used in CTF. I decided to check if the previous images contain an hidden message using this technic. For this, I used the tool named “Stegsolve” by Caesum. The tool is written in Java (jar file) and allow us to “navigate” into the different bits layers.

Here is the first image analysed with Stegsolve:

Stegsolve

Nice ! We extracted a part of a message. Here are earch parts of the message:

LSB0_Red LSB1_Red LSB2_Red LSB3_Green LSB4_Blue LSB5_Green LSB6_Green

The extracted message is : MakeMeTall. This wasn’t the flag.

Increasing size

With png image, we are able to resize image size by directly editing the binary file. This kind of resize will just affect the image size and not the data contained by the image. Considering the hint we got in the LSB, I decided to “Make the images taller”: data may be hidden in the images but not displayed due to the actual image size.

The first time I did the manipulation, I looked at the png chunck structure.

http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html

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

I decided to change the height of the first image and increasing it 25px more.

$xxd 0.png | head -n 5
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
00000010: 0000 0190 0000 017c 0806 0000 00e1 39ed  .......|......9.
00000020: 3500 0000 0467 414d 4100 00b1 8f0b fc61  5....gAMA......a
00000030: 0500 0004 1969 4343 506b 4347 436f 6c6f  .....iCCPkCGColo
00000040: 7253 7061 6365 4765 6e65 7269 6352 4742  rSpaceGenericRGB

Here, the image height is 017c (380), I changed it to 0195 (405):

$xxd new0.png | head -n 5
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
00000010: 0000 0190 0000 0195 0806 0000 00e1 39ed  .......|......9.
00000020: 3500 0000 0467 414d 4100 00b1 8f0b fc61  5....gAMA......a
00000030: 0500 0004 1969 4343 506b 4347 436f 6c6f  .....iCCPkCGColo
00000040: 7253 7061 6365 4765 6e65 7269 6352 4742  rSpaceGenericRGB

We got the following image:

0.png

We could use this technique to increase each image, but I preferred to used the TweakPng tool which can do it for us:

0.png

Here are the extracted images:

new0.png new1.png new2.png new3.png new4.png new5.png new6.png

We can see 7 lines with white and black square. I converted it to 0 and 1:

Image 0: 11111101111110101111
Image 1: 11111011111111111111
Image 2: 10101011000101110011
Image 3: 00001001110010000101
Image 4: 00110000111100001011
Image 5: 01011110110001101000
Image 6: 01001011100001111001

We know that we were looking for a flag starting with pctf:

p: 01110000
c: 01100011
t: 01110100
f: 01111011

After few observation, we noticed that the flag was written vertically, 1 char per column, using only 7 bits.

img0 = "11111101111110101111"
img1 = "11111011111111111111"
img2 = "10101011000101110011"
img3 = "00001001110010000101"
img4 = "00110000111100001011"
img5 = "01011110110001101000"
img6 = "01001011100001111001"

flag = ""
for i in range(len(img0)):
    c = img0[i]+img1[i]+img2[i]+img3[i]+img4[i]+img5[i]+img6[i]
    flag += chr(int("0b"+c,2))

print(flag)

FLAG !

FLAG

pctf{B3yondth3s1ght}

Zeecka