Special thanks to FLARE team for their annual FLARE-On challenges!
In this article I would like to show you how reverse engineering process looks like, where to put attention and some tricks I use.
Let’s get started! I will use special FLARE-On Level from BHUSA2019 as example. Link to the archive with password is on the picture below.
Downloaded archive contains two files — our binary and note which says: “Solve the challenge to get a sticker”.
First thing I usually do is checking binary file with file utility (https://linux.die.net/man/1/file) to get insight about its file extension.
$ file MemeCatBattlestation.exeMemeCatBattlestation.exe: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
It is .Net assembly, so to proceed further we need the following things:
- Windows environment to be able to run our binary — You can get one for free with the following link https://developer.microsoft.com/en-us/windows/downloads/virtual-machines.
- dnSpy (https://github.com/0xd4d/dnSpy)— .Net decompiler and debugger.
- (Optional) I recommend to install FLARE VM(https://www.fireeye.com/blog/threat-research/2017/07/flare-vm-the-windows-malware.html) on your just downloaded Windows Virtual Machine. FLARE VM has a bunch of pre-installed software for reversing and analyzing malware.
Now we are good to run binary in our virtual environment.
Stage 1 — MARAUDING TABBY FRIGATE
Program expects to receive correct input for Weapon Arming Code, otherwise you will get Invalid Weapon Code message.
It is time to analyze our program with dnSpy utility. The best option to get general understanding of program workflow is to take a look at Main function, navigate to MemeCatBattlestation>Program>Main. Main function gives us some tips how to get VictoryForm — we need to collect all three WeaponCodes (lines 34 to 36).
From all Stage1Form functions FireButton_Click is most interesting. FireButton_Click function compares our input with string “RAINBOW” (line 3), if it is true, FireButton_Click will set WeaponCode equal to our input(9) and will start victoryAnimationTimer(line 10).
That it! We have our first code! Enter it as Weapon Arming Code and you will see cool animation.
Stage 2 — PERIMETER DEFENSE KITTEH
Similar to previous stage we should pay attention to FireButton_Click function from Stage2Form. Now we have isValidWeaponCode function which verifies our input. At first it uses “for loop” to iterate over our input (line 5) to XOR each byte with value 65 and loop counter multiplied by two (line 9). Then isValidWeaponCode function compares our XORed input with array in the return statement with function SequenceEqual (line 11).
This is so called XOR cipher (https://en.wikipedia.org/wiki/XOR_cipher) and to break this cipher we just need to know how encryption and decryption process looks like:
Encryption: Plaintext ^ Key = Ciphertext
Decryption: Ciphertext ^ Key = Plaintext
To summarize — to decrypt the ciphertext, merely reapplying the XOR function with the key will remove the cipher.
In our case, Key is the sum of value 65 and loop counter multiplied by two (line 9) and Ciphertext is array in the return statement (line 11). To get Plaintext we need to XOR Ciphertext and Key.
We have everything we need to write our decryption routine. I wrote simple function which takes one argument Ciphertext as variable flag_enc(line 1), iterates over Ciphertext to XOR each byte with corresponding key value (line 4) and return Plaintext as variable flag(line 5).
Our second code! Enter it as Weapon Arming Code and you will see cool animation.
Stage 3 — KEYBOARD CAT JUGGERNAUT
We are almost there!
At stage 3 isValidWeaponCode function uses InitializeBattleCat method to encrypt our input and compare it to array in return statement(line 5). In addition it has getCatGenetics method to encode WeaponCode we entered in stage 2 with base64 encoding(line 4).
Mentioned above InitializeBattleCat method invokes AssignFelineDesignation function which is responsible for our input data encryption with two arguments — result from getCatGenetics as array cat and our input as data. At first AssignFelineDesignation generates key array s with InvertCosmicConstants function using array cat as input (line 3). Then AssignFelineDesignation uses Enumerable.Select method to apply lambda function to each element of data as variable b (line 6–11). Lambda uses a little bit of math to pick certain value from generated key array s to XOR with our input data (line 8–11). So we have XOR cipher and to find correct WeaponCode we need to decrypt array from return statement in isValidWeaponCode function using same approach as we did in stage 2.
The “trick” here is to find which variables we control and which not. In this case it is variable b which is an iterator over our input data. We also control cat variable, but it is based on our previous entered WeaponCode (from stage 2), so it is always the same as well as array s. This means that we only need to XOR array from isValidWeaponCode instead of our input to decrypt it.
We can do this by modifying current code or reimplement all needed functions with python as I did.
We have our final code! Enter it as Weapon Arming Code and you will get FLAREOn flag.
Today we learned how to analyze .Net assembly and how to write decryption routine with python. Reverse Engineering is very interesting and exciting topic which is essential for malware analysis and exploit development! I encourage you to try solve MemeCatBattlestation by yourself.
Also, the main event FLAREOn challenge is still active so give it a try!