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):
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:
IDA knows about this, too. Just select the entire table and right click, then select
Create struct from selection:
(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
Much better now! There are more imports loaded dynamically a bit further:
But that can be fixed in no time using the classical method:
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:
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
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
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,
The value at the right will be the class name you’re looking for:
Now go back to IDA, and apply the 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
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.