Reverse engineering malware: TrickBot (part 3 - core)

In my previous post, I explained how to dump the TrickBot core.

In this one, I will show a bunch of tricks that will make the analysis of said core easier. This is not a full malware analysis - I don’t intend to teach you malware reverse engineering, but rather, I’m aiming to make your reverse-engineering process less cumbersome and of higher quality.

Starting analysis: automagically renaming imports

We can see that the first thing the binary does is dynamically load a bunch of imports (not all, though):

loading imports

Given the knowledge gained from the previous posts of the TrickBot series, the next step is obvious: run the binary, load the imports, rename them, then have them nicely named in the IDB:


However, even after renaming them, the pseudocode is ugly:

stupid pseudocode

IDA knows about this, too. Just select the entire table and right click, then select Create struct from selection:

fix imports

(IDA seems to not like imports_table as a struct name)

Now, set the variable’s type to a pointer to whatever you named the previous structure (I chose import_table):

fixed imports, really

Much better now! There are more imports loaded dynamically a bit further:

even more imports

But that can be fixed in no time using the classical method:

yay for imports

Deep into the trick: Task Scheduler and COM

TrickBot makes use of the Windows COM API to register itself as a task in the Task Scheduler. The problem with that, however, is that the COM API is C++, and is not exactly pretty in source, let alone binary:

damn trickbot

Luckily, there’s no need no reverse that indirection hell manually; it might sound like a nag at this point, but IDA already knows about this, too. It’s fairly easy as well. If you check the first parameter of the first indirect call, and trace it back to where it is initialized, you’ll see a call to CoCreateInstance:


As the name suggests, that function is creating an instance. If there’s an instance, there must be a class. If you look at the documentation, you’ll see that the fourth argument is the riid, i.e. a reference to the identifier of the interface (basically, the descriptor of the class we’re after). And the value passed in this case is:

.rdata:004131EC stru_4131EC dd 2FABA4C7h                            ; Data1
.rdata:004131EC                                         ; DATA XREF: sub_401B60+55↑o
.rdata:004131EC dw 4DA9h                                ; Data2
.rdata:004131EC dw 4013h                                ; Data3
.rdata:004131EC db 96h, 97h, 20h, 0CCh, 3Fh, 0D4h, 0Fh, 85h; Data4

(type: CLSID, available in the mssdk_win7 type library)

To find out the name for this class, open the registry editor and go to HKEY_CLASSES_ROOT\Interface, and search for the first few bytes of the CLSID, {2FABA:

registry path

The value at the right will be the class name you’re looking for:


Now go back to IDA, and apply the type:

wrong type

Oops. That’s not it. That’s because the pointer is actually pointing to the vtable, not to the class layout with the function pointers. But, yet again, IDA knows about that, too! Simply change the type from ITaskService* to ITaskServiceVtbl*, and:


Keep doing that until you get a decently readable pseudocode, which can be easily understood at a simple glance:

v4 = (*a1->task_service)->GetFolder((ITaskService *)a1->task_service, v3, &task_folder);

That’s it, for now. I haven’t found anything else worthy of surgically dissecting in a blog post, because the rest of the bot is just your average boring reversing, and I’m not gonna waste your time with that. However, if there’s interest, I can write another post, dissecting how the malware performs the MitB (Man-in-the-Browser) attack, or any of the modules it downloads.

If you want to leave a comment, please do so on the reddit discussion.