Talking to dridex (part 0) - inside dropper
---
Dridex represents one of the most interesting malware
family one can find in the wild. It was descried in various
places before, it even earns a decoder in hybrid-analysis.
Shortly after that authors change how it is stored ;]
I read few publication about didex, but when i sat down and started
writing code communicating with bots, it turns out authors changed
few important pieces,
So i roll my slaves up and sat down to IDA, this series
will decument every painfull step i had to make to finally
be able to talk with dridex
Intro.
---
Dridex mostly come to us as spam contains .doc with few macros,
responsible for downloading dropper, one can quickly analyze it
using oledump.py and starring for some time in vbscript, or just
run it in sandbox and got dropped files;]
After unpacking boring packer, lets get into juicy parts.
We are presented with small stage1 dropper, written by someone who
either just learn how to write object-oriented code or is still learning.
Purpose of dropper is to download main binary from C&C and inject it
to explorer,plus some boring initialization stuff.
CFG extraction.
---
First lets take a look how to find C&C addresses.
In older samples there was PE section called .sdata and it contains
xored xml-document with all of interesting data,
85.25.238.9:8843
91.142.221.195:5445
46.37.1.88:473
About week ago it changed, no more .sdata :( - data sits in plain sight
somewhere in memory structured as follow
struct cfg_t
{
int field_0;
unsigned __int16 botnet;
unsigned __int8 count;
char unknown;
ip_addr cnc[count];
};
struct ip_addr
{
char ipaddr[4];
__int16 port;
};
using yara signature like this:
$new_get_cnc = { E8 [4] BE [4] 8D ?? 5B 83 C4 1C 0F [3] 08 0F [3] 09 0F [3] 0A 0F [3] 0B 0F [3] 0C }
we can easily locate address where it is used and pull those data
Ok, now we have to find a code that calls those addresses.
after going back-and-froward with references we stumble across
function presented at [0]
Here is a little digression, if you don't know it already dridex
uses encoded strings and run-time api resolving to make our life harder.
Fortunately nothing fancy, simple xor
https://gist.github.com/mak/dccb5f579a3d1e0b0180#file-dridex_decode-py
Back to businesses, despite whats in every report first communication is not
encrypted with xor but with RC4, keys are stored somewhere in binary
encoded as any other string, they are different per botnet but otherwise
don't seems to change that often, for botnet 220 key is:
ub9sKhcvsePZXuFC4HRw8KjFSIVUxsdAJXFyVP3Acl7HYL9KQBzETBzFvk2FlxeHZFBljIPps21W
armed with cnc addresses and key, we can create a message,
Dridex authors were kind enough not to use any fancy binary format,
just plain xml (sometimes gziped but we got to that part later...)
message looks something like this:
where `unique` is a bot name, created as shown in [1],
`botnet` is a 2 bytes value hidden in confing, name corresponds to request we'd
like to do.
Most basic requests is `list` which obtains list of nodes.
After decrypting response, using RC4 with the same key, we got something like this,
Apts4+yozUR8Nbcan9dOya6yFIq6mxfdnJjlydF+uAELwWrIEIcvQIkk1mPURXr25/IwtnDW9l4s36C10iL0O6H3sJ1xhnUvcLN7ccjZU+RNySaj6YYSALvTBcGfNreUusy1ESLHKscAq4LJqzNy3UoB6fHLyJkULKhVFpKnogyKQEt4lctDeIpAS3iKQwb3205JWYYEZMwTJQEzS9B29XQK6aa1VsPxFd31tsa7IPRFldSbdDgUVQmVq35rDX5nJNAfOYttztqNC8etW0oDIxrkEzMJedOrGIIvAnMUtdjDeIouPdceNNhiLzkGY3q6gQoV8pwkCQsSrwltmFOmbyW9l6Vx+XWBiD8wOROQS3iK
base64-encoded string is copied without decoding and dealed with in next stage.
next command is `bot` and is responsible for downloading main dll
base64-string
There is no philosophy, base64-encoded string is being decoded
and loaded into memory, what is interesting is how it is done.
It's normal in malware world to apply extra layer of protection to
files stored in local system, for example Tinba is additionally xoring
it's configuration file with bot id.
But non-writen rule of how malware works, is that every code is passed
through memory in clear text, as one can guessed this not a case;]
Indeed, dridex'es method of injecting into another process is quite nice[2].
It consists of two stub loaders, first responsible of decoding real payload,
(again just xor) second is used as a simple pe-loader which make possible
to run PE files, without syscalls like LoadLibrary or CreateProcess.
This is clearly visiable in any memory tracer,
[37ceca4ac82d0ade9bac811217590ecd.bin - 3980][3952]called[pre] NtOpenProcess(1212) = 1276 - C:\WINDOWS\Explorer.EXE
...
[37ceca4ac82d0ade9bac811217590ecd.bin - 3980][3952]called[pre] NtWriteVirtualMemory(Explorer.EXE,1fe0000,459264) src: 932e90
...
[37ceca4ac82d0ade9bac811217590ecd.bin - 3980][3952]called[pre] NtWriteVirtualMemory(Explorer.EXE,b20000,2552) src: 12f348
...
[37ceca4ac82d0ade9bac811217590ecd.bin - 3980][3952]called[pre] NtWriteVirtualMemory(Explorer.EXE,b209f8,2460) sr c: 415020
...
[37ceca4ac82d0ade9bac811217590ecd.bin - 3980][3952]called[post] NtAllocateVirtualMemoryx(SELF,1900000,12288,MEM_COMMIT|MEM_RESERVE, RWX --- )
[37ceca4ac82d0ade9bac811217590ecd.bin - 3980][3952]called[post] NtAllocateVirtualMemoryx(SELF,1910000,65536,MEM_COMMIT, RW- --- )
Whats important with further analysis is that it relays quite heavy on
loader metadata, which is somehow model to resemble legit PE,
which is obviously not since it missed almost every part of it beside
typical MZ-PE signature.
0000000: 4d5a 0000 0000 0000 0000 0000 0000 0000 MZ..............
0000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000030: 0000 0000 0000 0000 0000 0000 4000 0000 ............@...
0000040: 5045 0000 0000 0000 0000 0000 0000 0000 PE..............
0000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
Main dll is obviusly packed, but i left to the reader as a homework,
since this is the end of introduction - cya in next part,
mak
sample used,
37ceca4ac82d0ade9bac811217590ecd
[0] http://www.cert.pl/wp-content/uploads/dridgetcnc.png
[1] http://www.cert.pl/wp-content/uploads/driduniqe.png
[2] http://www.cert.pl/wp-content/uploads/dridprepl.png