An in-depth look into a new piece of malware named MassLogger. We’ll look at what functions it has and how they’re achieved, while also describing its control flow and source code.
I am back with another malware analysis post. I apologise for the time in between posts, I have been busy working on my threat tracker (threatshare). This post took some time to put together, and I would like to say a huge shoutout to Casperinous for his time and effort helping me find the correct samples and aiding in the analysis of this piece of malware and a huge thank you to Steve Ragan (twitter) who edited and reviewed this post!
In the space of commercial malware we see a lot of names coming and going. One of the recent pieces of malware that has popped up is MassLogger. MassLogger has been created by an actor named NYANxCAT who is very active in the underground community. This actor has published a lot of malicious code under the guise of "educational" purposes to Github. But now this veil of education has fallen away, and NYANxCAT is selling their malware on some entry-level hacking forums. Here's the thread (link). Here are a few excerpts from their main thread.
We see the actor advertising plenty of functionality along with the programs MassLogger can steal from and how the malware will attempt to avoid various analysis methods.
There is also the inclusion of a classic TOS that the author thinks will cover themself if they get into trouble (it won't). Along with making sure that no one can get refunds or "trash" their "sales thread". The beginning price of MassLogger is $30 for 3 months of use along with the option of $50 for lifetime use. When MassLogger is purchased, the author will provide a builder for use. They have posted a promotional video which I have re-uploaded so as to not give the creator any potential advertisement.
Take notes of the options available in the builder, as I will be referencing how this functions, and how the malware determines what functionality it should use.
MassLogger is written in .NET, which uses managed code. I can reverse the sample with relative ease, and get a close to source code representation of the binary. But like any malware, the creator has used packers and other tools to try to obfuscate their code. So it helps that the creator is a big fan of sharing his code on sites like GitHub. To achieve some of the functionality in MassLogger, the creator has copied and pasted his code from GitHub and frankensteined it together to create MassLogger. Because of this, we can use the code he has publicly shared, to get an idea of what things looked like before compilation.
Thanks to Casperinous I was also able to get a sample of MassLogger that didn't have as much obfuscation as other samples. This sample is what I’ll be using for my analysis of the final MassLogger payload. Looking at the comparison, it was still somewhat obfuscated. Here is the before and after of the sample once de4dot was used on it.
de4dot before & after
Once I had used de4dot on the binary I then began to go through the sample and rename methods, functions, classes until the names painted a picture of what was going on within the sample. Let's take a look at the main function, we can see that the creator has used some techniques to make it harder to follow the control flow of the program. Here's what the first few lines of main looks like.
The sample makes use of goto statements to jump around the program making it harder to trace. The developer also creates wrappers for function calls so that you have to take one extra step to get to the desired function. There are other techniques used to make the reversal harder, but I will cover them later in this article. In the image above, you’ll notice that once we enter the for loop, the program will then call InitializeSettings. This function will decrypt the malware's configuration. The configuration is used to determine what functionality is used, along with other important information. Here is a list (link) of the functionality I have discovered.
MassLogger determines its functionality through an internal config that returns values according to the functionality selected in the building stage. Because the creator does not want you to be able to easily extract the config, he has used some methods to encrypt the config and then decrypt it during runtime. Looking at the config section in dnspy, we see that there are a lot of strings which appear to be base64 encoded.
Encrypted config strings
Here is a full list of all the config variable names (link). MassLogger initializes a bunch of empty strings that will then be populated by the config decrypt function.
Empty config strings
The decryption function which I have named InitializeSettings, looks like this. We can see that it initially gets the key and then uses it to create an AES object for decryption.
Here we can see an important function named AESGetString. This function is used to decrypt all config strings. After this function is used to decrypt the sample version another function named AESDecrypt is used. AESDecrypt is a wrapper to call AESGetString with the provided AES object. Let's take a look at AESGetString as it seems to be what is handling the decryption of the config strings.
On the right hand side of the parameters provided to the GetString function, we can see that initially, the config string is Base64 decoded and then passed into a decrypt function. Because AES uses a key to be able to decrypt its config, I have set a breakpoint at the return of a string from the Decrypt function. This will allow me to inspect the AES object which will contain the decryption key which was being created at the start of InitializeSettings.
Within the AES object the key is a byte variable named _key this variable contains what we are looking for. The IV is also generated each time the decrypt function is called and using these two pieces of information I have then created a simple config decryption script in CyberChef (link).
Here is a link to the recipe which can be used to decrypt the config of this version of MassLogger. Now that I have a recipe to decrypt the MassLogger config strings, let's try and use it to decrypt the version of this sample.
Along with the version, I can also determine other parts of the config. I can see what functionality the builder has enabled/disabled, along with credentials used for SMTP/FTP exfiltration. Luckily, checking some of the config strings, we can see that anti debug and anti-vm are disabled, which will reduce a lot of hassle trying to reverse and debug the sample.
Once the config has been decrypted the malware then grabs some information about the PC and runs mutex. After this, if the Windows Defender exclusion functionality is enabled in the config, and the malware is running as admin then the malware will attempt to add itself into Windows Defender's exclusions.
Windows Defender Exclusion Checks
Most of the functions in MassLogger will document if they're enabled within the log file, along with any necessary environment options required for the functionality to succeed. If you look at the above image, on the second line you'll see that MassLogger has some dynamic settings that are set during runtime. One of these is the MainDirectory variable that'll be set to the directory containing the running malware. If the checks fail, then it's logged and the function returns. If the checks succeed then MassLogger will add itself to exclusions.
A new object is created named PSProcessStart. This is an object that will start a powershell process according to the provided variables. After this there's a call to CombineObjects to combine the provided strings. To add an exclusion to Windows Defender through PowerShell, you must make use of the Add-MpPreference cmdlet. This cmdlet allows you to add preferences to Windows Defender, one of these being ExclusionPath, which will exclude the given path from Windows Defender scans. Once this exclusion has been successfully added, then the success is logged and the function returns.
MassLogger uses a few techniques to hide and interrupt analysis. These range from anti-VM to anti-debug and anti-sandboxie.
Let's first take a look at the anti-debugger, this is the flow that will be used if the setting is enabled.
We will arrive at IL_94 if the anti-debugger setting is enabled. Then there is an if statement that calls a function I have named DebuggerPresent. If this function returns true, then the program goes to IL_9C which as you can see above will make the malware exit and self-destructs. Taking a look into DebuggerPresent we can see a simple call.
Check Remote Debugger Present
MassLogger has imported the CheckRemoteDebuggerPresent from kernel32.dll and used it with parameters of a handle to the current running process and a referall to an empty boolean. The flag is then returned and the result of the API call is used in the previously mentioned if statement. This check is going to exit the process if a debugger is present. Although in theory this may work for someone new to debugging and reversing malware, in practice this function can just be removed so that I didn't have to actually deal with it trying to hinder my analysis.
In the image above you can see that AntiVM is called within an if statement. The result of the function will either cause us to go to IL_1D or IL_D6. IL_D6 calls the ExitSelfDestruct function to exit the program and IL_1D will continue with the flow of the program. Let's take a look at some of the methodology of the AntiVM.
Detect Virtual Machine
This is the original code from the creators' GitHub. It utilises the ManagementObjectSearcher class to be able to query information about the PC through WMI. It selects everything from Win32_ComputerSystem, and then iterates through the retrieved items. In each item, it checks the manufacturer and converts it to a lowercase string. This string is then compared to "microsoft corporation".
Models are also queried if they contain "VIRTUAL". After these two checks there are two more checks if the manufacturer contains the "vmware" string and if the model string is equal to "VirtualBox". These checks will determine whether the sample is running within either VMware or VirtualBox environments. If this function returns true within the malware then the program will exit and delete itself.
This check is called and if the result is true then the program will self-destruct like it does with the other VM checks. The chosen methodology of checking if Sandboxie is running is to try to get a module handle for a DLL that runs within Sanboxie. If this handle fails (returns 0) then the function will return false indicating that the program is not running within Sandboxie.
The author of MassLogger has tried to pack in as much functionality as possible. One of these functions is to spread via connected USB. This is an old technique, but may prove to be quite effective given the right victim. This functionality is again enabled within the builder. The malware will check whether the functionality has been enabled and if so it'll jump into the first method within the USB spreader class. Again looking at the creators GitHub page we can get the original code. The first thing the function does is run the Initialize function. Within the Initialize function it calls ExplorerOptions.
This function makes sure that explorer doesn't display extensions, hidden folders or files. Once these settings are confirmed it'll go on to look through the attached drives, checking whether they are a removable USB.
Once it finds a removable USB, it'll search its directory checking if the work directory exists, if not then it'll create this directory with its display hidden. It will then check if within this work directory another directory exists that'll contain all of the icons used for spreading. If the directory doesn't exist it'll create it. Again it will check if the malware exists within this work directory, if not it will copy itself into the work directory. Lastly it then checks whether the payload is within the directory, if not it'll drop the payload into the directory. Let's take a look at the payload.
USB Spread Payload
This payload is what we commonly refer to in malware as a binder, it will run the original file and the malware. Making it seem as though the program runs what the user expects along with the malware hidden in the background. Once this is done the spreader will begin to infect all the files within the USB.
The function recursively iterates through all of the files on the USB, checking whether they have been infected. If not, then the file will have its icon extracted to the icons directory within the hidden work folder on the USB. The malware then moves the file into the hidden work directory and compiles a replacement that uses the same icon as the original file, along with commands to open the original file from within the work directory whilst also running the payload. This means that all the files will be replaced on the USB with infected versions that will then be run if the infected user shares the USB with anyone.
MassLogger offers the user the ability to maintain persistence on the infected machine. This is achieved by making sure that the malware runs on boot. Looking in the malware for this, there is a class dedicated to it that is only called if the functionality is enabled within the config. The first thing it does is get the folder that the malware is going to be copied to. Stereotypically this is within AppData.
It'll then get the executable path and check whether the install path matches the current running program's path. If they do not match then we get all running processes. Iterating through each process checking if the processes' file name matches the current running process. If so then it'll kill the running process. After this the malware checks if the program is running as admin, if it isn't then it'll use the following to open a registry key.
Open Sub Key
Reversing the used string we get: "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\". This is the key used to determine what files are used for startup. MassLogger sets the registry key to the location of the copied file in AppData.
Set Registry Key
Once this has been done the MassLogger will read all bytes of the original file and then write them to the install folder found within the config. A setting is then checked to see whether MassLogger should delete the zone identifier for the newly written binary in AppData, which will cause forensics on the file to be slightly more difficult.
MassLogger then creates a directory for a batch file within AppData, here is the directory it generated for me: "C:\Users\admin\AppData\Local\Temp\tmpD8A7.tmp.bat". A stream writer is then created for the generated file and the following is written to it.
@echo off is just an indicator to not output the used commands, then the script waits 3 seconds by using the timeout command. Once this has been done we see the START command being used to run the new copied file in AppData. The batch script then CD's into the directory containing the batch script and deletes itself.The batch script is then run by the malware with a hidden window, once this has been done then the malware will exit.
MassLogger first initialises some settings for the function.
Once these have been set MassLogger will go on to check if the downloader setting has been enabled along with if the DownloaderOnce setting is enabled. MassLogger doesn't use a recurring call to a C2 to get the file to download, and instead will ask for a URL upon building. The malware checks the location of where it would download a file to, if a file doesn't exist, it'll create a HTTP GET request to the download link found in the config. If the download fails, then this'll be logged and the function will return. If not, then the malware will get the response from the request and copy it to a memory stream. This memory stream is then written to a file stream which is located in the download path from the config.
Once this has been accomplished MassLogger proceeds to create a VB script within the temp folder and begin writing to it.
Downloader VB Script
This script will run the downloaded file and then delete itself. The malware creates a process to run this script and then logs that it has successfully ran the downloaded file.
MassLogger's main feature is its keylogger. We begin with the usual check to see if the keylogger has been enabled, and if it has, we then jump into an endless for loop. The keylogger uses a string builder to log any key presses. Thanks to the very generous creator of this malware we can simply check his GitHub to find the full source of the keylogger. The first important thing the keylogger does is create a low level keyboard process. This is set to HookCallback. This function will take key presses and translate them into strings that can be written to the string builder.
Within HookCallback we see a few checks and then some flags set to whether the caps lock or shift button are pressed on the keyboard. The current key is mapped from another function, and checked to see if it should be logged as a special key e.g the enter key, or if it should be uppercase because of caps lock or the shift button being used. Before the key is written to the log the malware will get the current window title and log, it if it has changed.
The author chooses to use a very common method of implementing a keylogger by calling the windows API SetWindowsHookEx using the WHKEYBOARDLL, which will get low-level keyboard events. The handle is then passed to the current process.
If the infected user has managed to install malware once, then it is likely that they have infected themselves multiple times. The author of MassLogger knows this, and doesn't want his malware to be sharing an infected system with other malware. He has included a "BotKiller" which is a piece of code that will look for and remove malware. This functionality is usually uncommon due to most competing malware having reasonably good methods of hiding themselves. Again this functionality is optional and if enabled then the function will be run. Let's take a look again at the creators GitHub where he has pasted the source code for their "BotKiller".
The main function is RunBotkiller, which will go through all running processes and then call the Inspection function on them.
First the inspection function checks whether the inspected file is itself. Then the file directory is compared to application data and user profile directories, if the file is within these directories then it is labeled as a threat. Next the filename is compared to wscript.exe which is used to run VB scripts. Lastly the location of the file is again compared with another folder and if the file's location begins with this directory then it is labeled a threat. This method of detecting possible threats is very problematic and I'm sure will cause false positives. If the file has been labeled a threat by Inspection it will be checked to see whether its window is visible. If not then RemoveFile, will be called which will kill the process, remove it from startup in the registry and then delete the file off disk.
MassLogger supports many programs that it can steal credentials from. I'll concentrate on the more commonly used programs, as the author has implemented the same methodology of retrieving credentials for multiple programs. The first program MassLogger attempts to steal from is Telegram. MassLogger starts by getting the following directory: "C:\Users\admin\AppData\Roaming\Telegram Desktop\tdata" and checking if it exists. If it does exist then the malware will begin to zip the files within this directory and write the following to the log: "Usage: Download 'Telegram Desktop' and unzip all files in 'Telegram.zip' to AppData\\Roaming\\Telegram Desktop\\tdata"
Next up is Pidgin, it begins by checking if the stealer setting is enabled. Like Telegram the malware gets the following directory: "C:\Users\admin\AppData\Roaming\.purple\accounts.xml" and checks if it exists. If the file does exist, it is read using an XML node and the contents are written to the log.
Once Pidgin has been stolen from MassLogger will then go after FileZilla. Like the previous programs malware will get the following directories: "C:\Users\admin\AppData\Roaming\FileZilla\recentservers.xml" and "C:\Users\admin\AppData\Roaming\FileZilla\sitemanager.xml". Once these have been checked to exist then the function will once again use an XML node to iterate through them and write the credentials into the log.
Discord is the next target of the malware, the creator has the code for this function on his GitHub so I'll look there to reverse it.
Discord File Search
We first see the SearchForFile function being used to find a leveldb file that Discord uses to store credentials. It does this by getting the directory location for the local storage of discord. It checks if this directory exists and then will iterate through each of files that have an ldb file extension. Then reading these it will check if they contain the "oken" string to determine if it is the correct file. Once the correct file has been found then regex will be used to extract the token from the file and this will be logged.
NordVPN is then attempted to be stolen from by MassLogger. This is done by getting the following directory: "C:\Users\admin\AppData\Roaming\NordVPN" and the user.config within it is read by XML and the credentials are written into the log.
MassLogger will now proceed to attempt to extract credentials from Outlook, it does this by first initialising an array of registry locations.
We then see another array with the following.
MassLogger will then go through the registry locations looking for keys. It will then proceed to use the array of strings to then look through each key with regex. Searching for passwords which will then be logged.
The malware will also go after browsers, the first one it targets is Firefox. It will begin with getting the following directory: "C:\Users\admin\AppData\Roaming\Mozilla\Firefox\Profiles", then checking if it exists. Once this has been done the malware will use signons.sqlite and grab any stored credentials. Decrypting them with DES. The same is done for all chromium browsers.Chromium Browsers
The login data storage location is found and opened. MassLogger will then query credentials and other information from these databases and use Bcrypt to decrypt them.
MassLogger has many methods of getting the stolen information to the actor using the malware. Currently MassLogger uses 3 methods: FTP, SMTP & HTTP. The first two are somewhat simple where credentials for the chosen method will be stored in the config and then used to send an email or upload the zip to the receiver. HTTP is more interesting because the author has created a PHP control panel to receive logs from the malware. Here is what the corresponding panel for this version looks like.
The control panel will receive zips uploaded by the malware and allow you to view the log and download all the contents. Information about an infected machine is placed in the zip filename in the following format: user_country_hwid_date_extra.zip
If you're reading this I'd like to begin by thanking you for making it to the end. I hope you enjoyed this writeup, and got some useful information out of it. I am very proud of this post and hope to take more in depth looks into malware in the future. Since the writing of this post MassLogger has had some small updates along with a new control panel. The analysis in this post still applies and I may update this post if there are any larger updates to cover. Until the next one, thank you!