The Fidelis Threat Research team is comprised of expert security researchers whose sole focus is generating accurate and actionable intelligence to better secure customers. Together, they represent over... Read More
July 5, 2017
Researchers have observed TinyLoader, a well-known backdoor, delivering point-of-sale and banking trojan malware over the past few years. Fidelis Cybersecurity Threat Research happened to notice it delivered from a site that hosted a variety of other malware and that was an association we had not seen previously so it prompted us to take a deeper look. This post covers our malware analysis and then describes how our research allows for direct interaction with the command-and-control server.
Tinyloader has a few unique characteristics
It is, in fact, tiny — typically weighing in under 5 KB.
Its command-and-control (C2) server runs on Microsoft Windows, which is fairly uncommon in malware today.
Finally, it is extremely versatile due to its modular C2 mechanism. This mechanism allows the C2 server to pass custom bytecode directly into the running memory of the bot making it easy to load new malware or augment additional malicious behaviors.
Understanding how TinyLoader functions allows us to mimic bot functionality. Doing this then provides a mechanism to connect directly to malicious C2 servers to monitor commands issued, modules sent, and the running processes targeted by the operators.
In this post, we will discuss TinyLoader delivery vectors, various characteristics of its C2, and finally, how to create a script to mimic the bot functions to monitor C2 activity. We have made our script available on Fidelis Cybersecurity Github(.
The TinyLoader sample we observed was as a secondary infection. A machine that had been infected with Nymaim was later found to be downloading “188.8.131.52/pos.exe”. What’s also interesting about that IP is that the Nymaim malware was downloaded by a BetaBot sample that also came from the IP “184.108.40.206/bbcrypt.exe”. The BetaBot was found downloading Nymaim from “updateservers312.com/jaff/515_new_c.exe”.
For this research, we analyzed this TinyLoader sample: 037c675489bb0faeab114bbd6cf3067a — though any of the TinyLoader samples mentioned in the IOC section below will provide a similar outcome.
The main part of the bot is XOR encoded and wrapped in a similar fashion. The bot brute forces the XOR key out by comparing it against a known value. The brute force loop provides a custom sleep routine that was likely put in place to cause sandboxes to time out.
The first C2 transmission is a sort of checkin:
The data is in the form of:
The ‘req_num’ or request number is initially set to all NULLs but is then changed by the subsequent downloaded bytecode. This lets the C2 fully control the bot as it sets up what the bot will request next. The ‘campaign_id’ is hardcoded in the bot which is why it is labeled as such. The 0x0c in the picture is the length of the data, while the ‘bit_version’ is set by the bot after a call to IsWow64Process.
The C2 responses are sets of code sequences containing bytecode blobs that will be executed. This is an interesting way to control infections. We broke out the responses into a list (below). Due to the nature of this capability, the bot could essentially download any code to run on the infected machines.
C2 traffic responses(commands):
Gather process list
Install Code Module
Gather process list command
The initial blob of bytecode returned is used to copy a second handler bytecode blob into the memory address provided. The bot then sets req_num to 00 01 00 00. Each new request returns the same sort of setup where bytecode is sequentially written and then a handler is eventually added to initialize the code.
This sequence continues in a list of request numbers.
è 00 03 00 00
è 00 04 00 00
è 00 05 00 00
è 00 06 00 00
è 00 07 00 00 -> this sections detonates the blob of data that’s been copied
When detonated, this copied over bytecode has a whitelist of process names and a mutex. It will attempt to create the mutex and then enumerate all running processes while building a list of those not in the whitelist.
Below we can see a snippet of the code to check each process name to see if it contains a 4 byte string.
We can get a list of all the strings the bot uses to check if it’s not interested in that process.
Data is sent back to C2 with a req_num of 00 0a 00 00 along with the process list appended to the previously mentioned structure. There is also a hardcoded string that is prepended to the data which can be seen in both the bytecode and the traffic.
If the bot sends an Update Binary command, the return is bytecode to copy over a PE updated TinyLoader binary. It then sets the req num to 00 00 c1 00 to begin the next sequence.
The bot then downloads chunks through the following sequence.
00 00 c2 00
00 00 c3 00
00 00 c4 00
00 00 c5 00
00 00 c6 00
00 00 c7 00
00 00 c8 00
00 00 01 72
00 00 02 72
00 00 55 01 – restarts after file is written and persistence setup
Next, the newly downloaded bot begins running through the same C2 process again before continuing with the following sequence.
Install Code Module
The bot then goes through the following sequence to download code. The code chunks are saved for later. The code module normally downloaded contains the bytecode that can be used to download other files.
Understanding the C2 structure can help automate the monitoring of these C2s as we find them and allow us to test certain elements of the traffic. For this part, we’ll be primarily focusing on the ‘x00x00x00x54’ request because that appears to be the generic checkin request as the bot waits for additional commands. It’s also the request that other PCAPs from previous reports show as returning commands to download additional files.Let’s start with some basic Python code for sending and receiving data.Now we just need to account for receiving the data. Since the data length from the C2 is sent within the first 12 bytes we can just receive the first 12 bytes, pull out the length and then account for how much more we should read. Adding the below to our send_msg function.
For the C2 message itself we can just use a Python class to mimic the structure we have previously laid out.
This leaves us with decoding the traffic and then pulling out the relevant data we want. The decode function is a simple XOR loop.
Now we just need to see if this data is the same as the sleep routine but for demonstration purposes we’ll just try to find the next command if it exists and log the data received to screen. For all the recent versions of TinyLoader we’ve gone through the received bytecode appears to always have the ‘mov edx, dword [ebp]’ command right before it loads the next C2 command in place, this could be different for other versions and since we are dealing with bytecode being executed dynamically via C2 it could technically be anything.
The full script will be included with this post. For testing we used a currently live C2 of 220.127.116.11 port 40020.
Decoded this gives us the commonly delivered bytecode that will sleep and then perform the same request again, this makes the bot perform this ‘checkin’ over and over again until it is given another command.
Awesome, so now we can either expand on this by accounting for all possible commands from the C2 or simply use this script as a way to test for payloads on a live C2 without having to actually run the bot the entire time.
TinyLoader continues to be a widespread threat to global organizations. Here we have discussed TinyLoader capabilities, infector vectors, and how to craft a script to monitor ongoing C2 commands.
Fidelis customers are protected from TinyLoader by a variety of mechanisms designed to detect malware throughout the infection chain.
Nymaim from BetaBot:
See Fidelis platforms in action. Learn how our fast, scalable Fidelis Elevate and Fidelis CloudPassage Halo platforms provide deep insights into the SOC to help security teams worldwide protect, detect, respond, and neutralize even the most advanced cyber adversaries.