A few weeks ago I heard about the annual hacking challenge put on by MWR InfoSecurity called Hackfu. I was about a month late to the game but figured I’d give it a go to see how many I could get.

The competition consisted of 10 challenges interleaved into an interesting storyline of a character living in a post apocalyptic world. Each solved challenge, while independent, unlocks a connecting passage of the story.

If you’d like to follow along you can download the challenges for Hackfu here.

Challenge 1

The first challenge comes with an encrypted “solution” file and an “instructions” file. The following clue is provided.

Within “Books”, you find about 50 plaintext files that appear to be the entire texts of classic works of literature. The “readme” file contains the following text:


Challenge: Find the key by breaking the book cipher.

Given the book cipher clue, I presume each tuple represents either a character or a word.  Since the first number is larger, I figure it’s either the page number, character index, or line. With the smaller size of the second number, I’m guessing it’s either the length of the characters or the word. The trick is determining which of the 50 books is being used for the cipher. After scripting up a few possibilities, it turns out it was the line number and the word number in the line. The solution script is posted here.

Challenge 2

The second challenge looks to be a steganography challenge as it contains a “image.bmp” file and the following clue.

Challenge: Analyse the image and retrieve a hidden key.

Opening the image with stegsolve yields some interesting results. It looks like there is a QR code in plane 0 & 1. I wrote a python script to extract the data from just these planes by masking off the other bits. After adjusting the colors in Gimp, I read the QR code and opened the solution file. The solution script can be found here.

Challenge 4

The fourth challenge looks to be another steganography one but with audio instead.

Challenge: Analyse the audio file to retrieve a hidden message.

 One of the first things I typically do with audio stego files is open it in audacity and view the spectogram and the metadata. The metadata references “Rudolf Light Writer”, “fldigi”, and “feld”. After some quick googling I discover fldigi is a program for analyzing ham radio audio. Rudolf Light Writer and feld refer to Hellschreiber, a ham radio mode. Opening the audio file in fldigi and selecting Hell -> Feld Hell Op-Mode displays the following result.

This password unlocks the zip file in the Challenge 4 directory but not the solution file. Inside the zip is another audio file. I check the metadata for this file to discover the next clues: speed, backmasking. Using audacity to reverse the audio file and speed it up yields a voice saying that the challenge was complete. After much toiling, it turned out the actual words in the audio file turned out to be the key to the solution file.

Challenge 6

The sixth challenge is an image that appears to be mixed up.

Challenge: Analyse the image and retrieve a hidden key.

Zooming in on the picture you could see that the image looked to be made up of text that had been rotated in slices. I verified this by manually rotating squares starting from the middle of the image using gimp. Realizing this would take forever, I scripted the solution using Gimp’s python API. The solution can be found here.

Challenge 7

The seventh challenge was a password protected Word document.

Challenge: The document contains a flag within, retrieve it to continue.

Given the password on the file, the first thing I did was extract the hash from the file using John the Rippers office2john script. Once I got the hash, I ran John against it and got the password for the file, “salinas”. Guessing the file could have a macro, I opened the doc using LibreOffice and found the password in the macro definition.

Challenge 9

The ninth challenge was a puzzle inside a spreadsheet with the following clues.

The only information you could recover from the page is:

#exile = 27; #wicker = -23; #canine = 28

y = b1*x1 + b2*x2 + c

Challenge: Analyse the data and calculate the next location.

Studying the spreadsheet, it appears that each line appears to equal one of the two coordinates for the next location. From the clues, I deduce that the #keyword are likely a variable for the number beside them. At this point I begin looking at the differences in the final coordinate for lines that have the same #keyword. I note that they are always the same sign(+,-) and are always relatively close the the value that #keyword is equal to. This leads me to deduce that the #keyword is the ‘c’ in the provided equation. From the first clue one line 1, we are told we need to find the coefficients for the equation to solve the challenge. With ‘c’ determined, we need to find out what x1 and x2 are. Studying the final coordinate on each line, we also see that there is a larger difference from ‘c’ for lines that are longer so x1 is likely the length of the line. We can confirm this from line 13 were we are given 3 lines lengths for the keyword that rhymes with liqour (#wicker). I determined x2 from the clue on line 20 that tells us to forget the month and year, which leaves us with the day for each line as x2. Plugging these values into the equation, I solved for the coefficents using a little linear algebra. Once I got the coefficients, I solved for the last location. With the final location in hand I tried to open the solution file. Turns out there was one last step, you had to plug the coordinates into google maps.

Challenge 10

The tenth challenge was a reversing/crypto challenge with the following clue.

Challenge: Analyse the decrypt binary and get the key from the input file.

Opening the binary up in IDA Pro, I can see it has been compiled for the MIPS architecture. It appears to take one parameter of length 16. It then performs a repeating key XOR to a file that is read in called messages.enc. I’ve posted the disassembly of the decrypt function below.

After reviewing a few solutions for a similar Cryptopals challenge (set 1, problem 6), I wrote a script that would use frequency analysis to score all combinations of output from each possible XOR key. I only brute forced up to the first 6 characters of the key before I saw that it was repeating and was only a 4 character key instead of the 16 I had pulled from the binary. The solution script can be found here.

All in all, Hackfu Challenge 2016 was alot of fun. The storyline was creative and interesting and the challenges kept me engaged. I only wished I had found out about it earlier so I may have been able to solve challenges 3,5, and 8. Hopefully some of the other contestants will post the solutions for those.


*** Update – Check out http://andrewmohawk.com/2016/06/05/hackfu-2016-writeup/  for additional solution writeups.

By |2016-10-12T16:53:58+00:00May 13th, 2016|CTF|5 Comments


  1. megal0maniac May 17, 2016 at 9:24 am - Reply

    Hello! Just dropping in to post my experience (and solution) for challenge 3.
    Firstly, I tried to XOR the text since it was all printable, to no avail.
    Next, I looked at the characters with a hex editor. There was a definite pattern – Every odd byte was either 0xC2 or 0xC3, and every even byte was a high value, between 0x80 and 0xbf if I remember correctly.
    Ignoring the odd bytes for the time being, this gave me a range of 64 possible values. Given that that the odd byte differed by only a single bit, I’d get 128 possible values if I stuck the differing bits together – the valid range for standard ASCII text 🙂
    I sketched out some of the even bits in binary and confirmed that there was indeed what looked like a mask – only bits 0 through 5 changed (little-endian counting)
    I wrote a C program to take the changing bit of the odd bytes (bit 0) and stick it together with the 6 changing bits in the even bytes and write the result to a file:


    int i = 0;
    FILE *parse = fopen(“instructions.txt”, “rb”);
    FILE *output = fopen(“output.txt”, “wb”);
    char buff1 = 0;
    char buff2 = 0;
    while(buff2 != -1)
    buff1 = fgetc(parse);
    if (buff1 == -1) break;
    buff2 = fgetc(parse);
    if (buff2 == -1) break;
    fputc(( (buff1 & 0x1) << 6) | (buff2 & 0x3F), output );

    This gave me a file which still wasn't readable, but it was much closer than the original "text"
    I ran it through xortool (https://github.com/hellman/xortool) using space as the "most possible char" and it solved the repeating xor cipher with the key \x0b\n\x11\x1a\x16\x11\x19\x10\r\x12\x10\r\x1a
    The password "youhavetochooseeitheronexortheothernotboth762khz" was tucked away inside 4011 characters of nonsense text, made obvious by its long length.


    • b0yd May 17, 2016 at 2:02 pm - Reply

      Nice solve! This one definitely had me grinding for a while. The “instructions” threw me off the trail with the “It’s… definitely not XOR encryption, you’re certain of that.” clue.

  2. girona May 24, 2016 at 9:32 am - Reply

    Challenge 3 literally was NOT XOR. First I removed the c2/c3 using iconv to convert from utf-8 to latin. Then solve as per normal xor (determine key length (13) and then use frequency analysis. NOT XOR key was “tuneinformore”.

    Challenge 8 was adapted PLAY FAIR. There is a good implementation in pycipher which can easily be adapted. Tricky part was finishing the key. Taking the DCnnn from filename sorted by month and converting to letters results in the string “miaplacidus”. This didn’t work as the key, but trying various other terms “carinae” produced the correct answer.

    Very keen to see a writeup for Challenge 5!

    • b0yd May 24, 2016 at 12:55 pm - Reply

      Thanks for posting your solution! It appears I was sooooo close to solving Challenge 8. I had found the “miaplacidus” clue and even found that plotting the 12 locations in the pictures created the “Beta Carinae” constellation. Unfortunately it appears my modified playfair code was broke. 🙁 Also hoping someone will post the solution to Challenge 5, Andrew Mohawk is holding out on us.

    • Andrew June 13, 2016 at 9:22 am - Reply


      Can you explain how you got to the key?

      Challenge 8 the key was actually the constellation Carina, if you plotted the points on a map it apparently looked like it (even though I ended up brute forcing it anyway)

      Did a writeup of 5 at http://andrewmohawk.com/2016/06/05/hackfu-2016-writeup/#challenge5


Leave A Comment