MalwareTech

Let’s Unpack: Dridex Loader

A few people have been having problems with unpacking the initial loader for Dridex (the one dropped by the macro), so I’m going to show you an easy way to do it. One of the other problems people have, which i can’t fix, is the fact the Dridex infection chains have a very short lifetime which makes it near impossible for most people to reverse, I’ll explain why.

The current Dridex infection chain has about 4 stages:

An office document containing a macro which run a powershell script.

The powershell script which will fetch the packed loader from a hacked site or sharepoint and run it.

The packed loader which will unpack itself and inject code into a newly created spoolsrv or svchost process.

The injected process which will contact a loader server and fetch and execute the real bot binary.

The problem for analysts is there are 2 points of failure here: the hacked site hosting the loader can be cleaned or sharepoint account deleted, or the loader server gets suspended (either of these will prevent successful infection). Furthermore, the loader servers are often geofenced (only work if your IP resides in the country targeted and isn’t a VPN) and once a loader is uploaded publicly the Dridex group have the ability to blacklist it, permanently banning anyone who runs that loader from contacting any C2s.

What’s fascinating about all these “failures” is that they are likely intentional. Most victims who get an infected email will open it within a few business days, after that the majority of the people opening the emails are going to be doing IR or malware analysis, so it’s beneficial for things to die after a week.

So that people can follow along with this tutorial, here is a zip containing the malicious office doc and packed loader from the same chain so no need to worry about dead urls (password: infected). As for the geofenced loader servers, I can’t do anything about that and because the loader is already revoked you WILL get blacklisted for running it (unless you know how to bypass the blacklist, follow this tutorial in a newly installed VM and possibly change IP afterwards).

Retrieving the Packed Loader

First things first you’re going to want open the malicious document in Word, but don’t click “Enable Content” just yet. Open a debugger (as usual I’ll use WinDbg), attach it to winword.exe, set a breakpoint on CreateProcessW, resume the process, then click “Enable Content”.

The breakpoint will be hit nearly instantly with newer Dridex samples (some VMs may get detected, so if the breakpoint isn’t hit look into masking your VM).

We want to dump the 1st and 2nd parameter of CreateProcess (application path & command line parameters respectively), we can do this with the following commands:

What’s happening here is the malicious macro is running cmd.exe with a command to run powershell, bypass the execution policy, then download and run an executable. If we remove the string concatenation and carats which are just baisc obfuscation, we get the following:

We can now just manually fetch the exe from littlwnowern[.]top/lukaku/ (url is dead now but I’ve uploaded the binary in the archive as “GksagD.exe.sample”), this is the packed loader.

Unpacking The Loader

TO start with we need to enable DEP (Data Execution Prevention) for all applications, the reason for this will become clear later. To do so go to Control Panel > System And Security > System > Advanced System Settings > Settings (the one under Performance) -> Data Execution Prevention, then turn on DEP for all programs.

Next we’re going to open the exe in PE Explorer, and set the “Relocation Stripped” flag in the PE header, which will prevent ASLR from loading the executable at a different address every time we run it, making for easier reversing.

Now save the exe and open in in IDA Pro.

Typically a Dridex loaders will create an svchost.exe or spoolsv.exe process and inject into it, so we know the unpacked code will probably call CreateProcess; To verify this, set a breakpoint at the end of CreateProcessW (on the ret instruction) and hit run.

Once the breakpoint is hit, you should see that GksagD.exe has created a suspended process named svchost.exe or spoolsv.exe as expected. If we single step to return from CreateProcessW back to whatever code called it, we’re met with the following.

IDA has fragmented the instructions which means the code has been changed since the executable started, which is usually the result of an unpack-in-place (often malware packers will use process hollowing to write the unpacked code into another process, true packers will unpack the code into the same process).

Now we know that the main executable code is replaced at some point, we can put a write breakpoint on the current address, which will be triggered when the code is modified.

Once done, remove all other breakpoints and restart the process.

The breakpoint was triggered from an address outside of the main executable section, which means the packer allocated some memory then copied some code to take care of replacing the main executable.

If we take a look at the memory in Process Hacker we can see that it’s now readable and writable, but not executable, which is great because it means the packer is now no longer using any of that code.

Now for some Sherlock level deductions: we know that code is executed here later and the memory is not currently executable, so it’s probably going to be made executable at some point.

The function used for adjusting memory protection is usually VirtualAlloc, VirtualAllocEx, or NtProtectVirtualMemory. If you’re familiar with Windows internals, you will know that both VirtualAlloc and VirtualAllocEx will call NtProtectVirtualMemory internally, so that’s where we will put a breakpoint.

We could sit and inspect the call stack every time NtProtectVirtualMemory is called, wait for the address in question to be set to executable then parse the PE header to find the new entry point, or we could be smart.

What we’re going to do is set a conditional breakpoint on NtProtectVirtualMemory with the following script:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

if(Dword(esp+0x10)==0x20||

Dword(esp+0x10)==0x40||

Dword(esp+0x10)==0x10)

{

if(Dword(esp+4)==0xFFFFFFFF)

{

if(Dword(Dword(esp+8))>=0x400000&&

Dword(Dword(esp+8))<0x42e000)

{

PatchDword(esp+0x10,0x04);

}

}

}

return0;

To do this, go to NtProtectVirtualMemory and set a breakpoint on the first byte, right click > Edit Breakpoint, then click the “…” button and paste the script.

This script will be run every time NtProtectVirtualMemory is called, and will do the following:

Verify the page protection parameter (esp+0x10) is 0x10, 0x20 or 0x40 (aka PAGE_EXECUTE, PAGE_EXECUTRE_READ, PAGE_EXECUTE_READWRITE), which means the call is changing the page protection to executable.

Verify the target address is within the main executable section’s range (0x400000 – 0x42e000).

Change the protection parameter to 0x04 (non executable).

Return 0 (resume execution instead of breaking to the debugger).

Let’s hit run and see what happens.

An access violation exception! Take some time to enjoy the moment as this is probably the only good access violation error you’ll ever see….but why exactly is it good?

Our breakpoint script on NtProtectVirtualMemory set all the memory to non executable when the packer tried to set it to executable. The exception means that whatever the packer was writing to the memory has now been successfully written and it’s trying to call something in that memory. If we’re lucky the thing that the packer was writing to the memory is the unpacked loader and the address it was trying to call is the entry point, shall we see?

For this we’ll use an amazing tool called processdump (download link), what the tool does is dumps any exe or dll images loaded into the processes memory and packs them back into .exe or .dll files.

use “pd32.exe -pid <process id>” to dump the process.

The number at the end of the file name is the base address of the image in memory so GksagD_exe_GksagD.exe_400000.exe will be whatever the packer mapped in the place of the old executable, so we will take a look at that in IDA.

The address of the entry point matches the address of the exception, it’s the unpacked executable!

Tips for Reversing

The loader is tricky because all strings are encrypted and there’s no imports, but the methods I detailed in my Dridex reversing tutorials will work on the loader too.

Note: the loader executable is multipurpose (it’s both the code which injects svchost / spoolsv and the code injected into svchost / spoolsv). If you want to reverse the injection part of the loader just open it in IDA and run, If you want to reverse the loader part you’ll need to copy it to system32 and run from there (beware that on both occasions the loader will delete itself after its finished).