European Cybersecurity Month 2018 - outsourz3d task

Hello everyone

My adventure with solving the task from different Capture The Flag contest is still in progress. About two weeks ago I decided to look at one of the tasks from European Cybersecurity Month CTF this challenge is called outsourz3d. The category of this is Reverse Engineering + MISC it sounds like a lot of fun. ;)
I invite you to read about my way to solve this very curious task from scratch. If you want to solve it yourself, this is the link -> http://outsourz3d.ecsm2018.hack.cert.pl/ 

After downloading the binary I always look at what is the specification of the file. Something like this:



This is ELF 64-bit file so we can simply use IDA to disassemble it and look at the asm code. But first, let's take a look at the strings in binary - maybe one of them will be the flag.


It wasn't very helpful, but sometimes it works differently. ;) It's time to look at asm and get the knowledge about how the flag is "set".




It looks like an array of chars. Why chars and not ints for example? Because the compiler reserved exactly 80 bytes on the stack and this array has more than 30 elements 30elements*4bytes > 80 bytes. The last compare is simply checked if the number of the arguments is 2.

This is maybe the most important part of this analyze. Let's focus and look:


When you look at the top of the main function you can see that the value from [rbp+var_50] address is the char *argv[] and this is the array of pointers to the pointers to chars. The first pointer is to the argument of the ./binary arg but the add rax, 8 instruction is enough to get the pointer to the first char of the second argument. So [rbp+var_20] is the first character of argument, [rbp+var_18] is the pointer to the ninth char and so on (pattern: <address of first char+offset>). The next instructions create some repeatable pattern:






It's important to look for some "templates" in reverse engineering and this is one of them. Some char is the argument of the function. After the execution of this method, the byte from returned value is compared with the value from the array which is on the top of the main function.

Another thing that we can see is that the indexes of the chars are the same as the indexes of the values with we will compare the returned values of the functions. For example:

char_from_arg[2] is compared with value_to_compare_with_char[2]

The indexes of both arrays are the same at compare. And this is the first important step in the crack of this binary:

INDEX OF THE CHAR IS THE SAME AS INDEX OF VALUE TO COMPARE WITH CHAR 

Now we can dive into the function which is responsible for return the value. Let's take the first function for example.






The argument of this function is our char from the flag. (more precisely - ascii value of this character) This char is subtracted with some random value which is 0x7B in our example. The result of this subtraction is returned and compared with the value from the array. This gives us this pattern:

char - 0x7B = 0xB5 => char = 0x7B + 0xB5

But we have to be sure what instructions are in the all functions. Let's take a look at some of them.

ADD instruction


 ROL instruction





 















XOR instruction

 

















ROR instruction



















These instructions are used for checking if the char from the exact index of the argument is the same as in the flag. From the description of the task we know that we have to reverse 20 binary files correctly to get the flag so now we should download another binary to check if the template of the main function is the same as in the test file. It is the same so we can think about the steps which will give us the correct flag for any file from the task page. Let's take a look at the objdump code of the binary before you read about below steps. We have to reapeat this steps for 20 binaries.

1) Download the binary with the same session id as earlier (for the first request to the server we don't know what session id is)

2) Use objdump with --start-address option to get the asm code of the file in the text file (start address value should be the address of the first function at file written by some human and not be generated by the compiler automatically)

3) Functions are named by this pattern sub_<address of the function> and we have to get this address of the function and append it to a list

4) When you execute the objdump with -M intel option the index of the char will be movzx  eax, BYTE PTR [rbp-<index>]. When we get this index we will be able to save the decrypted character at the correct position in the flag

5) Get the compared value -> mov BYTE PTR [rbp-0x<some_value>],0x<compared_value> 

6) Crack the flag because we have information about:
- where the char is in the flag
- in what functions we should look for the instruction of the analyzed char and where this function is in the memory
- what is the value with which our char will be compare

7) Send the cracked file to the form at the site of the task with the same session id as earlier

8) Print the response from the server (in the response for the last binary we will see the flag)

I decided to use regular expression to solve this task. This is the cracker: https://github.com/shizzeer/CTF/blob/master/ECMS/outsorz3d_crakcer.py

And this is the use of this cracker:


LAST RESPONSE AND THE FLAG

 
ecsm2018{4ngry_r1pp1ng_th3m_1nput5}

Thank you for reading! Cheers!

Comments

Popular posts from this blog

Learning of malware analysis. Solving 9-1 lab from the "OllyDbg" chapter. ("Practical Malware Analysis" book)

PicoCTF 2018 - Reverse Engineering writeups