I was looking for a .NET malware to mess around with dnspy a bit so I checked out https://bazaar.abuse.ch. Sure enough I found one right at the top that was labeled as AgentTesla and Anubis.
Note: this is not the Android malware making its rounds currently that shares the same name.
FILE SIZE: 128.00 KB (131072 bytes)
ORIGINAL FILENAME: Anubis.exe
CREATION DATE: 9/30/2020
As I loaded it up in dnspy, I was expecting to spend a lot of time de-obfuscating this malware but to my surprise it wasn’t obfuscated at all so we can look at everything this malware is doing straight from the code level.
It looks to be utilizing Loki code to do the majority of the actions. From an overview, we can get a good idea of what its capabilities are.
- Install ransomware
- Steal cookies
- Steal credit cards
- Steal passwords
- Steal web data
- Grab hardware information
- Grab wallet information
- Send the data somewhere
Looking through the code a bit deeper, let’s look at the Echelon section here.
This section is responsible for looking in the Windows Credential Manager and grabbing local creds.
In the Loki section, there’s a couple of classes here.
Just from this little bit of code, we have a good understanding of this piece of malware. Looking at the settings, we can see what the attackers currently have set. Ransomware and loader capabilities seem to be disabled for this particular sample meaning that it’s just looking to steal info.
If we look back at the Main() function, we can correlate the settings with the actual functions being called if they’re enabled.
|webka||get_webcam function called|
|grabber||grab_desktop function called|
|steam||StealSteam function called|
Every one of these functions also have Program.dir being passed to them. If we take a look at that function, we can see it’s actually creating a directory to save all of the results of these functions in a directory called AX754VD.tmp located in the AppData\Local\Temp directory.
This is found by looking at the dir function and seeing that it’s calling the GetTempPath() function. Looking at Microsoft documentation, this outputs the directory that’s stored within the Temp environment variable. By default the path mentioned earlier is the default for that variable.
Continuing to look at the Main() function, we can see that this sample will always perform the following actions.
These don’t have checks for within the settings class like the others so they will always run.
Grabs a screenshot of the screen and saves it as screen.jpg in the AX754VD.tmp mentioned above.
Grabs data from FileZilla artifacts called sitemanager.xml, recentservers.xml, and filezilla_sitemanager.xml. These artifacts provide details of saved FTP sessions as well as simply recently used FTP sessions via FileZilla and they include the credentials utilized for those connections in plain-text. This allows the malware to grab FTP creds quite easily.
Copies all files from the tdata directory in order to steal Telegram data. The default location is %APPDATA%\Telegram Desktop\tdata however this malware also starts this function by looking at the directory stored in the DefaultIcon registry key to ensure it knows where these files are stored in the event that the user chose a non-default install directory.
Looks at the key files, cookies file, and logins file of Firefox and then proceeds to decrypt them in order to grab any credentials saved in Firefox.
Copies any wallet.dat files found in order to steal CryptoCurrency wallet information. The wallet.dat files includes the wallet private keys.
Grabs information about the OS and based off of that information, it creates a custom UserAgent to use in traffic back to the C2 server. The C2 server is http://anubiscode%5B.%5Dfun/ seen stored in the settings under the variable name of Url.
Copies the vdf files containing login information from the Steam directory.
Recurses through NordVPN directories to find user.config and passes it to the decoder function to get plaintext values.
Downloads a file from url_loader variable set in the settings and saves it as svhost.exe and proceeds to run it.
Under the crypt class, we can actually see the passwords and salts used for the loki_decrypt() function.
In the RansomwareCrypt() function, we can see what directories are targeted, what the ransom note will contain, what the encryption key used is, etc.
Above is the array for directories that are targeted by the ransomware function.
Here we can see the ransom note being created and saved as a file called HowToDecrypt.txt
Formatted and using the variables stored in the Settings class:
All your files are encrypted with Loki stealer: v.2.0 Reload
- Send 0.02 BTC to: KESHEL
- Follow All Steps
If ransomware capabilities were enabled in this sample, there would’ve been a BTC wallet address included in the ransom note.
Let’s break down how this sample is performing encryption. Here’s the block of encryption code:
This sample is using rijndaelManaged for the encryption. Rijndael is a symmetric key AES algorithm. Here we can see the settings being used. This sample is using the algorithm with a 256-bit key size and a 128-bit block size. These values are later passed into the rfc2898DeriveBytes function. This function takes a password, salt, and iteration count to create keys for encryption and decryption using a pseudo-random number generator.
The password and salt are actually the same string. The sample is using the string variable PasswordEncrypt for both values and then it iterates through 1000 times.
Here’s the PasswordEncrypt variable:
Now this is the part that I’m not 100% sure I’ve totally figured out. I’m not well-versed in programming and nor am I a cryptography genius. I know the basics. But this is what I believe is happening.
The generated result is stored in a variable called rfc2898DeriveBytes. The sample then takes the KeySize variable and BlockSize variables, divides each of them by 8, then passes it through to the variable rfc2898DeriveBytes which are then then passed to rijndaelManaged.Key as well as rijndaelManaged.IV for the final Key and IV values. Then we can see the cipher mode chosen is CBC or Cipher Block Chaining.
Then basically the sample recurses through all directories stored in that directory array mentioned earlier, reads the bytes of each file and replaces them with the generated encryption bytes then saves the file with a .loki extension.
For a random sample grabbed on a late night to just mess around with, this was pretty interesting to take apart and analyze. Shoutout to dnspy for making this as easy as possible to check out.