DFA 2020: Reverse Engineering

The section consists of three ELF Binaries and is a great way to learn about reverse engineering. Reverse engineering ELF files is best done in a Linux Virtual Machine, with tools like gdb (GNU Debugger), Radare2 and readelf. It can also prevent risks of infecting your host in the event you are dealing with evil malware. As it’s my first time reversing ELF binaries I would highly recommend having a REMnux set up as lots of useful tools are preinstalled!

Information

Category Name: Reverse Engineering

Files:
malware000: 12.7 kB
malware101: 6.1 kB
malware201: 6.2 kB

My Recommendations

This is my personal preference. I like being organized and deleting a folder when I’m done with it .

mkdir Documents/dfa20/malware

There are no verification hashes. You can download the files from the CTF into the malware WD.

I used Radare2 to solve two questions, as it’s automatically installed in the REMnux VM. Any disassembler should work. GCC is installed by default on Linux. If you are using another distribution you can also install ida free on your VM.

Walkthrough

1. MALWARE000 (100)

I’ve used this new encryption I heard about online for my warez, I bet you can’t extract the flag!
First, identify the file:
				
					file malware000
				
			

Which returns an ELF 64-bit executable. Going for the easy way to see its contents:

				
					strings malware000
				
			

Whoever created this encoded a string with BASE64. Decoding it:

				
					echo ZmxhZzwwb3BzX2lfdXNlZF8xMzM3X2I2NF9lbmNyeXB0aW9uPgo= | base64 -d
				
			

the command base64 -d takes an input as a file, by using echo and the | we are basically telling base64 to decrypt the string as is instead.

Answer: flag<0ops_i_used_1337_b64_encryption>

2. MALWARE101 (350)

Apparently my encryption isn’t so secure. I’ve got a new way of hiding my flags!

Repeating the same commands as above, the file is also an ELF binary. The strings output is the following:

The 10 character []A\A]A^A_ decrypts to nothing. I tagged along this very helpful writeup to see how I could use Radare2.

				
					##Give execution rights to disassemble the binary 
chmod +x malware101
r2 -d ./malware101
##Next Input
aaaaa
##Printing disassembly of main function
pdf @ main
				
			

Here is my annoted version of the output of pdf @ main (this is my understanding of it, I might be wrong in my interpretation):

If you were to read the red characters (the ones the purple arrow points to) you would get:garins>saT–lfstLCAOg>M, which contain the characters of the flag format “flag<>”.
I copy pasted the output of pdf @ main in a Text Editor and reordered the letters based on the variable.

This reads as: flag<sTaCk_strings_LMAO>

Answer: flag<sTaCk_strings_LMAO>

3. MALWARE201 (550)

Ugh… I guess I’ll just roll my own encryption. I’m not too good at math but it looks good to me!

Giving execution privileges:

				
					chmod +x ./malware201
				
			

Running the malware:

The encrypted flag is: “\x6d\x78\x61\x6c\xdd\x7e\x65\x7e\x47\x6a\x4f\xcc\xf7\xca\x73\x68\x55\x42\x53\xdc\xd7\xd4\x6b\xec\xdb\xd2\xe1\x1c\x6d\xde\xd1\xc2”

encrypt(“my message”, 10) == “\x7b\x52\xe3\x78\x6f\x42\x41\x64\x67\x62”

Going to use radare2 to get more information:

				
					r2 -d ./malware201
aaa
pdf @ main
				
			

In this excerpt of the de-compiled main function, we can see that the encryption key length = length of the string, so our encryption key is 32 bytes long (which is also the length of the cipher):

Also, the main function calls two other functions: fcn.004005b0 and fcn.00400620.

I used hints to solve this, but spent a looot of time trying to figure it out by myself. My own interpretation is that each characters is treated as the integer of that character.
fcn.00400620 is the encryption function. This is a loop that occurs in that function, the loop applies to every character (integer) of the string to be encrypted:

This works, but to get the flag the entire string/list of integers needs to be floor divided by 2 (???) no idea why.

In Python:
First, convert the cipher into a list of integers , so that each character/integer is treated individually:

				
					cipher = "\x6d\x78\x61\x6c\xdd\x7e\x65\x7e\x47\x6a\x4f\xcc\xf7\xca\x73\x68\x55\x42\x53\xdc\xd7\xd4\x6b\xec\xdb\xd2\xe1\x1c\x6d\xde\xd1\xc2"
int_cipher = [ ord(a) for a in cipher ]

				
			

Then, we tell python to perform the function on the integers and return them as characters

				
					flag = ''.join(chr((int_cipher[i]^((i%0xff)|0xa0))//2) for i in range(32))
flag
## Returns: 
'flag<malwar3-3ncryp710n-15-Sh17>'
				
			

This is my attempt at explaining the function:

Answer: flag<malwar3-3ncryp710n-15-Sh17>

TLDR

Strings can be the fastest way to find flags in RE CTFs.
Radare2 comes pre-installed in Remnux distros and is another great tool for RE. 

Recent Posts

Follow Us

Featured Video

Guide

Discover more from forensicskween

Subscribe now to keep reading and get access to the full archive.

Continue reading