Connect to the remote machine and break the code. Oh wait, maybe you'll
need some tools.

Score   300
Link    ssh://user:ndh2k13@z0b.nuitduhack.com:2222/

We are able to retrieve two files:

  • an ELF asking for a password
  • a vmlinux

Launching crackme on my box failed miserably. The code didn’t make any sense and the e_flags field of the ELF header which was supposed to be 0 was equal to 0x20.

As we were provided with a vmlinux, I guessed the ELF loading routine of the kernel had been modified to check if e_flags was 0x20, and in this case apply some operation. When reversing load_elf_binary (fs/binfmt_elf.c), you see that the code is xored. It can be fixed with the following code:

#include <stdio.h>

#define OFFSET (0x610)
#define SIZE (0x418 + 0xe + 0x28)

int main(int argc, char** argv)
{
    char key[] =
        "\x12\x43\x34\x65\x78\xcf\xdc\xca\x98\x90"
        "\x65\x31\x21\x56\x83\xfa\xcd\x30\xfd\x12"
        "\x84\x98\xb7\x54\xa5\x62\x61\xf9\xe3\x09"
        "\xc8\x94\x12\xe6\x87";

    FILE* f = fopen(argv[1], "r+");
    char buf[SIZE];

    fseek(f, OFFSET, SEEK_SET);
    fread(buf, 1, SIZE, f);

    for (int i = 0; i < SIZE; ++i)
        buf[i] = buf[i] ^ key[i % 35];

    fseek(f, OFFSET, SEEK_SET);
    fwrite(buf, 1, SIZE, f);

    fclose(f);
    return 0;
}

Now that we have a working ELF, we can look at it and see that it a quite straightforward to reverse. There may only be four different characters:

  • w
  • a
  • s
  • d

Looking closer, we can see that there is to globals, which begin at 0, and that must both be equals to 15 to have the right password. We can also se that there is a 16x16 table filled with ones and zeroes, and the globals (which are in fact w and h position in the table) must point to a 0 (it’s a maze, you must get from (0, 0) to (15, 15) without going through a wall).

The following python script find the correct sequence of keys, which is the key:

#! /usr/bin/env python3

import sys

TABLE = [
    0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
    0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01,
    0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
    0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
    0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
    0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01,
    0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00,
    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
]

CHARS = {
    "w" : "wad",
    "s" : "sad",
    "a" : "was",
    "d" : "wsd",
}

def get_counts(key):
    count_1 = 0
    count_2 = 0

    for i in key:
        if i == 's':
            count_1 += 1
        elif i == 'd':
            count_2 += 1
        elif i == 'w':
            count_1 -= 1
        else:
            count_2 -= 1

    return count_1, count_2

def test(key):
    count_1, count_2 = get_counts(key)

    if count_1 == 15 and count_2 == 15:
        print(key)
        sys.exit(0)

    if count_1 < 0 or count_2 < 0 or count_1 > 15 or count_2 > 15:
        return False

    offset = (count_1 << 4) + count_2
    if TABLE[offset] != 0:
        return False

    print(key)

    for c in CHARS[key[-1:]]:
        test(key + c)

    return False

test("s")

Key is:

```text ssddsssassdddssssdssaawaasssddddddwwwwwwddwwwwwdwwdddsssssaassssaasssddddwwddsss