Sunday, March 2, 2014

Boston Key Party - R3V3 writeup

Unfortunately we didn't have too many people or too much time to compete in this year's Boston Key Party. It was a very well organized CTF, with some high quality tasks. Here is my writeup for the 250 point reversing task.


We received a 64-bit ELF, disguised as an exe file. This is what it does when we start it:
$ ./R3v3.exe
[1]+  Stopped                 ./R3v3.exe
The binary was packed by UPX, so the first step was to unpack it.
$ upx -d R3v3.exe
Then we loaded the file into IDA and looked around. There were some promising strings, that told us where to look in the code. The whole checking mechanism starts at 0x40112A. After some renaming, we found something that we have to patch in order to go forward with the solution:
.text:0000000000401165 call bad_level
.text:000000000040116A call level_2
But since we ended up solving the whole task with just static analysis, we didn't have to do that. What I named as level_2 starts at 0x4011E4. This is where the fun begins. We are asked for a password and then some form of checksum is calculated, that has to be equal to 0x936.

The checksum algorithm is not very interesting here, because we ended up solving the task without having to consider it. The reason for this, is that we get enough information about the password in the next step, which is called level_1 here. (I named them backwards, starting from 0.) Level 1 (at 0x40126A) does 3 consecutive checks, and this is the heart of the crackme.

Let's look at those check_pass functions now. I will present only one of them here, because they are very similar. check_pass_3 uses 2 different indexes to go through our password. 

Both index_1 and index_1b are incremented by 1 at each turn. Index_1 indexes an array I named _weird_iv_2. I didn't know what it was for at the time, a better fitting name would be checksum_arr_2. What this function does is basically compare pairs of password[i] + password[i + 2] to predefined numbers in the checksum array. This, and all the other check_pass functions give us lots of information about the password. Here it is summarised:

  • checksum_1[i] = password[i/3] + password[i/3 + 1] + password[i/3 + 2]
  • checksum_2[i] = password[i] + password[i + 2]
  • checksum_3[i] = password[i] + password[i + 3]
Here I was wishing that I knew how to use z3. Instead I had to solve it "by hand". It wasn't too hard, since if we guess the first character we can devise a whole 3 character block and the next character. Here is the code if anybody is interested:

The resulting password was MA_SECONDO_VOI_E_STATO_ANTANI?. The final level will cut out "ANTANI" from this and display that as the key. 

This was a simple but enjoyable reversing task. Thanks to the organizers for the nice CTF!