DRG Online Challenge July 2013 Solution

A new monthly series kicked off last month with the inaugural DRG Online Challenge July 2013 and we're off to a promising start. We received three correct submissions. In the order we received them, those who correctly solved the challenge were Vytautas Krakauskas, Björn Zettergren and Thomas Kjærlund Petersen. All three provided a solution within a couple of days after the challenge was published. While Vytautas was the quickest to tell us he found a solution, Björn provided a rich and lively chronicle of his efforts and Thomas discovered a clue we had inadvertently left behind, which he took advantage of. As promised, we are going to feature one solution write-up. Take it away Björn...

A challenge

This text describes how I thought and worked while solving the monthly challenge that Dragon Research Group set up. I really enjoy these kinds of exercises; It feels great when you can deduce small clues in the riddle, that eventually lead to finding the answer. Usually, I learn a lot. This was no exception.

If you would like to have a go at the challenge yourself, stop reading now and go to the challenge webpage! You can always come back afterwards.

The mission and the steps taken

Find a hidden message in a PGP message block at DRG Online Challenge July 2013. I saved it to my computer as drg-challenge.txt, and try running it through gpg (the GNU Privacy Guard, an OpenPGP implementation).

    $ gpg -d drg-challenge.txt
    gpg: packet(7) with unknown version 12
    gpg: no valid OpenPGP data found.

Of course it wouldn't be that easy, the comment did say "something is not right" after all. I spent a few moments messing around with various ideas; Maybe the block text is an ASCII-image if viewed at a different line width and small fonts - Fruitless. Maybe the block text contains some pattern of characters not contained in the base64-table, try removing all base64-chars - That left me an empty console.

Time to stop the random messing around, and look at the code-block more thoroughly from a format point of view. After a while I notice that the base64-encoding looked weird. Padding goes at the end of the sequence in Base64 (strictly speaking though, PGP uses Radix64 for "ASCII Armor", which is Base64 with a 24-bit checksum appended to it). Also, the checksums equal-sign always goes at beginning of the last row:

    -----BEGIN PGP MESSAGE-----
    Comment: something is not right
    [...lots of more data...]
    -----END PGP MESSAGE-----

I tried moving the equal-signs to the "correct" place, but still got the same errors. I began to suppose that the whole block might have been reversed, line by line, except the comment and PGP-boundary markers. I also found that according to the specification, the first few bytes of the ASCII-armour is actually the PGP-header, eg. jA0EAwM is the header for symmetrical CAST5 data, jA0EBwM the header for AES data, and so on. Although the beginning of the first line of the encrypted block did not adhere to this, i did notice that the header existed in reverse at the end of the line. So, let's try reversing the Radix64 block!:

    $ (head -n 2 drg-challenge.txt; sed -r '/^(-----.*PGP.*-----|Comment.*)/d' drg-challenge.txt| rev ;
    tail -n1 drg-challenge.txt ) > drg-challenge-reversed.txt

Now it looks something like this:

    -----BEGIN PGP MESSAGE-----
    Comment: something is not right
    [...lots of more data...]
    -----END PGP MESSAGE-----

This seems to have done the trick. Gpg will now recognize the data as valid PGP-block. However, I need a passphrase to decrypt it!

    $ gpg -d --no-use-agent drg-challenge-reversed.txt
    gpg: CAST5 encrypted data
    Enter passphrase:

I randomly try the few obvious options; A blank passphrase, drg, dragonresearchgroup, dragon, research, challenge, passphrase in various cases and combinations. None are correct. I tried different case-combinations and variations of the comment "something is not right". I tried using the passphrases left and wrong (since that something is not right either).

All of these attempts where futile, no award for me. I considered if there were any attacks against CAST5 (although I find it highly unlikely). So, I did a little reading on the viability of brute forcing it. Found a good explanation of why that would take a long time, for any reasonably long passphrase. I conclude that the best approach for now, is to go back to looking at what potential clues the challenge provides. Primarily, I have at my disposal the PGP-block and the original instructions at the challenge web-page. I looked through the HTML-source for clues and find nothing. Viewing the web-server response-headers yields no additional hints either.

I started to think about the comment again - "something is not right". Perhaps I was over-eager to preserve the comment when reversing the rest of the block? I tried the reversed comment as passphrase, with GREAT success! It's the correct passphrase! Cue adrenaline surge, heartbeat at unhealthy frequencies, a smile on my face! But back in the console window, signs of chaos!

    $ gpg -d --no-use-agent --passphrase "thgir ton si gnihtemos" drg-challenge-reversed.txt
    gpg: CAST5 encrypted data
    gpg: encrypted with 1 passphrase
    gpg: WARNING: message was not integrity protected
    [...lost of more data...]
    begin 644 dne

When I settle down a bit after the first feel-good-moment of finding the passphrase, having spent a few minutes staring at the output for a while, I recognise that it looked like uuencoded data. The last rows that say "begin 644 dne" seem to indicate that this is actually inverted uuencoded data. That part of uuencoding says that after decoding it, it'll write a file called dne with file-permissions 644. I construct a command to reverse the order and decode it (tac prints files from bottom and up):

    $ gpg -d --no-use-agent --passphrase "thgir ton si gnihtemos" drg-challenge-reversed.txt | tac | uudecode

So what is in the file?

    $ file dne
    dne: PNG image data, 220 x 221, 8-bit/color RGB, non-interlaced

When viewed in an image-viewer, the displayed image is that of an inverted Dragon Research Group beer label logo, with no obvious sign of a hidden message within the image itself. I decided to check the comment field using ImageMagicks "identify"-component - it felt like the second place to look after the image itself. Immediate success:

    $ identify -verbose dne | grep -i comment
        Comment: sdrawrof wen eht si sdrawkcab

Well, except that it seems a little backwards...

    $ identify -verbose dne | grep -i comment | rev
    backwards is the new forwards :tnemmoC

That did indeed seem like the final message, rather than a clue to continue digging. The filename is dne, which backwards becomes end after all. I considered further possible interpretations: Could there be additional strings within the raw image data? Could the author have been so cruel to stoop to steganography? After brief experimentation with both of these possibilities, I decided to accept that "backwards is the new forwards" is the intended hidden message, and mailed that to the challenge email-address.

Thank you Senghan Bright at Basefarm, for editing this text. Thank you DRG, for providing the challenge, it was lots of fun! If you have any questions or comments, please let me know.

Best Regards

Bjorn Zettergren
Basefarm SIRT


For further details on how the challenge was constructed along with notes and write-ups from all challenge players who solved solved the challenge, please see the updated DRG Online Challenge July 2013 page. The newest, DRG Online Challenge August 2013 is now available. Visit the DRG Challenges page for information about all current, future and past challenges.

posted at 4:40 pm | permanent link

About DRG

Apply to DRG

Host a DRG Distro Pod

Insight & Analysis


Weekend Reads


Security Innovation Grant

Mailing lists

DRG PGP public key

Follow us on Twitter Follow DragonResearch on Twitter

Feedback: dragon@dragonresearchgroup.org