Unpacking Malware: Dridex
Dridex is a malware which has long been targeting the financial sector in attempts to steal user credentials and compromise individuals. It targets individuals by sending phishing emails with Microsoft Office-based attachments embedding malicious macros which download additional payload and attain the authors' objectives. Since the first-stage malware is typically packed by Dridex, we’ll uncover how to unpack it and continue with analysis of subsequent stages.
Acquiring the Malware Sample
Here’s the hash of the malware sample we’ll be using for the unpacking:
Type | Hash |
---|---|
MD5 | 6a8401448a5bd2b540850f811b20a66d |
SHA1 | 9f01d4442c495c7128649b98201187bc0c58dedd |
SHA256 | 178ba564b39bd07577e974a9b677dfd86ffa1f1d0299dfd958eb883c5ef6c3e1 |
You can acquire the malware sample from MalwareBazaar.
Unpacking Dridex
Let’s jump into the section where we discuss the packing of the Dridex malware.
Indicators of Packing
Loading the executable into PEStudio, we can see several indicators which point toward a packed executable:
- Lack of API imports
- Size of code is zero
- Presence of the non-standard
.text1
section
Unpacking via Dynamic Analysis (x32Dbg)
To get started, load the binary into x32Dbg (we can also use OllyDbg for our analysis). We’ll be setting up a few breakpoints on critical Windows API calls which are typically used by packed malware to load the unpacked malware into memory. The calls include:
- VirtualAlloc
- Used to allocate memory in the calling processes' virtual address space
- Typically used to allocate chunks of memory where the unpacked executable is stored
- VirtualProtect
- Used to change the protections on pages (memory segments) within the calling processes' virtual address space
You can use the Command
input at the bottom of the screen to use the bp
command and set up the desired breakpoints. Here’s an example:
bp VirtualAlloc
bp VirtualProtect
Let’s kick it off. First, let’s move into user-code so we’re not dwelling in libraries.
Now EIP should be at the EntryPoint
of the executable. I’ll simply be executing until our desired breakpoints are hit [F9]. The VirtualAlloc
call isn’t of prime importance to us. It’s the address it returns in EAX which points to the recently allocated memory. Let’s execute to return and see what address is returned in EAX. It’s0x490000
. Let’s follow it in the first dump.
Now, let’s continue and see if any data is written to this address. Run again and we hit another VirtualAlloc
call. Interesting. Let’s execute to return (CTRL+F9) again and see what address is stored in EAX. Let’s follow the address, 0x5A0000
in dump two.
Press Run
again and a VirtualAlloc
call is hit again. But notice the addresses you previously followed in dumps. They’re not updated with some data. Take a closer look and you’ll see it’s has the MZ
header at the start indicating it might be the unpacked PE. But why is it allocating three separate segments of memory? If you go back to dump one (with the address, 0x490000
) and scroll down a bit, you’ll see the DOS message (but no MZ header indicating it might be copying data from this segment to the segment in dump two but that’s just one guess since we aren’t properly looking at what it does with the data just yet).
For the third VirtualAlloc call, let’s go to its return and check the address at EAX again. It’s 0x5B0000
. Let’s follow this in dump three. Run again and a VirtualProtect
call is hit and there’s another MZ header (followed by more data) loaded in dump three. Well, this is a different PE since there’s clearly a difference in terms of data after the PE header. So, what is this binary actually doing? Are there multiple decoys?
Let’s go to the return of the VirtualProtect
call now and step out of it by pressing F8 (step over). Since all allocation is done, the VirtualProtect
calls are likely just to change the permissions/protections on the pages and make the code executable. We’re interested in dumping the mapped PE out. To do so, let’s see if the addresses we’ve been following are called or jumped to for execution. These are typically jmp
or call
instructions with the address being pointed to by the eax
register. You can breakpoint on these instructions in advance and dump the PE out from the address since this is the point where the binary is now actually going to execute the PE without playing around with any other decoy binary.
Run past all other breakpoints and stop at the jmp eax
breakpoint. Step into the jmp
instruction and you’ll see this is where the execution of the unpacked executable begins.
We’ve now seen the segment at which the mapped executable begins its execution - 10000000
. You can either dump out the mapped binary from the Memory Map using x32Dbg or use a tool like ProcessHacker to do so. I’ll be using Process Hacker to dump the memory. Open up the tool, double click the process (running under x32Dbg), and dump out the entire PE from the address.
Since this is still a memory-mapped executable, we’ll need to cleanse some bits before it’s usable. Open it up in PE-BEAR and let’s realign the sections. Let’s first fix the section headers such that each section’s raw and virtual sizes are the same. Then, fix the raw sizes such that the size of the first section is equal to the raw address of the second section minus the first one. For the last section, you can fill it up such that the map on the bottom shows perfectly mapped sections on the raw end (usually, you do so by trial-and-error of increasing raw size values. As soon as the red section fills up, you’ve done your bit). For us, it’s C000
.
Now that it’s done, you can see the imports, exports, and executable information which was previously not available to us. One final thing - if you’re to continue your analysis in a static analysis tool like IDA, you’d have to fix the image base address of the executable. Let’s just change it in the Optional Headers from the default of 400000
to 10000000
.
That’s it. You’ve got the unpacked executable all ready for further analysis!