In October 2022, Microsoft published a blog post about Raspberry Robin and it’s role in the current cyber crime ecosystem. Microsoft reported, among other things, that they have observed Raspberry Robin delivering the well-known malware families IcedID, Bumblebee and TrueBot besides the already known delivery of FakeUpdates/SocGholish. At this time I was not really aware of TrueBot or I simply had forgotten about it.
In December 2022, Cisco Talos published a blog post in which they reported increased activity from TrueBot and mentioned that TrueBot might be related to TA505. They have observed TrueBot delivering Grace (aka FlawedGrace and GraceWire) as a follow-up payload, which is known to be exclusive tooling of TA505.
Since I have already analyzed some TA505 campaigns a few years ago and anything related to Raspberry Robin is of interest to me, TrueBot now had my attention and I finally found some time to take a closer look and here we are.
I have decided to start a small blog series that will cover the following points:
- Analyzing different packed samples and identifying decryption/unpacking code
- How to statically unpack with Python using Malduck?
- Analyzing TrueBot Capabilities
- IOC/Config extraction with Python using Malduck
- C2/Bot Emulation
- Bonus (maybe): Infrastructure analysis
The blog series is structured so that we gain the knowledge step by step to be able to take the next step.
In this first post, we’ll look at some packed samples and gain enough knowledge to write a static unpacker in the next step.
Identifying decryption/unpacking code
We are primarily looking at the packed samples that Talos also mentioned in their blog post including one sample that I have found on VirusTotal. All of these files are 32 Bit samples, mostly DLLs except for one sample which is a regular executable.
If you look at the binary, you will relatively quickly stumble upon a large binary blob that is referenced in only one function in the binary. The two loops in which the blob is referenced should give you a good indication that something might be decrypted here, see the screenshot below.
I have checked all available samples and the decryption algorithm is identical in each case, however, there are a few different variations, how the decryption function is called. In the most common variant there is an export, which calls a wrapper function, which in turn calls the decryption function. Sometimes there is only one wrapper function, sometimes several, and sometimes the decryption code is directly in the export of the DLL.
Regular executable where the call to decryption function is located in
Decryption code directly in an exported function:
The decryption algorithm uses a hardcoded key and is XOR’ing through the entire binary blob, with incrementing the iterator by the length of the key. Additionally, another part of the decryption “formula” is a boolean
and operation with a hardcoded value. By using a debugger, it’s pretty easy to get to the unpacked code. However, since we want a have static unpacker, I reimplemented the function in Python.
Now, all we need to decrypt is the binary blob, the decryption key and the parameter for the
and operation. In my next blog post, I will describe how to get these values with help of Python and Malduck.