Sunday 11 October 2015

Fireeye - FlareOn 2015 (Challenges 1-3)

I took the day off today to solve the Fire Eye Reversing FlareOn challenges [1] and decided to publish my notes here. These challenges were very entertaining and I strongly recommend to anyone who is interested in reversing for fun.

In total, there are 11 challenges with different levels of difficult and covering the most diverse kind of technologies (from .NET to mobile reversing). This post goes through solutions for the first challenges. 


.::[ Challenge 01
This challenge is a win32 executable and basically validates a password inputed by the user. If the password is correct the binary outputs a flag otherwise an error.

Figure 01: Challenge 01 XOR encryption scheme
By analyzing the code we realize that the binary compares the user input with an encrypted string located at address "0x00402140". This string has 24 characters (according comparison at the address "0x0040105e") and is the targeted flag in this challenge.


Figure 02: Encrypted key located at position 0x00402140 (24 characters)
The software uses an xor based encryption scheme with key equal to "0x7d". This key could be found hardcoded at address "0x00401053". To recover the original password it was necessary to:

password = xor(encrypted_password, key) = "bunny_sl0pe@flare-on.com"

Figure 03: Challenge 01 flag
Summarizing:
  • Binary name: i_am_happy_you_are_to_playing_the_flareon_challenge.exe
  • MD5: 7c0f16de595ae03e2928d3fa6b73b235
  • Cryptographic key: 0x7D
  • Password size: 24 characters
  • Encrypted password: 1F08131304220E114D0D183D1B111C0F18501213531E1210
  • Decrypted password (flag): "bunny_sl0pe@flare-on.com"

.::[ Challenge 02
This challenge is also a win32 binary without the extension ".exe" (the binary has to be renamed before executed). The binary is designed to validate a password inputed through standard input. If the password is correct then the flag is output otherwise an error. 

The first detail to observe within the binary is the size of the password which is 37 characters (0x25). This information can be extracted by observing address "0x0040108e". Figure 04 shows the code responsible for validating the size of the password. 

Figure 04: Code responsible for validating the size of the password
Immediately after validating the password size the execution flows to the main decryption block. Figure 05 shows the decryption and main block used in this challenge. 

Figure 05: main decryption code 
In this block we can recognize a XOR based cryptographic scheme with key equal to "0x1c7" located at position "0x004010a9".  Actually, besides the XOR operation, the block performs a set of small transformations. The data index register (edi) in this block is pointing to the encrypted data located at address "0x004010f4". 

Figure 06: Encrypted data 
The full heuristic of this block can be described as the following pseudo-code
  1. initialize 2 "zeroed" variables: one is the summation (stored at bx) and the other one is the rotation stored at dl (first 8 bits of edx);
  2. Iterates over each character within the inputed password; 
  3. apply a mask of 0x3 (11b) to summation variable. This means that the outcome of this operation can be any value between 0 and 3
  4. XOR the character with the key 0xC7;
  5. The resulting value of the previous operation is stored in al register segment (first 8 bits of AEX register);
  6. rotate left ah in dl bits; 
  7. Evaluate the expression al = al + ah + CF (Carry Flag);
  8. Compare the value of al with the encrypted character pointed by edi;
  9. if is not equal: exit("invalid password!");
  10. Otherwise: 
    1. bx = bx + al (update the summation variable);
    2. go back to step 2.

In order to decrypt the encrypted content and recover the plain text password, we need to reverse the above mentioned heuristic. The reversed operation for the encryption heuristic is: 

plain_text_char = XOR ((encrypted_char - shift_var),  key)

We created a small Ruby script reversing the above described heuristic. Figure 07 shows the Ruby script created to decrypted the data. 

Figure 07: decryption Ruby script 
 This script will decrypt and output the password. Figure 08 shows the output of the decryption script.
Figure 08: decryption script output

Finally we get our flag and a success message when executing the challenge binary.

Figure 09: success message when executing the binary with the right password


Summarizing:

  • Binary name: very_success
  • MD5: d88dafdaefe27e7083ef16d241187d31
  • Cryptographic key: 0xC7
  • Password size: 37 characters
  • Encrypted password: A89A90B3B6BCB4AB9DAEF9B89DB8AFBAA5A5BA9ABCB0A7C08AAAAEAFBAA4ECAAAEEBADAAAF
  • Decrypted password (flag): "a_Little_b1t_harder_plez@flare-on.com"


.::[ Challenge 03
Challenge 03 is composed by a "frozen" Python script. This characteristic can be verified by many ways, such as: monitoring the filesystem, by the icon of the application or string analysis. Figure 10 and 11 shows the output of the "strings" command and "procmon" [3] (application from sysinternals) with some evidences that the binary is, indeed, a frozen Python script. 
Figure 10: "strings" outputting some strings containing references to Python 
Figure 11: Procmon monitoring the elfie binary and showing references to Python
The binary shows an image in the background and prompts for the flag. For this challenge the first step was extract and inspect the content of the executable. We used the PyInstaller Extractor [4] to extract all the content inside the executable. The extractor will create a folder called "elfie.exe_extracted" with many files inside. We are interested in the file called elfie (without any extension). This file has a big python script full of variables with obfuscated names and containing pieces of base64 content. Figure 12 shows a piece of this obfuscated script. At the last line of this file it is possible to spot a very interesting line which concatenate all variables, decode and execute the outcome content.  
Figure 12: decompiled elfie python script 
If we replaced the "exec()" by "print()" this script will print the source code. This source code is still obfuscated but at least the execution flow and some strings are still readable. In fact most of the code is a base64 related to the images and the real source code has less than 50 line of code. Figure 13 shows the flag inside the deobfuscated source code. 

Figure 13: Decompiled Python source code

We can spot the flag inside this file (passed as parameter to the "reversed()" function) which is: "Elfie.L0000ves.YOOOO@flare-on.com". Now if we type this value in the challenge elfie application we get success.  

Figure 14: Flag
Summarizing:

  • Binary name: elfie.exe
  • MD5: 8f0400fe6d897ddbcef2aaf9f9dbd0a4
  • Decrypted password (flag): "Elfie.L0000ves.YOOOO@flare-on.com"


.::[ References:
[1] http://www.flare-on.com/
[2] http://www.aldeid.com/wiki/X86-assembly/Instructions
[3] https://technet.microsoft.com/en-us/library/bb896645.aspx
[4] http://sourceforge.net/projects/pyinstallerextractor/files/

1 comment:

  1. Hello o/,

    Cool article :D

    Some r2tips, for the first one try to use the radare2 visual graph "VV" after an analysis "r2 -A" or "aaa" within radare2. Also, you can use "wox" to perform xor operations directly within the radare2 open in -w mode.
    Try using r2 with https://conemu.github.io/en/Screenshots.html it will looks much better with the tango theme for example + utf8 "eco tango" "e scr.utf8=true" and of course truecolor => " e scr.truecolor = true"

    Enjoy,
    Feel free to come on #radare @ freenode :D
    https://twitter.com/maijin212

    ReplyDelete