Bigkey Writeup
Cyberstakes Online 2015

Like most reversing challenges, the objective of bigkey is to find a flag or a key that satisfies a given binary. However, it is immediately apparent that the key for this challenge is in not the typical short 32 character key format.

The binary starts by loading three offsets into the data segment into esi and addresses of three buffers on the stack into edi. It then uses the movsd op code to move 0x400 double-words from the data segment into the buffers.

load_bufs

Following that, it opens file pointed to by the first argument of the program and reads in onto another buffer. Next, it combines the four buffers xor buf1 and buf2, then adding the result with buf3. If that is equal to the corresponding byte in file_buf it continues. Otherwise, keyfile is reported invalid.

combine_bufs

If it makes it through the entire set of buffers successfully, print_key is called. In this function, which takes the address of the file_buf as an argument, loops through the entire buffer adding – adding together 0x40 byte chunks.

condense_file

As much as I may have wanted to, I didn’t have to do math on 0x1000 characters by hand. Therefore, I wrote a short python script to do it for me.

First I opened the file binary mode (I was confused when it didn’t work before).

with open("bigkey", "rb") as bigkey:
	bigbytes = bigkey.read()

I used 16 byte long strings from the start of each buffer to uniquely identify it so that I could read from its starting index.

buffer_one_index = bigbytes.find(b'\x86\xEA\xD5\x70\xA9\xC1\xC6\xE5\xA0\x14\x36\xE9\x5B\xA4\x34\xCC')
buffer_two_index = bigbytes.find(b'\x6C\x51\xEB\x82\x22\x0C\x01\xDC\x2A\x32\xE5\x31\x58\xBA\xD8\xCE')
buffer_three_index = bigbytes.find(b'\x51\xE4\x88\x63\x27\xB2\xE1\x02\xD1\x14\x77\x4F\x33\x61\xEF\x1E')

buffer_one = bigbytes[buffer_one_index:buffer_one_index+0x1000]
buffer_two = bigbytes[buffer_two_index:buffer_two_index+0x1000]
buffer_three = bigbytes[buffer_three_index:buffer_three_index+0x1000]

Finally, I iterated through the arrays in the data segment to produce the proper keyfile and condensed it into the printable flag.

key = ''
for i in range(0x1000):
	c = (buffer_two[i] ^ buffer_one[i]) + buffer_three[i]
	key += chr(c % 256)

flag = ''
for i in range(len(key)//0x40):
	acc = 0
	for j in range(0x40):
		c = key[i*0x40 + j]
		acc += ord(c)
	flag += chr(acc % 256)
print(flag)
*****
Written by on