Flare-On 5 CTF WriteUp (Part 2)
This is part 2 of the Flare-On 5 CTF writeup series.
4 - binstall
It is time to get serious. Reverse Engineering isn't about toys and games. Sometimes its about malicious software. I recommend you run this next challenge in a VM or someone else's computer you have gained access to, especially if they are a Firefox user.
Similar to the last challenge, binstall.exe is a .NET PE. However this time it has been obfuscated using ConfuserEx.
All original method names and removed and strings are encrypted. Running de4dot gives somewhat a clean assembly.
Strings are still encrypted. For example, ExpandEnvironmentVariables
takes a string as an argument which is decrypted at runtime. De4dot supports string decryption by specifying the method token of the decrypter. However, the author was not able to get it to work likely because the decryptor methods were generic which de4dot doesn't seem to support.
Decryption of strings is not a priority as we can always debug the binary and get the strings at runtime. However, let's do it anyway. ConfuserEx being quite a popular obfuscator there are many public (and private) deobfuscators sparing us from writing our own decrypter. A tool named "ConfuserEx Static String Decryptor" was able to decrypt all the strings and we get a clean assembly as shown below.
Analyzing binstall.exe
With the obfuscation out of the way, let us begin analysis. Main
first calls smethod_7
. Note that this is not the original name of the method. The obfuscator removed original method names during the obfuscation process. Consequently, since de4dot cannot guess the original name it generates a name based on the method signature.
smethod_7
calls smethod_3
, smethod_2
and smethod_4
.
smethod_2
opens the FireFox profiles.ini file and removes all occurrences of the string Path=Profiles/
from it. Additionally, it also clears the FireFox cached files.
Similarly smethod_3
clears off the Chrome browser cache.
smethod_0
and smethod_1
are helper methods to delete a directory and a file respectively.
Lastly, smethod_4
clears the Internet Explorer cache.
Going back to Main
the next call is to smethod_5
with path constructed from the %APPDATA%
environment variable and ending in browserassist.dll
.
smethod_5
decodes a piece of base64 encoded data and decrypts it by xoring it with 0x33
. The decrypted data is written to the file browserassist.dll
.
Lastly, Main
calls smethod_6
.
This method adds browserassist.dll
to the AppInit_DLLs
registry key. The AppInit_DLLs
are a set of Dynamic Linked Libraries (DLL) that are loaded upon startup into the address space of every executable that links with user32.dll
. Essentially, this means everytime a GUI application is run, browserassist.dll
would also be loaded into it. This is a typical modus operandi of malware.
Extracting browserassist.dll
is easy. We can either copy the base64 text and decrypt ourselves or run the malware in a virtual machine and copy the dropped DLL from the said location.
Analyzing browserassist.dll
As its name suggest, browserassist.dll must be intended to be loaded in a Web Browser. However, being registered as an AppInit DLL it will be loaded in all GUI applications. Naturally, the DLL is likely to check whether it is running in the correct process before it begins its operations.
Analyzing the disassembled code there is indeed a call toGetModuleFileNameA
to retrieve the full path of the process in which the DLL is loaded.
The filename is then passed to a function which calculates a hash value from it. For success, the hash must match 4932B10F
.
The hashing algorithm is simple, the decompiled code of which is shown below.
We can reimplement the same algorithm in C.
For the string "firefox.exe" this yields the same hash as expected by it. This explains why the challenge description recommends running this on a system where Firefox is installed.
$ gcc hash.c -o hash
$ ./hash firefox.exe
firefox.exe -> 4932B10F
If the hash matches, it compares the File Version Info.
In particular, the major version must be less than 55. If all of the conditions match it proceeds to start a thread. The thread function constructs a string on stack byte by byte.
The string is then xored with 0xD7
.
The xored string is passed to another function which looks to decrypt something.
Dynamic Analysis
At this point let us switch to dynamic analysis. We install an old version of Firefox like 34.0 from https://ftp.mozilla.org/pub/firefox/releases/34.0/win32/en-US/ in a Virtual Machine. Running binstall.exe drops browserassist.dll which is also added to the list of AppInit DLLs. We can now start Firefox under x32dbg, set it up to break on module load. In this way, x32dbg pauses whenever a new DLL is being loaded. Once browserassist is loaded, set a breakpoint on the CryptDecrypt
call.
When the breakpoint is hit, stepping over the call we can get the decrypted data.
The decrypted data looks to be a URL pastebin.com/raw/hvaru8NU
. Navigating to the URL we find another base64 blob.
The data is encrypted and the same call to CryptDecrypt
decrypts it.
Analyzing the injected code
We can dump the code to a text file for further analysis. Formatting using a JSON beautifier we get the following.
which when displayed in a tree view looks like
Essentially the JSON code is a webinject config. Visiting any URL beginning with flare-on.com
injects Javascript code into the matching js files - controller.js
, model.js
, view.js
.
http://flare-on.com/ is the homepage of the FLARE challenges. It is modelled like a Linux a shell and supports commands like ls
, cd
to navigate etc.
If we take a diff between the original js files (by opening the URL in a clean browser) and the modified one we can quickly zero in on the changes.
A new command su
is added in controller.js
, but executing the command requires a password. The password is checked by the function cp
in the same file.
The code is lightly obfuscated. After formatting and simplifying we get
The root password is k9btBW7k2y
. However, typing the password at the su
prompt does not give us the flag. Looking again at the diff we can find the changeDir
function is modified too.
On every cd
command it is checking whether the directory name matches with something. Running the code separately we can find that the dir name is key
Navigating to the directory and typing ls
gives us the flag.
FLAG: c0Mm4nD_inJ3c7ioN@flare-on.com
Continue with the next part: Flare-on 5 CTF Write-up (Part 3)