So you may have heard that the FBI have linked three strains of malware to a North Korean cybercrime group known as Lazarus (or HIDDEN COBRA, take your pick). The first strain is a Dropper (which is what I will be analyzing in this post) that contains two DLL’s (these are the other two strains): a fully functional Remote Access Tool (RAT) and a Worm that spreads both utilizing the SMB vulnerability that WannaCry took advantage of and attempting to brute force SMB logins. Whilst these strains started to appear in 2009, meaning I am very late to the party, it isn’t my fault that the FBI didn’t figure this out earlier. As usual, you can download all three files on VirusBay, and if you’re here for the capabilities and overview of the file, just skip to the end. Anyhow, let the analysis commence.
As this isn’t just a Powershell script, I decided to go full on with the static analysis, in hopes that my static analysis skills with IDA would improve. As usual, I opened it up in PEStudio, which is extremely useful for static analysis as it gives you a great overview of the executable itself. I stopped feeling bad for myself about being late again when I realized that most of the files on VT are less than a day old. Except for that Babable one, which I can safely say that I have never heard of it.
Anyway, moving on. I checked out the Imports menu and noticed GetProcAddress and LoadLibrary, so this sample is most likely going to dynamically import some functions from somewhere, we just have to figure out what functions and what DLL they are stored in.
What interested me most was the resources section, as I could see (unknown), and as this is a dropper, there is a high chance that the DLL’s are stored in the resources. Sure enough, three resources occupy the section; MAIN, 101 and 104. Resource 101 and 104 are both larger than 50,000 bytes, so I think they might be useful for us. Also, the entropy is quite high on the final two resources, so there is a large chance that they are encrypted or obfuscated somehow.
After dumping the files to the Desktop, I opened them up to see what was inside. As you can probably see, the first one – MAIN – is not very interesting at all, although it could be important at some point.
The second one however, are a lot more interesting and have definitely been encrypted with some algorithm. And whilst the third resource looks like an extremely complex conversation, it is in fact also encrypted. So the question is, what is it encrypted with exactly?
I also decided to extract the third resource and compare it to one of the DLL’s that is dropped by this sample. Is it a coincidence that they are the exact same size? Possibly, but I very much doubt it.
Right, enough of the executable analysis, time to open it up in IDA Pro (Free – yes, you too can analyse malware for free) and see what is happening. As I already know, this particular sample interacts with its resources and drops them to disk, and so I first want to find the location at which the interaction begins. You can do this by searching the “Names” menu for the string “FindResourceA“. According to MSDN, FindResource() “determines the location of a resource with the specified type and name in the specified module“, so finding this will help to further the analysis. Sure enough, FindResourceA exists in the file, so I performed a X-Ref (Cross Reference – Just hit “x” on a certain string and IDA will search the file for other mentions of that string), and managed to locate the useful section.
Now that I have found where the malware is messing with its resources, I need to examine what occurs before it so that I can get a clearer picture. So after scrolling up for a bit, I finally managed to locate sub_401560, which seemed to be the main function in this sample. Whilst examining the function, I noticed calls to GetSystemDirectory and CreateDirectoryA, and upon further analysis, I managed to locate 3 hardcoded paths. I mean I would expect nation state backed groups to randomize file names in order to increase the stealth of the malware on the system, but I guess that makes the analysis easier. The hardcoded paths are:
"C:\\Windows\\system32\\mssscardprv.ax" "C:\\Windows\\system32\\Wmmvsvc.dll" "C:\\Windows\\system32\\scardprv.dll"
Once I had noted those paths down, it was time to descend down the rabbit hole that was sub_401560. After the hardcoded paths are resolved, the program calls OpenSCManagerA, which allows interaction with Windows Service. If that fails, it exits. Otherwise, it calls OpenServiceA on several strings such as Rpcss and Wmmvscv, possibly to check if the malware had already been installed on that system. If the program is able to retrieve a handle to the services that it attempted to open, it proceeds to delete it, so that it can re-root itself in the system.
Eventually, I found exactly what I was looking for; File interaction. If the Dropper is meant to drop a file to disk after decrypting it, how else will it do that without a call to CreateFile, or any other File I/O calls? As seen in the image, a similar routine to the service enumeration is called, where the program deletes the hardcoded file from the system, and then creates a new file. (40000000h == GENERIC_WRITE)
What fascinated me about loc_4017BE (The location to jump to if the file is created successfully) was that IDA automatically commented on one of the registers pushed to the stack, so it read NumberOfBytesWritten, int and hFile, which is normal for a WriteFile call – but there was no call to WriteFile. This means that there must be a call to another function after the variables are pushed to the stack, but before the file handle is closed. Introducing sub_401240. This is an extremely important function, as it must contain the decryption routine, because what is the point in writing out an encrypted file to disk and then decrypting it when you can just decrypt it before writing.
The first call in sub_401240 is a call to sub_401000. This is where the magic happens. Upon entering this function, you’ll notice the sub esp, 100h. 100h in hexidecimal is 256 in decimal. This is creating 256 bytes of space, which is a useful number to look for (or 100h) if you are trying to figure out a certain encryption method that is used in malware.
Just underneath the section that creates 256 bytes of space, there is a loop that occurs. You’ll also notice that 100h appears here too, and is compared with the value of EAX. Each time the loop goes round, EAX is incremented by 1, with the value being stored in [esp+eax+110h+var_100]. This is what’s known as initializing the Substitution Box. To put simply, a mix of numbers, letters and symbols are all put into an array, with the size of that array being 256 bytes. This array acts as a lookup table, similar to Base64, except in Hexadecimal. It starts of with 00 and loops until it reaches 100h.
After the S_Box has been initialized (filled up), the next section begins.
This is another loop, and whilst there are more operations, it still involves 256. Instead of filling 256 bytes with values, it takes the already initialized S_Box and scrambles it using a pre-assigned key. You can tell if the function is scrambling the S_Box by observing it in a debugger and looking at the process’s current memory. If it is scrambling the box, you’ll see it as it iterates 256 times. As this function requires a key in order to scramble the box, it will be hard coded into the binary, but most likely encrypted until it is needed. If you haven’t guessed, the encryption method used here is the stream cipher, Rivest Cipher 4, AKA RC4. In this case, the key is located in byte_408030, so after performing static analysis, we are able to extract it using a debugger.
Finally, once the S_Box has been scrambled, the decryption routine begins, which loops through the encrypted text and decrypts it, using the scrambled S_Box to create a keystream and XOR the encoded data with, in chunks. It does this until the text is fully decrypted, and then it returns.
Right, that’s enough static analysis for now, let’s crack this thing open in a debugger.
So now it is open in x32dbg, I need to locate the function responsible for altering the resources. Looking at the strings tab, I found “RT_RCDATA“. This is what was stored in the Type offset that was passed to FindResourceA. That wasn’t so difficult.
Once I navigated to the location of “RT_RCDATA“, I then followed the program flow up, until I located GetWindowsDirectory and GetSystemDirectory. I then put a breakpoint on the operation that appears at the start of the function, located at 00401560. This is the important function that leads to WriteFile – Now that I had found it, it was time to run the debugger until I hit the breakpoint. Once it was hit, I jumped over functions to get an overview of what occurred up until the main WriteFile. However, the program seemed to exit after calling OpenSCManagerA. Before realizing why, I spent a while scouring the file for Anti-VM/Anti-Debug measures, finding nothing. Turns out, this particular sample needs to be run with Admin Privileges, otherwise it exits after failing to open the service manager. I definitely did not feel idiotic at all when I realized this.
Once I had restarted the file with Admin privileges, I was able to jump over functions until I reached the WriteToFile function. Entering the function, and opening it up in Graph mode, you can clearly see the loop that occurs. First, 1400 bytes are read from the resources (the DLL’s). These bytes are then passed onto the RC4_Decrypt routine, which decrypts the bytes in memory. The decrypted bytes are then passed to WriteFile, which as the name implies, writes the 1400 bytes to the files. This loops until there are no more bytes to decrypt, and then the function returns.
Entering the RC4_Decrypt routine, we can easily label functions, as it is almost exact to what IDA displayed. This time, however, we are able to extract the key that is used to scramble the S_Box, as the key is stored at [edx+408030]. Once we start going through the Scramble_S_Box function, x32dbg is able to resolve the memory address to a string. The incredibly complex key that was chosen to decrypt the files is… cdefghijkl. Surely this couldn’t be correct. Upon running one of the dump files through an RC4 Decryption algorithm, using the key cdefghijkl, it provided an almost exact match, however it seems that the RC4 algorithm that was in the sample was custom to an extent, as the MD5 Sum of the DLL did not match the decrypted dump file.
Now that the first DLL has been written out to the file on disk, the same routine occurs for the second file. First the program gets a handle to the resource that contains the DLL, and then loads it into memory. The program then decrypts the file using custom RC4, with the key cdefghijkl. The decrypted resource is then written to another file on disk.
The locations of the dropped DLL’s are:
Once the files have been written to the disk, it returns from the routine and starts to root the dropped DLL’s by adding persistence methods. This is accomplished through 2 different methods. The first method is altering registry keys, specifically keys at SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost
and SYSTEM\\CurrentControlSet\\Services\\Wmmvsvc. The value stored in CurrentVersion\\Svchost is the path to scardprv.dll, and the value stored in Services\\Wmmvsvc is the path to Wmmvsvc.dll.
After finishing up altering the registry, the program then opens the service manager once again, this time to create 2 new services; SCardPrv and WmmvSvc, both of which are set to Auto Start. The command that is allocated to the services are C:\Windows\system32\svchost.exe -k Service, where Service is the name of the Services. As it is running under svchost.exe, it is difficult to notice scardprv.dll is running, unless you view the command line argument. The description for these services look legitimate;
Wmmvsvc: Windows Media Management Driver Extensions SCardPrv: Manages and controls access to a smart card inserted into a smart card reader
When the services have been created and setup, the dropper then executes the services using StartServiceA. Once they have begun, the program’s work is done, and so it starts to exit. All handles are closed, EndDialog and PostQuitMessage are both called, and then the process exits, leaving the running services to continue the flow.
Now that was only the dropper, so I will be attempting to analyse the two DLL’s that dropped, to figure out how they work, so make sure to follow me on Twitter (@0verfl0w_) to see when I next post. As always, if I have missed anything feel free to comment or DM me – I’m still learning 🙂
*** Summary of Execution ***
- Program is executed on a system, with Admin privileges
- Gathers System Information – Windows Directory, System Directory
- Uses custom _strncpy() to form full paths of files
- Checks to see if two services are present on the system
- If they are found, they are deleted and the execution continues
- The program loads one of the resources stored in RT_RCDATA
- DeleteFile is called so that any existing files are removed
- scardprv.dll is created in the System32 directory
- The program then decrypts the RC4 encrypted resource in memory
- Chunks of 1400 bytes
- The key is cdefghijkl
- This decrypted data is then written to the created file
- The next resource in RT_RCDATA is loaded, and the same routine occurs
- Decrypt RC4
- Now the files have been dropped to disk, persistence methods are used
- Registry keys are altered
- Two services are created that auto start:
- The services are then executed by the program
- Exit routine is called
- Program terminated
*** Summary of Execution ***
- Dropper (MD5) : 4731cbaee7aca37b596e38690160a749
- Dropped SMB Worm (MD5) : e86c2f4fc88918246bf697b6a404c3ea
- Dropped RAT (MD5) : 4613f51087f01715bf9132c704aea2c2