Hack.lu 2011 CTF Write-up: Unknown Planet

This week we participated in the Hack.lu 2011 CTF, a Capture-The-Flag event organized by the FluxFingers team at Hack.lu. Even if we were only three with two other members playing at night, we placed 6th out of >100 teams! Congrats to FluxFingers for the wonderful work done, we enjoyed it so much.

This is our first write-up for this CTF, hopefully more will come.

The challenge consists of a single jpg file called “8c4f14e28155a2c3cf4b2538c1e0958b”:

and the following string:

“We got this file. Can you find the name of this planet?”

The jpg file name looks like an MD5 digest. Inside this file there’s a zip archive:

0 $ unzip -d src 8c4f14e28155a2c3cf4b2538c1e0958b 
Archive:  8c4f14e28155a2c3cf4b2538c1e0958b
warning [8c4f14e28155a2c3cf4b2538c1e0958b]:  192407 extra bytes at beginning or within zipfile
  (attempting to process anyway)
  inflating: src/5IIUED7GheR         
  inflating: src/6JXtwsTTh9k         
  inflating: src/87F1s5POUJc         
  inflating: src/BPiIOASG_Z6         
  inflating: src/nLPA8X0UJqf         
  inflating: src/rySOWi4fZkA         
  inflating: src/uvlSlG3Tgow         
  inflating: src/Uw105aD3qYh         
  inflating: src/Yui5oq58hlx 

One of these files is a wav with some Morse code in it. The other files are just pieces of the whole wav file containing the planet name Morse-encoded. We created a python script to compute all the possible wav files and compared each md5 checksum with the original file name. There are only 8 files we need to compute, so the total permutations are 8! = 40320:

#!/usr/bin/python

# Author: Marco Squarcina  from c00kies@venice
# Description: Script for solving the Unknown Planet challenge of hack.lu CTF 2011

import os, hashlib, math, sys
from itertools import permutations

if len(sys.argv) != 3:
	print("Usage: %s  " % sys.argv[0])
	sys.exit(1)

path  = os.path.abspath(sys.argv[1])
fhash = sys.argv[2]
out   = os.path.join(os.getcwd(), 'planet_name.wav')

flist = []

# open files
for f in os.listdir(path):
	fh = open(os.path.join(path, f), 'r')
	if(fh.read(4) == "RIFF"):
		sample1 = fh
	else:
		flist.append(fh)
	fh.seek(0)

count = 1
nsamples = len(flist)
nperms = math.factorial(nsamples)

# compute all the permutations and check md5 against fhash
for p in list(permutations(flist)):
	print("\r" + str(count) + "/" + str(nperms)),
	count += 1
	sample = sample1.read()
	sample1.seek(0)
	for i in range(nsamples):
		sample += p[i].read()
		p[i].seek(0)
	if hashlib.md5(sample).hexdigest() == fhash:
		print("\nFound it! The correct wav is stored in " + out)
		oh = open(out, 'w')
		oh.write(sample)
		oh.close()
		break

# close files
for f in flist:
	f.close()
sample1.close()

With this script, we got the correct wave file in a very short amount of time:

0 $ ./assemble.py src/ 8c4f14e28155a2c3cf4b2538c1e0958b
23876/40320
Found it! The correct wav is stored in /home/lavish/planet/planet_name.wav

Using audacity the Morse code become easily readable, so:

.--.  ....  .  ..  -.-  -.--  ---  ...

can be translated to:

Pheikyos

What a name for a planet 😉

Author: Marco Squarcina

Computer Science student and an Open Source enthusiast. My main interests are computer security (especially mandatory access control systems), Linux systems administrations and audio applications.