Sunday, September 29, 2013

No cON Name Facebook CTF qualifiers writeup

With only 3 tasks and no flag submission, the No cON Name Facebook CTF had a slightly unusual qualifier. On Twitter the organizers clarified that the qualifier is "not a CTF". The teams not only had to solve the tasks, they had to create writeups as well. The tasks were interesting, but they were surprisingly easy. I worked alone this time and solved the tasks pretty quickly.

Level 1

This was a web hacking challenge with some client-side JavaScript code to evaluate the key.


Looking at the underlying JavaScript we can see this obfuscated code:




After beautifying the code, this is what we can see:
var _0x52ae = [...];
eval(function (_0x7038x1, _0x7038x2, _0x7038x3, _0x7038x4, _0x7038x5, _0x7038x6) {
    ...
}(_0x52ae[0], 46, 46, _0x52ae[3][_0x52ae[2]](_0x52ae[1]), 0, {}));
The easiest way to deobfuscate this is to change "eval" to "console.log" (in chrome). This will print all of the unpacked JS source. Here is an interesting function:
function encrypt(form) {
    var res;
    res = numerical_value(form.password.value);
    res = res * (3 + 1 + 3 + 3 + 7);
    res = res >>> 6;
    res = res / 4;
    res = res ^ 4153;
    if (res != 0) {
        alert('Invalid password!')
    } else {
        alert('Correct password :)')
    }
}
Any string that produces a numerical value between 62540 and 62544 will be accepted. Finally, this is how the numerical_value is computed:
function numerical_value(str) {
    var i, a = 0,
        b;
    for (i = 0; i < str.length; ++i) {
        b = ascii_one(str.charAt(i));
        a += b * (i + 1)
    }
    return a
}
It is pretty straightforward to forge a key by hand now. This was one that worked for me: "}}zzzzzzzzzzzzzzzzzzzzzzzzzzzyyA". I started adding new letters until I was close to the target value. Then I changed the values that are close to the beginning to fine-tune it. It was a pretty bad idea to start with "z" characters, since there are very few characters with larger ASCII codes. Here is the flag as the result:


Level 2

The task here was to reverse-engineer an Android application package (apk) file. I cheated here and instead of looking at the source I looked at the resource files. There were 16 images that looked like parts of a QR code. It took me roughly 3 minutes to puzzle them together and after reading the QR code I got a flag:


788f5ff85d370646d4caa9af0a103b338dbe4c4bb9ccbd816b585c69de96d9da
Level 3

Level 3 was a 64-bit ELF executable. This is what happens when we launch the application:


I started reversing the ELF binary, but I'm terribly lazy and I wanted to do this as fast as I can, because if I were trying to get into the final with a team time would have mattered. I decided to write a script that tries every character until it is accepted and then continue with the next one. I figured out the first character by hand (it was a space, for some reason this was my third try) and then I knew what to look for in the output. Here is the script, it's pretty short:
from subprocess import Popen, PIPE, STDOUT
flag = ""
while True:
for x in range(32, 128):
p = Popen(['./level.elf'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
stdout_data = p.communicate(input=(flag+chr(x)))[0]
if stdout_data.count("*") > len(flag):
flag += chr(x)
print flag
break
This is what we get when we run the script:


And here is the flag after trying the password:


Interesting challenge. I really should have reversed it instead. I will never be a better reverse engineer if I keep cheating. Next time!

No comments:

Post a Comment