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 :
… 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:
Nice ! We extracted a part of a message. Here are earch parts of the message:
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:
We could use this technique to increase each image, but I preferred to used the TweakPng tool which can do it for us:
Here are the extracted images:
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