Robert Giczewski

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

Trickbot tricks again

17 Nov 2020 » malware_analysis, reverse_engineering

After the disruption of the Trickbot botnet by Microsoft and “allies”, it had become quiet about Trickbot. At least for a couple of days. Just a few days after the partial takedown, comrade Emotet came to the rescue and executed Trickbot on infected systems [1] [2].

Afterwards Trickbot activities continued to rise, as you can see in various press reports. [3] [4] [5].

If you work on Trickbot, especially extracting Trickbot configs, you probably haven’t missed that something has changed in the last weeks. I recently downloaded some newer samples from Malware Bazaar and was wondering, why my config extraction did not work. So I started debugging my code and fixed it but something was strange.

Let’s take 6ca141e8ed2443113c9e497d231b93cf41d86b224993c48f589b375a830cd27c for example.

The extracted config looks like this:

        <module name="pwgrab"/>

Normally, the port number looks different and there are usually much more C2’s inside the config. When I looked into a sandbox report, I could also see a C2 IP which is not included in the config.

I searched for existing blog posts or tweets about that and finally stumbled across a tweet from hatching and I knew, I have some work to do.

As usual, the Trickbot config blob is XOR and AES encrypted so we have to find new functions which are executed after the config decryption and ideally taking the config decryption output as an argument. If you are using BinDiff, you should be able to spot it quite fast, just watch out for this beauty:

I reimplemented the function in python and it looks like its working fine.

# e.g.
def convert_to_real_ip(ip_str):

    result_octets = []
    octets = ip_str.split(".")
    o1 = int(octets[0])
    o2 = int(octets[2])
    o3 = int(octets[3])
    o4 = int(octets[1])
    x = ((~o1 & 0xFF) & 0xb8 | (o1 & 0x47)) ^ ((~o2 & 0xFF) & 0xb8 | (o2 & 0x47))
    o = (o3 & (~o2 & 0xFF)) | ((~o3 & 0xff) & o2)
    result_octets.append(str(((~o & 0xff) & o4) | (o & (~o4 & 0xff))))
    result_octets.append(str(((~o2 & 0xFF) & o4) | ((~o4 & 0xff) & o2)))

    return ".".join(result_octets) + ":443"

fake_ips = ["", "", "", "", ""]

for item in fake_ips:

The output and thus the correct C2 IPs look as follows:

I hardcoded port 443 into my function because I could also see it hardcoded in the Trickbot code but there might be other ports in the future as well. So far I only found the group tags rob3 and tar2 with identical configs using those fake IPs.

If any of you have more samples using fake C2 IPs with other group tags or other configs, I would appreciate a hint.




77b7bbf78f7a14d808b61a23ea7b29c2bc2e3d8faf62bccf3459182730ea42e3 (siehe
7b2b661233d8af2e13cbf8962ad1b409a6494acd806f3d8d43f98eb3ae1fedc9 (siehe
5369104b8dca5c077c88af645cbb567e4406a6e1f6b4600faadc14e04211c334 (siehe