Hack.lu 2011 CTF Write-up: Hidden Challenge

There is no description available… but: find the key

No information was given about this challenge, but we immediatly found it inside the scoreboard javascript, scoreboard-1.1.js.

Here is the pertinent js code:

// Hidden challenge

if( window.addEventListener )
{
    var keys = [];
    window.addEventListener
    (
        "keydown",
        function( e )
        {
            keys.push( e.keyCode );
            if( keys.length >= 10 )
            {
                keys = keys.slice(-10);
                // konami
                challenge = [71, 74, 77, 90, 81, 15, 2, 68, 45, 47, 65, 84, 73, 92, 86, 6, 121, 73, 27, 46, 83, 6, 91, 71, 73, 81, 64, 67, 98, 53, 78, 67, 8, 64, 76, 67, 65, 66, 44, 97, 69, 78, 73, 68, 73, 66, 75, 64, 39, 97, 71, 72, 76, 8, 77, 70, 83, 66, 98, 51, 67, 69, 77, 65, 83, 66, 65, 7, 35, 47, 6, 67, 80, 92, 87, 70, 5, 75, 43, 55, 67, 6, 18, 1, 121, 73, 86, 72, 46, 52, 82, 79, 71, 70, 31, 7, 67, 68, 114, 120, 66, 23, 31, 29, 22, 67, 22, 23, 123, 39, 71, 20, 17, 29, 70, 30, 67, 30, 101, 104, 29];
                decrypted = "";
                for( i = 0;i < challenge.length; i++ )
                {
                    decrypted += String.fromCharCode( challenge[i] ^ keys[i%10] );
                }
                try
                {
                    eval( decrypted );
                }
                catch( e ) {}
                keys = [];
            }
        },
        true
    );
};

The key is provided by typing the keyboard. The array challenge is XORed with the key, and the resulting string is assigned to the variable decrypted. After that, an eval(decrypted) is executed.

Now it's a matter of finding the right key: there are two ways of doing so.

Decypt the ciphertext

Being some js code, the value of decrypted may start with alert(. If our assumption turns out to be true, finding more than half of the key is just a matter of performing a XOR between alert( and the first 6 chars of the ciphertext. To do so, we use the following code:

#!/usr/bin/python

# Author: Marco Squarcina 
# Description: Script for solving the hidden challenge of hack.lu CTF 2011

challenge = [71, 74, 77, 90, 81, 15, 2, 68, 45, 47, 65, 84, 73, 92, 86, 6, 121, 73, 27, 46, 83, 6, 91, 71, 73, 81, 64, 67, 98, 53, 78, 67, 8, 64, 76, 67, 65, 66, 44, 97, 69, 78, 73, 68, 73, 66, 75, 64, 39, 97, 71, 72, 76, 8, 77, 70, 83, 66, 98, 51, 67, 69, 77, 65, 83, 66, 65, 7, 35, 47, 6, 67, 80, 92, 87, 70, 5, 75, 43, 55, 67, 6, 18, 1, 121, 73, 86, 72, 46, 52, 82, 79, 71, 70, 31, 7, 67, 68, 114, 120, 66, 23, 31, 29, 22, 67, 22, 23, 123, 39, 71, 20, 17, 29, 70, 30, 67, 30, 101, 104, 29];
decrypted = ""
plaintext = "alert("
key = range(10)

for i in range(len(plaintext)):
    key[i] = (challenge[i] ^ ord(plaintext[i]))
for j in range(len(challenge)):
    decrypted += chr(challenge[j] ^ key[j%10])
    if (j+1)%10 == 0:
        decrypted += '\n'

print("Key: %s\n" % str(key) + "\nPlaintext:\n%s" % decrypted)

This script yields the following results:

0 $ ./decrypt.py 
Key: [38, 38, 40, 40, 37, 39, 6, 7, 8, 9]
Plaintext: alert(C%&grats!N'u solvFDje :)\nPO&=tion: ECzqd1753ds.a295c9Ema;

That makes a lot of sense. We just need to complete the missing part of the guessed plaintext "alert(****grats!" in order to get the whole key: there are only 4 reasonable substitutions:

  • alert("Con
  • alert("con
  • alert('Con
  • alert('con

We try these 4 strings until we get a perfect decryption for the entire ciphertext and finally:

0 $ ./decrypt.py 
Key: [38, 38, 40, 40, 37, 39, 37, 39, 66, 65]
Plaintext: alert('congrats!\nYou solved the hidden challenge and have received an extra live :)\nsolution: fc09d1753d309fa295c9f9');

Done!

Use the konami hint

During the CTF we didn't really care about the comment // konami inside scoreboard-1.1.js, but it would have saved us some time.

Googling "konami" we get:

"Konami code" looks interesting because the first result is the wikipedia entry for Konami Code. Now, guess what the combination

↑ ↑ ↓ ↓ ← → ← → B A

is? Yes, the key 😛

Typing shows:

TAA-DAAN! 🙂

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.