Recently I discovered Hacker Gifts and I really liked their idea. I wanted to try it, but I was a little hesitant due to the price tag and not knowing how fun the experience would be. However, after a while, curiosity was stronger and I decided to send myself a card and find out. In this post I’ll walk you through the solving process, so you can decide if this is something a friend would enjoy.

 

Disclaimer: I won’t include the same exact files and clues I received because I don’t know if the puzzles are repeatable and/or if I would be breaking some sort of agreement. Therefore some hints will be obfuscated with an X character.

 

Solving the puzzles

Let’s begin 😃

After placing your order, you’ll get a card like the one below and it contains the first puzzle. By the way, you can customize the name on the card, the card design and the secret message that will be revealed after all the puzzles are solved.

Card

After scanning the QR, you’ll get something like this:

U2VjcmV0IGhleGR1b..............YzMS00NTQyKQo=

Typically, I’ve seen strings ending in “=” while dealing with base64 or encryption algorithms that use it, so I decided to try that first.

At this point, I thought that maybe the whole decoding pipeline could be automated, so I came up with this small program to decode the QR and convert from base64.

from pyzbar.pyzbar import decode
from PIL import Image
import base64


def solve():
    # let's see what's inside the QR
    qr = decode(Image.open('../puzzle/card.png'))
    data = qr[0].data.decode("utf-8")
    print(f"QR data: {data}")

    # the last "=" in data looks like it's base64
    # let's try that
    base64_message = data
    base64_bytes = base64_message.encode('ascii')
    message_bytes = base64.b64decode(base64_bytes)
    plain_msg = message_bytes.decode('ascii')
    print(f"Base64: {plain_msg}")

The decoded text contains a reference to a site and an access code. I’ve replaced the real content with letter X as mentioned earlier.

Secret hexdump for RV: https://XXXXX.XXXXX/ (XXXX-XXXX-XXXX)

When you open the link and enter the access code, a nice hex dump will be waiting for you. This is when I noticed that I didn’t want to automate browsing the site, so I decided not to automate everything, but still code things that looked fun. Here’s an extract of the hex dump.

Dump

The first important thing is that the hex dump starts with Rar!, so it should be a compressed file. And probably password protected because of the text at the bottom.

But, as you can see, the password seems to be missing. At first, I thought it was an error, so I retried a few times. After that, I suspected the password might be in a comment or hidden in some other way. And indeed, it was available in the source code, inside a div element:

Dump Password

So now that we know we are dealing with a password protected rar file, the next step is creating it, in other words, reversing the hex dump. The following method does exactly that.

def reverse_dump():
    newFileBytes = []

    with open("../puzzle/hex.txt", "r") as txt_file:
        lines = txt_file.readlines()

        for line in lines:
            if line.startswith("0"):
                parts = line.split(" ")

                for i, p in enumerate(parts):
                    if i > 0 and p != "" and not p.startswith("|") and not p.startswith("."):
                        newFileBytes.append(int(p, base=16))

    with open("../puzzle/hex.rar", "wb") as rar_file:
        for byte in newFileBytes:
            rar_file.write(byte.to_bytes(1, byteorder='big'))

After decompressing the file, you get two new files:

instr.txt
key

Instr.text contains several things:

  • The goal which is to login into a server.
  • A haiku poem that has the IP address encoded somehow.
  • A plain text password for SSH.
  • Instructions on how to brute-force another password to decrypt the key file, which is also needed to login.

Let’s start with the IP address.

This hipku will point to a server:

The placid XXXXX hawk
dives in the XXXXX river.
Jasmine XXXXX drop.

The typo in haiku is intentional and it’s the hint you need to know that the IP is hidden inside the poem. But how to interpret it? At first, I thought it might be a known poem with some modified characters, for example, “placid” could be “place”. However, after some googling, I found hipku, a program that converts an IP adress into a poem. So maybe the hint was even more explicit than I thought 😉

The decoding was quite simple:

from pyhipku import decode


def reverse_haiku():
    print(decode('The placid XXXXX hawk\ndives in the XXXXX river.\nJasmine XXXXX drop.\n'))
167.XX.XXX.XXX

Now let’s brute force the password. The instructions say that it’s a seven-digit password and provide the starting part of its SHA-256 as a hint.

from hashlib import sha256
from brute import brute


def brute_force():
    # replace "XXXXXXXXXX" with your real SHA-256 hint                     
    expected = str.lower("XXXXXXXXXX")

    for pwd in brute(length=7, letters=False, numbers=True, symbols=False):
        hashed = sha256(pwd.encode('utf-8')).hexdigest()
        # print(hashed)

        if hashed.startswith(expected):
            print(pwd)
83XXXX0

Finally, let’s deal with the key. The key file looks like this:

-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                      
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END EC PRIVATE KEY-----

I’ve used PuTTY quite often in the past and I knew it wants keys in ppk format. So I guessed I had to do something with the text to get a valid ppk file.

PuTTYgen helped me doing that:

PuTTYGen

You’ll need to enter the password that was brute forced earlier and then click on “Save Private Key”.

When I finally logged into the server, I was greeted with a console based Space Invaders game and you just need to beat the first level. It’s not difficult at all but playing over SSH was a little unresponsive.

Space Invaders

And that’s it!!! My secret message has been revealed!!!

Space Invaders Win

Tracking

Once your order has been completed, you’ll get a tracking URL and you can monitor how is your friend doing. This is one of the reasons why the puzzles involve visiting a web site and logging into servers in order to record milestones.

More importantly, you can point your friend in the right direction in case of being stuck.

Tracking

As you can see there are some hints available and it’s pretty much what we did, except for the choice of tools.

Just in case, solving the puzzles the way I did took me around 4 hours (while also documenting and preparing stuff for this post). I started at night and then went to sleep, so that explains the 18 hours in the screenshot.

Was it worth it?

From the solving point of view (the part your friend will get) absolutely. It was fun, unexpected and I love this sort of quests.

From the buying point of view, it all went well, payment was easy, everything arrived immediately, the tracking site gets the work done, etc. As for cost, it’s really tricky to come to a conclusion because we all have different ideas of what’s fun and how much is worth it. It also depends on your previous experience and how long it will take to solve the puzzles. In any case, at least you can judge for yourself based on this walkthrough. That being said, it would be nice if there were more options, maybe based on length or difficulty.

Final thoughts

I hope you enjoyed the walkthrough. In case you like this sort of puzzles, I’d like to suggest a much harder one wich is called Tom’s Data Onion. I had a blast doing it, it was not easy at all and I learnt several interesting things.

Thanks for reading!!! 😃