Monthly Archives

2 Articles

Brief notes on some of the Flare-On 2020 challenges

Posted on

This was my first flare-on and it was quite fun. I ended up procrastinating for a few weeks after finishing challenge 10 so the end result was not quite what was desired. So here are my thoughts on challenges that I consider to be interesting, which mainly focuses on challenge 9 and 10. As the official writeup will come out soon and will no doubt be far better than my writeup, I’ll likely not edit it too much.

Challenge 6

This was a frustrating challenge that took me 11.5 hours (mostly spent figuring out non-solutions) to solve. The binary is a QR code generator written in AutoIt. I initially expected this to be easy since AutoIt was my home turf (however out of practice I might be), however, this proved not to be the case. The deobfuscation was fun and easy to write as the obfuscation is extremely simple. However the final part took far too long, it took me around 8 hours to figure out that the decryption function was collecting bits and combining them into bytes 7 at a time to generate the desired password.

Challenge 7

This is by far my favorite challenge. In short, we have a pcap file of a network attack against an IIS server exploiting CVE-2017-7269. After identifying the exploit, the first step was to extract the shellcode. Initially, I could not get it working, but then after reading an article on the exploit that shows the disassembly of what’s going on behind the scene, I realized that the shellcode is to be converted to wide strings, and after that things were fairly simple. We had to fix up the register in a debugger (I believe ESI was to point to the beginning of the buffer), and then debug and then continuously dump the next stages until we get the flag data.

Challenge 8

I dislike this challenge. The flag was a gibberish string unlike the other challenges so I spent hours that I shouldn’t have. If not for that it would’ve been quite fun. My solution was dumping the ELF binary, patching it so that the check always returns ‘X’, repackage it in the resource and then run it.

Challenge 9

This challenge was fun. The challenge file is a PE file which does 2 things: load a driver using CapCom, and registers a COM DLL.

The manual mapper is written by the author and can be found here. The main difference between the public implementation and the private one is simply some slight obfuscation and the change in the pooltag. The mapped driver registers a registry callback.

Knowing that a driver is in play, I applied one of my techniques for dynamic analysis here that I have not seen discussed anywhere else (though I am sure it has been done by many before). The technique in essence is hooking the free function and dumping the buffer content before freeing. This allows us to see a lot of interesting information in binaries simply by running it without the need for debugging or anything else. In this case, as the target is a kernel driver, I used a hypervisor to hook ExFreePoolWithTag and dump the pool if the caller is not a valid target driver image. This gave us a very interesting string, “H@n.$h0t.FiRst!”, which will later be used. Now, onto static analysis, we can see that the driver registers a registry callback.

Inside it, it checks if the registry key operation is on the COM key “{CEEACC6E-CCB2-4C4F-BCF6-D2176037A9A7}\Config”, and if it matches that, the key is created with the class set to “H@n.$Sh0t.FiRst!”. This confirms that what we extracted earlier from our hypervisor is indeed some sort of password that will be important later on.

Onto the COM DLL that is registered, we can see that it first clears the Password and Flag field inside DllRegisterServer.

This activates the registry callback described before. Next, we can see that DllGetClassObject returns to us an object with a vtable, as is typically the case with COM APIs.

Outside of the standard functions, we can see that there is a custom function which gives us another vtable

This final vtable contains two functions, one which reads the password from the “Password” key and another which decrypted a buffer with it and writes the result to the Flag key. As a result, I LoadLibrary-d and called the functions in the COM DLL to get the password. I originally planned to write a full COM client however I decided to take the more lazy route as it works just fine.

Bugs in the challenge

This challenge had several bugs in it. The first of which is that it does not work on multi-core systems due to CapCom being used in an unsafe manner, thus we have to change our VM to be single-cored.

The second bug lies in the password decryption function. Do you see the bug?

That’s right, the variable pcbData was not initialized. The documentation for RegGetValueW states that the last parameter is a “pointer to a variable that specifies the size of the buffer pointed to by the pvData parameter, in bytes”, however in this case pcbData is not initialized and as such contains a gibberish value. In some cases, we might be fortunate enough that it contains a value that is higher than the size of the registry key and as such the read is successful, however, this is not guaranteed, as the value could be zero and the read could as such fail completely.

Challenge 10

Kudos to whoever made this challenge because it was absolutely painful and fun to work with.

A brief overview of the sample, it is essentially Armadillo but on Linux, it employs the same kind of nanomite-based obfuscation using ptrace and fork. There are two main techniques that I applied for reversing the file: static analysis and LD_PRELOAD hooking. As we cannot perform regular debugging due to the presence of nanomites, I applied the same technique discussed above to dump buffers that are passed into various functions. For reasons unknown, my dlsym hook (which was required for hooking ptrace as the function was dynamically resolved) did not work on Debian, however it worked perfectly on Ubuntu. I’ll publish the code within a few days.

When we look at the main() function, it appears deceptively simple.

However, when we input the string as a flag, the binary tells us that it stole our flag. What’s going on?

Using the technique of LD_PRELOAD hooking, I intercepted various functions such as memcmp, strcmp, as well as logged calls to ptrace() to extract information about what the binary is doing. One call to memcmp in the log stands out:

Well, if that doesn’t look like a part of the flag! What would happen when we enter it into the binary? As it turns out, the binary now consumes the entire CPU core for around 10 minutes or so before telling us that our password is wrong instead of telling us so immediately. So, we’ve likely done something right.

Further static analysis reveals a function that runs before main() which forks and initializes the first nanomite.

The nanomite debugger function then uses ptrace(PTRACE_POKEDATA) to write the UD2 instruction to the sunshine check that we first saw in

When the #UD is eventually raised, execution is redirected to the real password check function.

The function is as follows.

It’s passing rm -rf –no-preserve-root / into execve? What’s going on? As it turns out, ptrace on Linux allows for the interception of syscalls and that is exactly what’s going on here. Various syscalls are intercepted by the nanomite debugger, which then does certain operations depending on the syscall ID in EAX. The syscall ID is XORed with 0xDEADBEEF and multiplied with 0x1337CAFE resulting in the final nanomite operation ID. The IDs, their syscall, and the operations that it does is listed below.

In this case, execve simply removes the new line character at the end of a string, and nice decrypts a string from a table and writes it into the debuggee.

This is then passed into memcmp in the real password check function we’ve seen above. And voila, we have verified that what we obtained earlier is in fact the first part of the flag.

After this, we enter the function that I’ve named “stringhash_teaenc”. This function is the reason why the binary takes forever to run, as it employs not just 1 but 2 layers of nanomite to obfuscate it’s encryption algorithm.

As we can see, it gets a string using nice() and hashes it with crc64. This is then used as the decryption key to decrypt a buffer, which’s initial 20 bytes have been overwritten with the password. The entire buffer decrypts fine except for the first 20 bytes which are invalid as we do not have the password. The rest contains the entire Bee Movie script with a weird binary blob in the middle, which we will revisit later. The tea decryption functions are as follow.

There are several things going on here:

  1. The uname, pivot_root, chmod and mlockall syscalls are handled by the nanomite 1 debugger. The first 2, uname and pivot_root are simple and their operation can be easily seen in the comments above. The other 2 are more complicated. As we can see below, the mlockall handler tries to call the variable call_nanomite2. This was previously initialized to 0. The result is a SIGSEGV, which is then handled by the second nanomite debugger that we saw created earlier.
    In this case, the operation simply set eax to the second parameter + 1.

    The chmod call was similar, however in this case it does multiple operations, not just 1.
  2. As we can see, there are multiple calls to 0 inside the tea decrypt function. This is handled similarly to the way the first nanomite debugger called the second nanomite debugger, however the operation in question is a loop.
    In essence, null_call(&loop_start_address, &counter) will loop the counter from 0 to 15 and then returns.

Summing this up, we have enough information to begin implementing a non-obfuscated version of the encryption function. We can identify that it is a TEA-like algorithm based on the constant we retrieved (0x9e3779b9c6ef3720), and the key to the function is the CRC64 hash of a string, which is 0x674a1dea4b695809. Reversing the algorithm, we can decrypt the next part of the flag, which was located in the first 20 bytes of the buffer we saw earlier. We got “4nD_0f_De4th_4nd_d3strUct1oN_4nd”, which makes it “w3lc0mE_t0-Th3_l4nD_0f_De4th_4nd_d3strUct1oN_4nd”.

Recall the buffer I mentioned that was stuck in the middle of the Bee Movie script? That turns out to be a shellcode that does quite a lot of math. It’s not actually called, but reversing it will reveal the final part of the flag. The function in question uses a bignum library to do some calculation based on some data in the binary.

The first problem we have to solve is passing the first check involving bignum_03 and bignum_09. A simplified version of the function stripping out everything that’s irrelevant is as follow:

To pass the equality check, bignum_04 ^ bignum_rand mod bignum_01 must be equal to bignum_03. And as we can see, bignum_04 and bignum_03 are both the same value, and is less than bignum_01. This means that bignum_04 mod bignum_01 == bignum_04, and as such the bignum_rnd value should be 1 to ensure the equality.

The operation in question is essentially

math_powmod_naive(&bignum_02, &bignum_rnd, &bignum_01_p, &bignum_06);
math_divmod(&bignum_rnd, &bignum_01, &bignum_11, &bignum_08);
math_powmod_naive(&bignum_02, &bignum_rnd, &bignum_01, &bignum_06);
math_powmod_naive(&bignum_04, &bignum_rnd, &bignum_01, &bignum_09);
math_mul(&bignum_07, &bignum_06, &bignum_rnd);
math_divmod(&bignum_rnd, &bignum_01, &bignum_11, &bignum_10);
if (bignum_05 == bignum_10)

bignum_06 = bignum_02 ^ (bignum_rnd % bignum_01)
bignum_11 = bignum_rnd / bignum_01 // 1/bignum_01
bignum_08 = bignum_rnd % bignum_01 // 1
bignum_rnd = bignum_06 * bignum_07
bignum_06 = bignum_02 ^ (bignum_rnd % bignum_01)
bignum_09 = bignum_04 ^ (bignum_rnd % bignum_01)
bignum_11 = bignum_rnd / bignum_01
bignum_10 = bignum_rnd % bignum_01

Here, one of the images that was decrypted earlier in the binary gives us a hint as to how to solve the next part. This stackoverflow page might also be helpful.

As this part was solved with the help of someone who’s better at math than me, I’ll avoid inadequately explaining it and simply not explain it at all. You can check the official writeup for a detailed explanation when it comes out. Anyhow, solving it, we obtain the last part of the flag, “_n0_puppi3s@flare-on.com”.

Challenge 11

Challenge 11 is an DFIR challenge where we analyze the registry dump of an user infected with a Gozi-ISFB malware variant. It does not feature anything difficult like challenge 10, rather it is mostly tedious due to the huge amount of things to look through. Hasherezade’s tools were extremely helpful (though it didn’t support 64-bit binaries properly and I had to add that myself). Diaphora was also extremely helpful.

The startup of the malware was interesting and is one I have not seen before. It uses a GroupPolicy Logon Script to execute the powershell script that was stored inside another registry key. The string decodes to “iex (gp ‘HKCU:\SOFTWARE\Timerpro’).D”.

I couldn’t get Autoruns to work properly on the hive, so I initially did not find this, rather, I found the script stored inside TimerPro directly.

BitRAT pt. 2: Hidden Browser, SOCKS5 proxy, and UnknownProducts Unmasked

Posted on

Pt. 1 of the BitRAT series.

During my initial analysis, there were several features in BitRAT that I did not have the opportunity to fully analyze. As such, I thought another post is merited to explore these functionalities further. In addition to this, analysis of the binary revealed strong similarities and shared code with the Revcode malware. We could from this infer that BitRAT has a significant relationship to Revcode, whether it is the developers sharing code or the developers being in fact the same person. The information leading to this assessment will be explored in detail in the last section of the post.

Hidden Browser

I did not explore the Hidden Browser feature in much detail initially, as I assumed it would merely be an interface built on top of TinyNuke’s HVNC. However, this assumption was incorrect. The Hidden Browser (command 65-6E) is implemented separately and from scratch. The first command (0x65) calls the remote browser initializer (004B6A64), which is a considerably large function due to the heavy use of STL, Boost, and string obfuscation. Due to this, screenshots will be combined and cut to fit in the article. First, it generates a random 16-character string, which it then uses to create a named desktop.

Then, it tries to obtain the default installed browser by querying the file association for the “.html” extension.

Currently, only Chrome is supported and the function returns prematurely if another browser is set as the default .html  handler. BitRAT then checks to see if Chrome is already running. If this is the case, it creates a new browser profile in the temp directory, otherwise it uses the default profile.

It then appends some parameters disabling certain chrome features as is typical of HVNC browsers, creates the process and saves the browser window’s handle.

After this, the current thread enters a loop where it continuously screenshots the current browser and sends it back to the C2 server. The screenshot function makes use of BitBlt and GDI to take the screenshot, then convert it to a JPEG image and passes it back.

Parts of the image capturing code

Conversion to JPEG

Overall, the hidden browser is essentially another fairly basic HVNC implementation. For those not familiar with how HVNCs work, MalwareTech’s post is a fairly simple introduction that should clear things up.

SOCKS5 Proxy

For interfacing with the tor service that is dropped to disk, BitRAT makes use of the SOCKS5 library “socks5-cpp“. Interestingly, around 3 years ago a Steemit post was made describing how to use this specific library for sending traffic through Tor, this is presumably where the idea was taken from.

 

 

UnknownProducts, BitRAT, and the link to Revcode

A few days after I posted my initial article on BitRAT, @tildedennis noted that BitRAT is quite similar to the Revcode malware. Though I didn’t see it for a few days due to Twitter filtering out the notification, I was immediately interested for several reasons:

  1. I’ve dealt with Revcode before and have identified its author as Alex Yücel, notorious for developing the Blackshades malware.
  2. I knew that at one point, Revcode had a C++ payload that used Boost; however, I have not until now had a sample of this to look at and have only reverse-engineered the VB variant of it. The usage of Boost was shortly removed after it was implemented.
  3. UnknownProducts’ timezone is GMT+2, which matches Sweden. He previously pretended to be Russian, however this is utterly unconvincing for various reasons.

Given this reliable indicator that the two are possibly linked, a comparison between a sample of Revcode’s Boost variant (be535a8c325e4eec17bbc63d813f715d2c8af9fd23901135046fbc5c187aabb2) and BitRAT is in order. The sample was trivial to unpack, the packer stub was built on 18 Jan 2019 05:29:34 UTC and the Revcode file inside was built on 20 Dec 2018 03:02:36 UTC.

RunPE

What first caught my eye when reverse engineering BitRAT’s RunPE is how injection APIs are imported statically (refer to the previous post) and how a function parameter controls the return value.

While the rest of the RunPE was copy-pasted, I could not find any public RunPE implementation that has such an option for the return value or even one that references dwProcessId. As such, I immediately searched for references to injection-relevant APIs within Revcode and immediately found a virtually identical function with the same method for controlling the return value.

The rest of the code was virtually identical, with the only significant difference being that BitRAT encrypts the “NtUnmapViewOfSection” string.

RunPE in BitRAT

RunPE in Revcode

Keylogger

BitRAT’s keylogger hook callback (4ABC8D) decodes key data into human-readable strings. For example, the strings “{NUMPAD_2}”, “{NUMPAD_5}”, “{NUMPAD_7}”, “{F12}” are used to represent such keys. The same strings are used in Revcode. In fact, the entire keyboard hook function is identical.

Part of BitRAT’s keylogger callback

Part of Revcode’s keylogger callback

Service Manager function

The service manager shares identical strings such as “Boot Start,” “Win32 share process”, “The service is stopped,” “The service is in the process of being stopped.” While these strings are likely widely used elsewhere, they are referenced in the same manner and order. Furthermore, a comparison of the control flow graph reveals that BitRAT’s service manager only differs in complexity and length due to string encryption and SEH.

The flow graph of the service manager function. BitRAT is on the left, while Revcode is on the right.

Identical command handling mechanisms

A significant amount of command names are similar between the two malware. Both abbreviates “process” as  “prc”. Both do not abbreviate “webcam”. Furthermore, both BitRAT and Revcode set up a table of command strings and command IDs the same way. The command string gets passed to a function that returns a DWORD pointer, which is dereferenced to set the command ID. The only difference between the two in the command text and the lack of string encryption in Revcode.

BitRAT’s command list initialization

Revcode’s command list initialization

Audio recording

BitRAT and Revcode both use A. Riazi’s Voice Recording library for recording audio from machines infected by it. The only difference is that in BitRAT the debugging strings are stripped out while they are present inside Revcode.

CVoiceRecording::Record in BitRAT

CVoiceRecording::Record in Revcode

Other shared strings

Some tag strings presumably for formatting data for communication are common between the two.

 

Decrypted BitRAT strings

Strings from the Revcode binary

Conclusion

Given the findings above, it should be fairly evident that BitRAT is a successor to Revcode’s Boost payload.  Sadly, UnknownProducts’ bid to remain unknown did not work out too well due to the practice of code reuse. While it is possible that the relationship is based only on code-sharing, the combination of the matching timezone makes this unlikely to be the case. Revcode dropped around March 2019, and in April 2019, UnknownProducts posted the initial development thread for BitRAT. The product was finally released in June, suggesting that Revcode’s Boost and non-Boost codebase were split into two, one for sales as Revcode and one for sales as BitRAT. This split was probably done to increase sales and market presence and to allow the aggressive marketing of illicit features such as HVNCs and remote browsers, which are meant exclusively for fraud.