noxCTF – TookCookBook

“I’m locked outside of my program…. I have the password but somehow can’t access it. Can you help me?

Notes:

1. This is not a reversing challenge, try to research the behavior of the program

2. The program is recognized as a virus although it is not”

We start the challenge with an attached zip file, which contains two files:

  • Bazinga.exe
  • Bazinga.dll

By the challenge description, this is not a reversing challenge, so we probably shouldn’t try to reverse it. The files are probably packed, and that’s why the program is recognized as a virus.

Let’s run the program (after fighting with Windows Defender to keep the file instead of deleting it…)

We can see a pretty empty window with a top-menu button that says “Click-Me”. When clicking the button, a pop up appears with a message to insert a super secret password.

As we can see, the super secret password is “JohnE”.

Let’s try it.

Uhh, the password is wrong.

When trying “JohnE” as the password, we can notice that there are more wildcards (*) in the box than the letters in the password. That’s weird.

Let’s try to type random data in another program, like our beloved notepad.

Pressing random buttons on the keyboard results “bazinga” being written. It happens for every button, not only for character buttons (Shift and CAPSLOCK for example).

As we can see, the program prevents us from typing what we really want, and messes up the keyboard. The program doesn’t do it only inside its window, it does it for the entire system.

Anyone who is a bit familiar with Windows should know it can be done using hooks (The name of the challenge implies using hooks).

A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure. (from MSDN).

In simple words, hooks can be used by programs to wait for events that happen on other programs, and modify them before the target program handles them. So the program probably sets a global hook on keyboard events, and changes the pressed key before the message is passed to the target program. Let’s think how we can disable this behavior…

The program is packed, so trying to patch it probably will be a waste of time.

Let’s read a bit more about hooks.

The system maintains a separate hook chain for each type of hook. A hook chain is a list of pointers to special, application-defined callback functions called hook procedures. When a message occurs that is associated with a particular type of hook, the system passes the message to each hook procedure referenced in the hook chain, one after the other. The action a hook procedure can take depends on the type of hook involved. The hook procedures for some types of hooks can only monitor messages; others can modify messages or stop their progress through the chain, preventing them from reaching the next hook procedure or the destination window. (from MSDN)

So, each type of hook has a chain with all the hooks that were set for that type. Each hook can decide whether the event should be passed to the next hook in the chain, or not.

This is exactly what we need ! We can disable the keyboard modification by setting our own hook before the program’s hook, and our hook will stop the hook chain. If a program wants to set a hook, it needs to have a loaded DLL which contains the hook procedure.

The code is pretty simple: First, we need to load a DLL with the hook procedure, that simply returns a constant value (by Windows conventions). Then, we need to set the hook with WH_KEYBOARD_LL type.

Click here to download the code

After our program is running and the hook is set, we can launch the challenge program, and still write whatever we want. Let’s try JohnE of course, and we get the flag.

The flag is:

noxCTF{h00k_th3_h00k3r}

Note
Since the program uses hooks, you might have some problems running it on your computer, depending on the programs you have installed. For example, I use a program which enables me to create new key shortcuts for the system, so I managed to solve the challenge in a different way than the expected. By pressing buttons with precise number of times will the SPACE button was pressed, I succeeded typing the correct letters, without writing any code. I’ve spoken with the writers of the challenge about this weird, (but cool) way.

noxCTF – Crakaker

Crakaker

“I did something awful with the flag. Would you be able to understand how to fix it?”

We are going to dive into the internals of this executable, to thoroughly understand the program and generate the input required for the flag.
At the end I’ll also attach source code(s) of the solution and my interpretation of the program.

Initial analysis of the executable

Before we push the executable into IDA to start reversing it, we should probably know what we are dealing with; we can of course open it up in either IDA or IDA64 and continue on from there but I would throw it into DIE to understand what I am dealing with.

DIE

From here, we can understand that we are dealing with a PE+(64bit) that was compiled using MinGW GCC, and so we can prepare ourselves to the compiler wrappers, boilerplate and etc.

IDA, and the real main

Pushing the executable into IDA64, first thing I would do is go through the exports to better understand where the executable actually starts executing code besides the entry-point, if such regions exist.
We do this to ensure we are fully aware of what the executable is going to do, because we want to trace these kind of operations because they can be used to affect the main program, this can be done using a variety of ways; for example:
* Abusing TLS functions
* Abusing CRT startup
* Abusing IAT
* etc.

Exports

In the Export Address Table, our IDA has picked up that TLS functions are available and that could be used to execute code before our start function via ntdll!LdrpCallInitRoutine, this is always a good idea to analyze these functions but in this case going through the functions quickly they are just GCC critical state initializers/stub.

Moving on to start, we come across a small start function, entering the first function call we can see the regular __security_init_cookie so we can quickly rename that function to it’s proper name and move forward.

start

cookie

Side-note

From initial overview of the executable, we are able to notice that it’s not obfuscated or packed in anyway (DIE helps with this as well) so we can freely use the HexRays Decompiler to assist us in quick reviews to find the important stuff.

Inside the next call, we reach quite a big block of code so we should be careful to spot any tricks the author is attempting to use, from my knowledge of GCC and assuming this didn’t have any post-modifications done we can rule out majority of the code by using signatures to detect known GCC generated code.
I will try to use guessing and known code-snippets to attempt and detect most of the functionality of this function.

stackguard

My best guest this is part of the heavy stackguard protection of GCC, however I might be wrong, this is only for ruling out which parts of the code I actually require.

crt

This is some basic CRT startup, some SEH setting up and etc, we can safely ignore it however keep it mind there might be hidden stuff in the CRT we might need to check.

cmdline

Command Line parsing, this would get the string after the argv[0] for example if the commandline is Crakaker.exe nop we will get a pointer to nop in g_cmdline

parsing

Normally, the values that are being passed into the main function would be argc and argv and there would be a sort of program cleanup as the compilers add, from the exit we can see that result is the exit code so we can assume that the function the exit code is coming from is our main!

Understanding the main

Approaching the main function, we can see a lot of magic values being used so I’ll rename the properly to attend to them later if they are important.

main

Looking over at input_size, the maximum size is 16 and later we can see var_230 being turned into a number.. I would assume sub_407C4F transforms our input to a number somehow.

Let’s approach this function step-by-step, the compiler tries to not interfere with the main function, so this would be the author’s code we will start with sub_407E50 firstly.

sub_407E50

So from first impression, this looks like an initializer of some sort, these are quite common to initialize stuff like global variables or memory/functions to be used by the program so it should be rather safe however… looking at sub_407DE0 points us to a sort of initializer that calls functions that are in the .text section, that’s quite odd.

sub_407DE0

Let’s take one of the functions, and try to understand what this does.

qword_409980

sub_406650

Oh.. Yup, that’s some anti-debugging.

Okay, so we can rename all of the stuff in sub_407E50 appropriately, the bypass of this is rather simple, either we enable g_debug_check_passed while running our debugger or modifying nt!_PEB->BeingDebugged

debugger_check

Moving on to sub_407B40, we are able to see some sort of structure creation with copying from a global.

sub_407B40

Looking at unk_40B060 we can see that it’s just a table that goes from 0x00 to 0xFF, I would assume this is some sort of key system and that unk_40B060 is a key table of some sorts, arg_8 is being added to the table in a circular-motion I’ll assume it’s some sort of seed for the table while arg_10 being it’s size, let’s rename it properly and create a structure.

spawn_key

Some fields are unknown, also the key in the end is being copied to key_dirty my guess it needs the original key around.

main2

So now our main got a bit clearer, and we can see that sub_407C4F the function that transforms our v7 to a number with atoi is being passed the key we just spawned, that means the input together with the key gets to be a number.

sub_407C4F

Alright, so we can see that indeed key_dirty is being used and changed in the end, and var_C is being used as some sort of offset for the key while var_5 is being used as the next swapping value and in the end a1 gets the result. I’ll assume this is some sort of decryption method from our key and that a1 is a target, I’ll rename the fields properly.

key_decrypt

Alright, so we can update some of the stuff in our main

main3

Looking at sub_406A43, it’ll print “try again!” so for simplicity I’ll name sub_406A43 as print_fail and sub_4016AD as print_flag, and so we will move on to print_flag.

print_flag

At first, it might seem overwhelming but we can see that these operations are mostly on the constant values at the very start of the main which are here to generate something into the var_90 field.

print_flag_end

At the end, we can see that it’s indeed our flag printing and that our generated integer from the key is used as an allocation size, which is the flag size in the end, and the var_90 is some sort of a string that is being used against the integer and our original input.

sub_406E76

Another sort of initialization, let’s look into it.

sub_407435

From a quick overview, it’s just an initialization of an ASCII table, we can see that it then uses this as an ascii map.
Treating a1 as a character_map here, we rule out input_key_var because it’s used as storage and it contains some rules for output_key_var such as it must be output_key_var & 3 == 0 and the character_map is the actual thing that builds the return value.

I’ll assume that function generates the bytes for the flag, preparing print_flag by the information we got.

print_flag_end2

Continuing to sub_407AC4

sub_407AC4

Seems like a start for an unpacking, let’s continue on to sub_4079D8

sub_4079D8

Looking at the three first functions, I quickly rename them based on their appearance.

magic_formula_0

magic_formula_1

character_to_ascii

There’s nothing too special about them, and they are quick to understand.

Focusing onto sub_4077FA, it looks like some sort of unpacking based on the value we get from the ascii map (which comes from our flag bytes that got generated from the character_map).

sub_4077FA

sub_4077C4

Based on calculating the magic_index_value we can generate the following map of how the character gets unpacked:

[0] (x << 3) | (x >> 2)
[1] (x << 6) | (x << 1) | (x >> 4)
[2] (x << 4) | (x >> 1)
[3] (x << 7) | (x << 2) | (x >> 3)
[4] (x << 5) | (x << 0)

Research Summary

So we just went all of that, we understood most of the program thoroughly, what did we learn?

magic_value_0 = 117 * (argc / 2)
magic_value_1 = argc / 12.0;

magic_buffer_1 = aaaaabgfdgdgdsdf
magic_buffer_2 = aaaaaagfsdgsdgdsfgsdfg
character_map is generated by magic_value_* and magic_buffer_*

magic_formula_0 = (3 - 5 * a1 % 8)
magic_formula_1 = 5 * a1 / 8
character_to_ascii_map = accepted: A-Z 2-7

g_table_key goes from 0x00 to 0xFF
g_seed is [0x4B, 0x42, 0xB7, 0x14, 0xD8, 0xAF, 0xA2, 0x4E, 0x1D, 0x86, 0x46, 0xE0, 0xD3, 0xC3, 0x1A, 0xE0]

[important]
argc > 1
argv[1] must be at most 16 in length.
magic_buffer_* size is affected by argc.
output_key & 3 == 0

unpacking affects 5 flag characters at once and uses 8 of the flag_bytes at once.
Translate table:
[0] (x << 3) | (x >> 2)
[1] (x << 6) | (x << 1) | (x >> 4)
[2] (x << 4) | (x >> 1)
[3] (x << 7) | (x << 2) | (x >> 3)
[4] (x << 5) | (x << 0)

And after all of that, we also notice that our input only affects how many bytes we allocate for the string..
So looking at that, we only need to figure out how to properly generate the amount of bytes we want, that is generated by the key decryption and the proper amount of argc we need for the magic_buffer_* sizes.

Building the solving script.

So first of all, we are going to control the output of the key decryption, luckily if we look at the function we can see it’s just a XOR between our input to the key value, so we can just use the decryption as the encryption.
We just need to use the same functionality as the one we saw in the program and input what we want to except being used in the program.
Once we do that, we need to pick a size, remember that we need to have output_key &amp; 3 == 0 satisfied to actually work so let’s pick 128 which fits that nicely and is big enough for a flag, in any case we can just make it bigger.
So our script would look like this:

import subprocess
import copy


__KEY_TABLE__ = [x for x in range(0x100)]
__KEY_SEED__ = [0x4B, 0x42, 0xB7, 0x14, 0xD8, 0xAF, 0xA2, 0x4E, 0x1D, 0x86, 0x46, 0xE0, 0xD3, 0xC3, 0x1A, 0xE0]
__MAX_INT8__ = 0xFF
__TARGET_PROGRAM__ = './Crakaker.exe'
__MALLOC_SIZE__ = b'128'

class key_t:
    def __init__(self):
        self._key = []
        self._key_dirty = []
        self._key_offset = 1
        self._key_value = 0

    def spawn(self, seed):
        self._key = copy.copy(__KEY_TABLE__)
        offset = 0

        for i in range(len(self._key)):
            offset += self._key[i] + seed[i % len(seed)]
            offset &= __MAX_INT8__
            swap_value = self._key[i]
            self._key[i] = self._key[offset]
            self._key[offset] = swap_value

        self._key_dirty = copy.copy(self._key)

    def decrypt(self, input):
        if len(input) == 0 or len(input) > 0x10:
            raise Exception('out of bounds')

        offset = self._key_offset
        value = self._key_value
        output = [0] * len(input)
        for i in range(self._key_offset, len(input) + offset):
            value += self._key_dirty[i]
            value &= __MAX_INT8__
            swap_value = self._key_dirty[i]
            self._key_dirty[i] = self._key_dirty[value]
            self._key_dirty[value] = swap_value
            output[i - offset] = self._key_dirty[(self._key_dirty[i] + self._key_dirty[value])] ^ input[i - offset]

        self._key_offset = i
        self._key_value = value

        return output

def main():
    key = key_t()
    key.spawn(__KEY_SEED__)
    value = bytes([c for c in key.decrypt(__MALLOC_SIZE__)])
    proc = subprocess.Popen([__TARGET_PROGRAM__, value], stdout=subprocess.PIPE)
    out, err = proc.communicate()
    print(out.decode())

if __name__ == "__main__":
    main()

So we might need to adjust argc, but let’s just try to execute that as it is- and we get nice job: noxCTF{Move_Bitch_Get_Out_Da_Way}
Great, so the argc does not need to be touched, and we are done!