Thursday 26 June 2014

MWR Hackfu Challenge 2014

Every year MWR release their infamous Hackfu challenge in the build-up to the actual Hackfu event. I had a crack at this years challenge and managed to get just over half way. In this post I'll discuss some of the solutions.

For MWR Hackfu 2013 solutions check the excellent post here.


The challenge started off with a zip file containing a code book, some encoded text and an AES encrypted file. Decoding the text would give you the password to decrypt the file.

The whole challenge was based around the one time pad CT-37 ( You were given a set of 1000+ possible pads and had to decode the encoded text with each pad. Searching through the 1000+ decoded texts you would find the answer.

The pads were in a bit of an awkward format:

So the first thing to do was format the pads into something more user friendly:
with open("book.txt") as f:
    content = f.readlines()

for x in xrange(0, len(content)-1, 17):
    col1 = ""
    col2 = ""
    for y in range(x+4,x+14):
        col1 = col1 + str(content[y].split("|")[1].replace(" ", ""))
        col2 = col2 + str(content[y].split("|")[2].replace(" ", "")) 
    print col1
    print col2

Next came the decoding - I read in the pads, modulus with the encoded text then convert the result from numbers back to letters. I didn't quite finish the logic for number decoding so the final result had letters decoded but numbers encoded, meaning some manual conversion was needed.
ct37 = {"1":"A", "2":"E", "3":"I", "4":"N","5":"O","6":"T","70":"B","71":"C","72":"D","73":"F","74":"G","75":"H","76":"J","77":"K","78":"L","79":"M","80":"P","81":"Q","82":"R","83":"S","84":"U","85":"V","86":"W","87":"X","88":"Y","89":"Z","90":"FIG","91":".","92":":","93":"'","94":"bla","95":"+","96":"-","97":"=","98":"REQ","99":" "}

text = "769605051216509986104949466790121237625886055201851226360699645529130149291137238279392786680278378964378759191773333762068904750697824787177658393352150777878727078"

with open("book1.txt") as f:
    content = f.readlines()

for k in range(1200):
    book = str(content[k])

    ctext = list(text.replace(" ", ""))
    pad = list(book.replace(" ", ""))

    print "********************BOOK " + str(k) + "********************"
    #print "Text: " + str(ctext)
    #print "Book: " + str(pad)
    x = []
    for i in range(0,len(ctext)):
        x.append(str((int(ctext[i]) + int(pad[i])) % 10))

    i = 0
    y = []
    code = 0
    double = 0 
    for i in range(0,len(x)):
            code += 1
            double += 1

        if(code==0 and double==0 and int(x[i])==0 and i<len(x)-3):
            y.append(x[i] + x[i+1] + x[i+2] + x[i+3])
        elif(code==0 and double==0 and int(x[i])>6 and i<len(x)-1):
            y.append(x[i] + x[i+1])
        elif(code==0 and double==0 and int(x[i])<7):

            code = 0 
            double = 0

    for j in y:
        if j in ct37:
            print ct37[j],
            print j,
    print "."

The final message:

The Container

With the answer from the pre-challenge I could now decode the AES encrypted file to access the rest of the challenges:
openssl enc -base64 -d -aes-256-cbc -in -out
The zip file contained four challenges, I managed to complete 1, 3 and half of 4.
  • 01 - Binary Reversing
  • 02 - Steganography
  • 03 - Encryption
  • 04 - Password Recovery

01 - Binary Reversing

This challenge involved analysing a binary and discovering a secret password. You could enter a password guess and the program would tell you if it was right or wrong.

Assuming that brute force would be too time consuming I set to work analysing the binary with IDA and EDB debugger. The first part of the program could be followed with relative ease and you could observe the program iterating over the characters of the input password one by one. I discovered that when a valid character was found a counter variable was incremented. When the counter reached 19 the below condition would be met and the success message given:

To find valid characters the most obvious approach was to check the code for where the counter was incremented, I had hoped there would be some simple comparisons that revealed the characters... Unfortunately things weren't that simple and the bottom part of the program that actually analysed the characters was too complex to follow.

So at this point I knew that a counter was incremented on correct password characters but I couldn't find out how/why using static analysis - what about dynamic analysis?

If there was some way to iterate over password characters and read the counter's memory value (at esp+78h+var_50) as the program executed, I would know when a valid character was hit as the counter would increment. Never wanting to reinvent the wheel I hit Google and came across an interesting GDB fuzzer here. With a few tweaks it was ready to go.

(The more sexy solution would have been to patch the binary to spit out the counter value, unfortunately my assembly skills are somewhat limited)

To execute a python script in GDB:
gdb -q -x 

The fuzzing script:
# -*- coding: utf-8 -*-
import gdb

guess = ['"','z','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','"']

def break_handler (event):
         print "Break hit!"
         gdb.execute('x/x $esp+40')

gdb.execute('set pagination off')
gdb.execute('set verbose off')
gdb.execute('set confirm off')
gdb.execute('file check-passwd')
gdb.execute('break *0x8049603')

for i in range(13,len(guess)-7):
    for j in range(21,700):
        if j==34 or j==92 or j==96: j+=1
        val = unichr(j).encode('utf8')
        print j
        guess[i] = str(val)
        print "Guess: " + ''.join(guess)
        gdb.execute('set args ' + ''.join(guess))


As an example, when trying "u" as the 18th character you can see the counter incremented indicating this was a valid character. But when trying "t" or "v" the counter stayed at zero.

By analysing the script output I was able to construct the complete password.
novus orD0_saclorum

02 - Steganography

In this challenge you had to reverse the stego techniques used to hide data within an image. You were given a before image and an after image, by diff-ing the images you could see a pattern of changed bytes. Without knowing much about the jpeg format or compression I passed on this challenge, apparently the solution had to do with the least significant bit of the luminescence blocks.

03 - Encryption

This was one of those fiendishly simple yet annoyingly difficult challenges. You were basically told to decode this:

I initially tried some binary and ascii conversion as well as chunking as the 630 character block evenly split into chunks of 3, 5, 6, 7, 9 and 10 but couldn't spot anything. With a dot/dash like pattern I tried some Morse code analysis too but with spaces missing and no kind of deliminator the number of word combinations was too great. So what was the answer?

After a hint from MWR I revisited the binary conversion/chunking and realised I had missed the obvious. By converting the -/+ to 0's and 1's then splitting the data into chunks of 5 bits, you ended up with each chunk corresponding to a number in the range 1-26, hello alphabet!

etext = "100000011110101011111100001110011001000001001110011000001110011101010101111000001010111000101111100111000001110011101111100001000110101101111100100111011111000010100101011010110111110010011001100011100000011001001111100010100000101100010110101011100110111101010110101100100011010101111100111100101110100001100101110110000111110110101010111011001010111000001001101011100101100010011011101100101101000011001110110010110101110011100001111000110110001001101101100110100100001011110101110010010110101010011000010011001101010101110011100110001001101011010100101011100011011000100110111011000100111100000101011001010100101010010110001001"

for n in range(5,8):
    print "CHUNK SIZE: " + str(n)
    arr = []
    for i in xrange(0, len(etext), n):
    print arr

Of course no challenge is that easy, simple A=1, B=2 etc. substitution didn't work and neither did Caeser cipher variants. To find the answer frequency analysis was needed. I initially tried to do the substitution manually but the number of combinations made life difficult so in the end I used the excellent cryptogram solver here:

This gave me a rough answer:
operations otter heads approved s proceeds with spackages deliverfs to stargets bones ind i go sumesaryings codesmen of wettine em twaft a famiemnin

With a little hangman style guess work I cleaned it up to get the final answer:
operation otterhead approved proceed with package delivery to target zone indigo use arming code senoywettineestwaytayasiesnin

04 - Password Recovery

The final challenge involved decrypting a set of messages from a Mexican wrestling forum that had been hacked, you were given the password hashes and messages from the forum. First-up messages had to be base64 decoded, then translated from Spanish to English. The two target users could be seen sending AES encrypted messages back and forth.

My first plan of attack was to target password reuse. I guessed the target users may have used the same password for the forum as they did when encrypting their private conversation. In the story text MWR had given us a user and a password (NaClgoofd), this suggested a weak or badly designed salt scheme was in use. After much toying with hashcat I figured out that the site had used the id and username of the user as the salt when hashing passwords e.g. md5(id+username+password).

To crack the hashes I added the salt prefix using a hashcat mask:
cudaHashcat64.exe -m 0 -a 7 hash.txt ^0^0^1^a^d^m^i^n^i^s^t^r^a^d^o^r rockyou.txt

With the salt scheme I was able to crack the hashes of the two target users and the admin:

Unfortunately the private messages weren't just encrypted with these passwords. There was actually a more funky encryption routine at work. MWR released the following hint:
secret = SaltMachine.generate(msg.ref_info,application.secrets.privateboard)
key = md5.md5(secret).digest()

The private messages were actually encrypted with a key that was an md5 of msgid + threadid + userid + admin password. I've not used pycrypto much in the past so even with the solution in hand it took me a while (and a hint or two) to finally get the answer:
import hashlib
import base64
from Crypto.Cipher import AES

def decrypt(key,input):
    ciphertext = base64.b64decode(input)
    iv = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    cipher =, AES.MODE_CBC, iv)
    return cipher.decrypt(ciphertext)

print decrypt("003575029004Redfish99","WMJJBOOhGCkQrUVE0T03paykzQA5HZAdBVf5LaPcBpDZUIO9Y4M9lo2oU7ra9Gji7F3Qpph7jgvtpXIJDIgs+Q==")

print decrypt("003578029003Redfish99","KM4C5iPGzm9d01TwsLTqfA7Pas20qGgsiolhKMly9PT0qdIIjX8+mh2wrXqR4fdga0Aw+AF9g2YMGOoMQDeb0VmWWT06FtdZxv2CFIUAa1A9+rlkWyiMa4zewrYyKJDy")

print decrypt("003581029004Redfish99","2MyEvMWqWyfWAC/z6gypxvpvgCLIwt7ZHw64Yy3KBeqS9+QOk0bVzXQeI9MJo0Hm")

Decrypting the text gave the final solution:
ElEnterrador: Do we have progress? You committed to having it ready by now...
LaSombra: Calmate... Package is already in escrow. Pay my guy, and you'll get your little present.
ElEnterrador: Payment made. Reference: 18954-XW-8893432-AQP7

Final Thoughts

Hackfu certainly isn't for the faint-hearted. The challenges require technical know-how, the ability to think outside the box and dedication (unlike a bug bounty there was no prize money!). Despite not completing every challenge I still found Hackfu a great learning experience and it was an amazing feeling finally reaching answers after grinding away at them for so long.

If you have any questions about the challenges (or if you have a solution to challenge #2!) just drop me a comment below.

Big thanks to MWR for creating HackFu 2014, can't wait to see what next year brings!

Pwndizzle out.


  1. Thank you for sharing your thoughts and knowledge on this topic. This is really helpful and informative, as this gave me more insight to create more ideas and solutions for my plan. I would love to see more updates from you.
    while installing the antivirus if there is any issue created regarding to the installation and uninstall then contact norton setup to get the best solution.

  2. With McAfee antivirus, you will get a wide range of antivirus software programs for complete protection of your computers, PCs, and laptops. To know about its programs and products, you can visit its official website. The most appropriate and effective way to protect your data and device from malware, virus, and Trojans is to download, install and perform McAfee activate the process. McAfee is founded in 1987 by John McAfee. It's Ameican global computer security software company. McAfee is oldest, reliable and best antivirus, specially for internet users. It's headquarter in Santra Clara, California, USA. It's world largest dedicated security technology company. In 2011 Intel purchased this company and know it's part of the intel security division. After McAfee activation on your device your system will be automatic scan. If you have not enough memory or space so your system may be slow down. McAfee security scan plus is a free diagnostic tool for your system. For further assistance regarding McAfee, Office-Setup and other computer softwares kindly click on following links:- | | |

  3. I am to become a software developer. If I want technical support or help desk in an IT company, contact Me | garmin express | turbotax login |

  4. Are you looking at a Most loyal Independent Software Testing company in India to test your software? Your search ended here "Devstringx Technologies" is the top custom software development service provider company based in Noida, India. Till now we have created a lot of software for various industries which fully meet the requirement of the customers. We have so far created defect-free software for various business sectors such as e-commerce, hospitality, medical, real estate, educational, etc. We fully understand your business needs.

  5. We offer complete IT services at an unbeatable price. We specialize in designing beautiful websites, mobile application development, software development, and software testing services. We also cater to digital marketing services. In the last few years, our company has emerged as a proven independent software testing services. We build relationships with our customers and never leave it until it succeeds. We have a separate team for each sector and each region is headed by our expert managers. They have amazing knowledge and a great experience to fully handle your project. Our company is offering most effective Usability testing services.

    Do not hesitate to contact us if you have any queries. You can call us, mail us or even leave your query on our social accounts. We will be happy to resolve your query.

  6. Thank you for sharing excellent information. Your website is so cool. I am impressed by the details that you have on this website. It reveals how nicely you
    understand this subject. visit@:- webroot geek squad||
    linksys connect

  7. iLeaf Naturals is one of America’s most trusted dietary supplement companies. We are dedicated to having some of the safest and most effective products out in the marketplace. Our organic food products are made from real vegetables, fruits, and herbs that carry outstanding natural health benefits. If you have any kind of problem, please contact us and we will solve it.

  8. MVR are releasing every year hackfu challenge to build up the actual hackfu event.


  9. At SA Car Removal Adelaide, you have the buyer you’ve been looking for. Give us a call and we’ll make you Cash for Cars offer. We buy Sedans, Trucks, 4x4s, Vans, SUVs, Utes, Jeeps, buses, 4WDs, Light Trucks, Trucks and motorcycles of any make and condition. At SA Car Removal Adelaide, you have a licensed and insured auto buyer that will make you a Top Cash offer for your Unwanted Car today. We buy any make, any model, any year and in any condition of a vehicle. We provide eco-friendly Wrecking & Recycling and our Auto Wrecking helps to curb manufacturing for new parts so we keep the environment green. With more than many years of experience in cash for cars At SA Car Removal, our customers get

    Cash for cars in adelaide
    Cash for cars Caboolture
    Cash for cars ipswich

  10. This comment has been removed by the author.

  11. Hi....
    Flashback to August 2014. Planning for HackFu 2015 is well underway: Alec: Hmm, maybe HackFu could use a bit of DefCon-style badge hacking.
    You are also read more How can i get a Personal Loan

  12. The Alaska EBT card is an important tool for low-income individuals and families to access affordable and nutritious food. By understanding how to check your card balance and log into your account, you can stay on top of your benefits and make the most of this program.