Hello, today we are going to take a look at the quick analysis of infamous Dridex banking trojan, which stole over 40 million dollars in 2015. Over the years authors of Dridex have modified its structure, code base in hopes of improving its capabilities. Which is why samples you may find might differ from another. Below is the hash value of the sample that i analyzed.

SHA256: e30b76f9454a5fd3d11b5792ff93e56c52bf5dfba6ab375c3b96e17af562f5fc

Note: I am no expert malware analyst. This writeup simply shows what methods i used to analyze this sample. Obviously different tools and techniques could be used.

So without further ado lets get started. First to get a brief overview of what this program actually does we open it with Process Hacker. In Process Hacker we see that the program creates its child process and kills itself after 1 second.

birth

rebirth

destruct

And we see some network activity in Wireshark as well.

wiresharkcapt

This technique is called Process Hallowing(one of my favorites..shhh) AKA RunPE. The purpose of this approach is to unpack the packed version of malicious payload that the malware stores in itself and inject it to another process’ memory. By doing this, malware limits the risk of getting caught by not writing any malicious file to the disk. All of this activity takes places in memory. This could be done in two major different ways. One of them is iterating through the processes currently active in memory find a suitable target, hallow out the contents of that process by calling NtUnmapViewOfSection(https://msdn.microsoft.com/en-us/library/windows/hardware/ff567119) and inject the payload in its memory. The other one is to create a child process and do the same thing to that child process.

Our sample uses the second technique.

If we open up the program in IDA Pro we see some errors saying translation of Virtual Address failed. This is a pretty good indicator of malware being packed. After taking a look at the IAT(Import Address Table) and seeing some weird characters we are now sure that the sample is packed.

ida_error

To confirm that the program is not packed with some third party software we open up the sample in ExeinfoPE.

notpacked

But how are we going to unpack this? Well recall that the malware created a process and wrote something in its memory. This could be achieved by Microsoft APIs CreateProcessA(https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx) and WriteProcessMemory(https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674(v=vs.85).aspx). So that means if we focus on those we might be able to figure something out. If we take a look the documentation of WriteProcessMemory it says that the API is used to write the contents of the specified buffer to the specified process. So that’s it. All we gotta do is to put a breakpoint on the call to the WriteProcessMemory and then analyze the buffer parameter.

write_buffer

write_buffer2

As we can see the buffer starts with the magic letters “MZ”, which means the content is an executable, which is exactly what we have been looking for. So after dumping the unpacked version we open that up in IDA Pro and take a look at the IAT. AAaaaaaannd…

iat

What the heck? where are the functions? is it possible for a program with no IAT to steal $40 million? No way. In this case malware uses a method to obfuscate the IAT and calls the functions in run time(It obfuscates strings too). In order to know which functions this malware used we need to know what those entries are. Okay so lets get started. After wandering around in IDA Pro a function catches our interest.

hint_for_decryptor

If we take a look at the Xref table to this function we see that there are a lot of calls to it.

xrefs_to_decryptor

Now, why a function needs to be called this frequently? I don’t know. Maybe it is some kind of a decoding or decrypting routine? Well today is our lucky day because that is exactly what it is.

decryptor

After peeking inside this function we see that it has 2 call commands one of them being our target function. Let’s double click the function sub_406C08 and see where it will take us.

decryptor_call

Hmmm that’s interesting. We see a function named sub_406C20 is being called but right before that there is an offset being pushed to the stack. What is that?

encryptedtext

Looks like senseless chunk of data. If we put a breakpoint on that call and execute it 5-6 times we begin to see the API names.

iointerconnect

iohttpsendrequest

At this point i thought “Ok this is the encrypted string that contains the name of the imported functions and this function decrypts these names”. If we analyze further details we begin to see the first 8 bytes of the encrypted string are being moved to the ebx and ebp registers and those registers are XORed with eax and edi registers. After the XOR operation ebx and ebp registers are being moved to somewhere in the stack.

decryption_route

If we follow those addresses we see the API names we have been searching for.

decryptedtext

Conclusion: This function iterates through the encrypted chunk of data 8 bytes at a time, XORes these values with the eax and edi registers to get the real API names. If we take a look at these registers we see that the values of them are 76 a8 28 e0 & e6 ac 0d e8 respectively.

ebx

So, now we now everything to decrypt the IAT ourselves. I wrote a python script. Why Python? Well, because it is easy. The script does the same thing the malware does to decrypt the imported function names. We could easily take a different approach. Like waiting until the malware decrypts all the functions names and then take a look at the strings in memory or write a IDAPython script that will execute the code and at each breakpoint retrieve the function name.

decrypter_script

The reason I wrote the key backwards is because the registers are in little endian format. After executing the script we get what we expected.

iat_strings

Now wee see what functions malware uses. Based on this we can set breakpoints on these functions and analyze the code. Earlier we saw that malware tries to reach out to an IP address which I suspect of being a C&C server. Lets analyze. Most of the time malware uses InternetOpen(https://msdn.microsoft.com/en-us/library/windows/desktop/aa385096(v=vs.85).aspx) and HttpSendRequest(https://msdn.microsoft.com/en-us/library/windows/desktop/aa384247(v=vs.85).aspx) APIs to communicate with the C&C server. After setting breakpoints on those calls we observe 4 different IP addresses that the malware tries to reach out.

firstipaddr

secndipaddr

thirdipaddr

finalipaddr

After this we saw a weird string in the stack.

weirdkey

I saw this a few times to know it is the encryption key but that’s not important right now. We will come back to it in a bit. At the breakpoint to HttpSendRequest call we will see that the message were designed to be sent to the C&C is senseless. Most of the time malware uses encryption to make sure no one intercepts the network traffic between the malware and the C&C server. This could be done with Microsoft Crypto API(https://msdn.microsoft.com/en-us/library/windows/desktop/aa380255(v=vs.85).aspx). Some of the functions are CryptCreateHash(https://msdn.microsoft.com/enus/library/windows/desktop/aa379908(v=vs.85).aspx), CryptHashData(https://msdn.microsoft.com/en-us/library/windows/desktop/aa380202(v=vs.85).aspx), CrytptEncrypt(https://msdn.microsoft.com/en-us/library/windows/desktop/aa379924(v=vs.85).aspx). If we set a breakpoint on the call to the CryptCreateHash we will see that the AlgID parameter holds the value 0x8003. This indicates that malware uses MD5 algorithm to hash the data. After the CryptCreateHash usually CryptHashData gets called which is the case in our sample. But before it calls CryptHashData it retrieves Computer Name, User Name & Install Date from the registry. Malware achieves this with RegQueryValue(https://msdn.microsoft.com/en-us/library/windows/desktop/ms724909(v=vs.85).aspx). It appends 4 null bytes to the buffer containing Computer Name, User Name & Install Date. We can see that in the memory.

cryptcreatehash

After that malware writes all the data it retrieved from the victim to the memory.

unencryptedrequest

We see a hash value and programs that are currently installed on the system. If we calculate the hash value of the malware retrieved from the registry(Computer Name+User Name+Install Date+4 0x0 bytes), we get the exact same value in the memory.

manualmd5sum

Then malware encrypts all of this data and sends it to the C&C server.

encrypted_request

But how it gets encrypted? Let’s find out. Majority of the malwares use RC4 encryption because of its simplicity and speed. In this case our sample does the same. But because it implements its own RC4 algorithm its really hard for us to find out the part of the program that does the encryption to retrieve the key. But if you remember we saw a weird string in the memory right after the call to the HttpSendRequest. So, I used that string as the key of the RC4 algorithm to decrypt the C&C data and I got this…

decrypted__rc4_request

This is the same data in the memory before it gets encrypted and sent to the C&C server. So the encryption algorithm is RC4 and the key is Yhc3XUIiv2rNzgy968TWCcx6PjBvLnuyT0ofNA9lvif8EIoZrLshPJ2kYi1WFXMDsuihGkT. Because RC4 is symmetric encryption algorithm it uses the same key for encryption and decryption. Which means the data that comes back from the C&C server will be decrypted with this key. Because of Dridex servers being offline I could not say what data will be sent back and i did not analyze the code to know what the malware does after receiving a command from C&C server :) Sorry :). Well we got this far, lets decrypt the strings as well to see what further tricks this malware uses.

string_decryptor_hint

We see a function gets called in the code. If we double click on that we see a familiar pattern.

strin_decrypto_call

This is the same pattern we saw in the IAT decryption routine. If we follow the offset in the memory we see junk data.

encryptedstrings

After diving into the function we see that the same algorithm used to decrypt the strings. Just because we saw this pattern I am not going to go into the details for this. Long story short, malware reads the encrypted text 8 bytes at a time and decrypts it using XOR algorithm.

same_pattern_string_decrypto

Only this time there are multiple XOR keys. First we get a set of 0xb0 0x65 0x30 0xfd & 0xf7 0xd6 0xf0 0x8b keys. But after a certain offset the keyset changes to 0xdd 0x57 0x86 0xa1 & 0x49 0x40 0x60 0xc4. The first keyset is used to decrypt the libraries used for getting the imported functions. The second keyset is used to decrypt the hardcoded shell commands. Again I used Python to decrypt those strings.

string_decryptor_script

After executing the script we get this output…

decrypted_strings_libraries

The one above is the libraries decrypted using the first keyset. and the nne below is the shell commands decrypted using the second keyset.

decrypted_strings_commands

Despite these shell commands being messy and kinda mashed up we can determine the logic of what the malware does. We see that sdbinst.exe is used with parameters /q /u “%S”. This means that the malware tried to delete an .sdb file. The .sdb files are the files that contain extra information about Windows Registry. After researching some of the commands we will find out that this technique is used to bypass UAC authentication. Which means Dridex can gain Administrative privileges even if it’s started by a normal user.

Note: I analyzed the code a bit more after this and i found out that there are a lot more calls to the string decryption routine. Which means there could be other encrypted strings and other set of XOR keys. But because after the second decryption malware sleeps for a long time and i did not want to wait for it. So, if you can decrypt more strings let me know.

Thanks for your attention :)