A short challenge: picoCTF reverse engineering
I am slowly going into the world of CTF, “Capture the Flag”. I am not talking about the first person shooter multiplayer game type, but of a series of challenges online related to computer engineering and computer science, of very varied topics.
picoCTF is a great site to start. It offers very simple challenges, slowly goes upwards in difficulty, and it also hosts competition events. The difference with other sites, such as Hackerrank, is that here, the focus is on finding a flag, a string. The code is not really important, and for many challenges, you actually don’t have to code at all. Sometimes this flag is inside a hidden server, sometimes it can be in some obscure header of an uncommon protocol, and sometimes it is encrypted. I guess that it can also be “all of the above”.
I will be talking today about “Transformation”, one of the first challenges of reverse engineering available at picoCTF.
If you want to solve it (and I encourage you to do so), stop reading here and go give it a try. It is indeed a very fun one.
Clicking on “enc” will download a file. But for these challenges, a console will facilitate stuff a lot, so:
wget https://mercury.picoctf.net/static/77a2b202236aa741e988581e78d277a6/enc
Catting the file gives us this very confusing output:
Well, what now? Let’s look back at the screenshot of the challenge. Chinese characters require two bytes to be represented. The code given is grouping elements and converting them into characters. Let’s first make the encryption code, but in a more clear way that what is offered to us:
string = 'Hola'first_part = ord(string[0])
print(f'First byte {first_part}')
first_part_shifted = first_part << 8
print(f'First byte shifted {first_part_shifted}')
second_part = ord(string[1])
print(f'Second part {second_part}')added_elements = first_part_shifted + second_part
print(f'added_elements = {added_elements}')
first_two_letters = chr(added_elements)
print(f'First two letters: {first_two_letters}')
Essentially, we are taking the first character, transforming into its index in the ascii table, then shifting to the left one byte (this makes the value bigger, adding an empty byte to the right), and adding the second letter’s index of the table. Then, we transform this number into a character again, one which will not be on the common ascii table. However, it will be present on the modern extended character tables, which includes far more elements:
Now we have a better understanding of how our challenge was made. Let’s now try to decode the string that is offered to us.
This is my current approach:
Before explaining this code, let’s see the results:
So, the first chinese character is received. It is transformed into its ascii representation. Every group of two characters in hexadecimal here, is a byte. Every byte is separated and interpreted as a single byte character. And thus, the “encryption” is broken. I put some dots on top of the flag to not reveal the actual string solution.
After finishing, I googled to see other solutions. Of course, Python already had a oneliner for this, taking the entire string and asking it to be encoded as UTF16 Big Endian. Googling for other solutions after finishing a challenge of any type is always a humbling experience and a good way to learn stuff.
It was simple and fun, and I wanted to share it.
Have a nice week
Alejandro