[write-up] RuCTF 2016 Olympiad - ddisk, bigpic, deadpixel, damaged_v2

The Olympiad was a contest on the second day of the RuCTF 2016 conference in Yekaterinburg, Russia.
I attended the RuCTF Finals with the team ENOFLAG of the TU Berlin and thus decided to have a go at the Olympiad tasks as well.
While not beeing able to solve more than one task that day I took the time and revisited the tasks after the trip was over.
That proved to be more successful.

During the Olympiad the internet was limited to the google.ru cache, and a few other sites (mainly mirrors so you could install software). That made searching for stuff quite hard.

ddisk Challenge

For this challenge we were given a dd dump of a disk that was corrupted as it was unplugged while copying the data.
We were told that there is a file with the name "iCantRememberTheName.jpg" (I can't remember the exact name) that holds the flag.

If you used some random data restore tool you would be able to extract 83 valid JPG files without the original filenames.
All of these contained a string written in a small box that looked like a flag.
One of the files
Trying to transcript all of them and trying to submit them would have been an option, although not a nice one.

Upon looking further and using the "testdisk" program I found that there were two partitions.

PartitionStart End Size in sectors
Linux 0 32 33 4 52 48 65536
P HPFS - NTFS 4 52 49 16 81 1 194560

On of them is a NTFS partition which is known to hold filenames.
If you used this partition and then listed the files that was confimed:
Woha! Filenames.

You could then just search for the right filename, copy the file to disk and then submit the flag.

bigpic Challenge

I almost solved this challenge during the contest but an unnoticed mistake in my script made me skip it later.

In this challenge we were given 50 different files. I assumed that they were image files because of the name of this challenge "bigpic". They were however not valid files so one couldn't just open them.

I thought that you maybe had to concatenate all the files to one big file. That would mean that there is one file that contains a valid JPG header.
A short run of the following bash command confimed my thought:
for file in ./*;do file "$file"; done | grep image
./43: JPEG image data, JFIF standard 1.01

So file number 43 was the first part of our picture. I then figured out that the end of this file could be found in another file. That means that all the different parts overlap each other.
So one could try to find these overlaps, concatenate the files and then check if a valid image remained after all the files were used.

I wrote a short python script, that did exactly that and after a few seconds the following output occured:
Found overlap 9 48 at 48
Found overlap 48 26 at 52
Found overlap 26 34 at 38
Found overlap 34 36 at 84
Found overlap 36 39 at 52
Found overlap 39 30 at 429
Found overlap 30 41 at 358
Found overlap 41 23 at 350
[43, 35, 19, 16, 6, 50, 1, 49, 46, 42, 32, 17, 15, 45, 20, 40, 10, 37, 14, 2, 12, 22, 44, 21, 7, 24, 5, 25, 31, 38, 4, 8, 28, 33, 3, 47, 18, 13, 27, 29, 11, 9, 48, 26, 34, 36, 39, 30, 41, 23]
We got a valid image

I had a look at the image and there was out flag:
Bigpic flag

deadpixel Challenge

We were given a .mov file that contained a short video.

I tried several things I knew from past CTFs but none of them worked.

This task was not solved by me during the olympiad as I didn't notice the dead pixel in the upper left corner. Might the party the day before have had an impact here? I can neither deny nor confirm this assumption.
The dead pixel
Yes, there was a pixel in the upper left corner that switched from white to black all the time.
That sounds as if it is talking binary and the organizers want us to read its value.
Of course on could do that manually but I figured a short python script will do a better job than me.

I extracted all the frames with ffmpeg:
ffmpeg -i rick_and_morty_episode_96ebc0dba47.mov -vcodec png -an pngs/test%03d.png

and then used the python script to loop over all files.
The script reads the pixel at 13, 37 and converted it to a 0 or a 1 depending on the value.

That worked just fine and after converting the bitstring to human readable text I got the flag:
There seems to be a dead pixel at 13,37 that switches from white to black.
Let us get the value of that thing.
0 1 0 1 0 0 1 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 1 1 0 1 0 1 0 1 0 0 0 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 0 0 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1 0 0 1 1 0 0 0 1
Found flag. Convert:


damaged_v2 Challenge

We were given a .png file that didn't open because it was corrupted. Standard tools didn't do the job of fixing what was wrong with this one.

We could however use pngcheck to see what was wrong with the file:
pngcheck -f -p task.png
File: task.png (6120 bytes)
task.png invalid IHDR sample depth (0)
task.png CRC error in chunk IHDR (computed 296e6380, expected b317e0ca)
ERROR: task.png

There are two errors. The sample depth was invalid and the CRC sum didn't match for this block.
The second error seems to be the result of the invalid value for the sample depth.

Using a cached version of the PNG Chunk specifications I got the following information:
Color Type Allowed Bit Depths Interpretation
0 1,2,4,8,16Each pixel is a grayscale sample.
28,16Each pixel is an R,G,B triple.
31,2,4,8Each pixel is a palette index;
a PLTE chunk must appear.
48,16Each pixel is a grayscale sample,
followed by an alpha sample.
68,16Each pixel is an R,G,B triple,
followed by an alpha sample.

I then iterated through all color types for grayscale images (to medium success) but hit gold when I tried the ones for RGB triples. One had to readjust the CRC sum after each change but that was just a minor effort.

The path to success in images looked approximately like that:
That is the first attempt

That looks better

That one has the flag

Denis Werner