

THANOS RELATED MALWARE
1 Malware Summary
1.1 Malware description
Malcrove has discovered a persistent malware that has been active in targeting an organization in the Energy industry. The malware infects a victim’s host with a ransomware, encrypts certain files and tries to spread over the local network to infect other hosts. Our research revealed that the malware was created with the Thanos builder. Thanos is a RaaS (Ransomware as a Service) that provides buyers and affiliates with a customized tool to build unique payloads. Due to this reason all malware instances can have different hashes.
As a result, files are replaced with encrypted ones with the extension “.locked”. Moreover, a file with the following contents will be created on the victim’s machine.


1.2 Threat summary
Threat Type | Ransomware, Crypto Malware, Files locker. |
Symptoms | You can’t access files stored on your computer.Affected files will have their extension changed to a different extension like filename.locked.A ransom demanding message is displayed on your desktop (file “HOW_TO_DECYPHER_FILES.txt”). Attackers are asking to pay a ransom (in bitcoins) to unlock your files.The file “c:\windows\update.ps1” or “c:\windows\update{{number}}.ps1” is observed on an infected computer. |
Damage | All files with specific extensions are encrypted and cannot be opened without paying a ransom. |
Operation system | Windows. |
Distribution methods | By executing malicious .ps1 script. This malware is spreading inside the local network via SMB (port 445). The script has hardcoded credentials embedded with a username and password. |
1.3 Malware assets
Update.ps1 (update2.ps1, update3.ps1, update4.ps1) | |
SHA-256 | 240E3BD7209DC5151B3EAD0285E29706DFF5363B527D16EBCC2548C0450DB819B64E453ACB4624AC06A1E8D6072CE2E49718CC7E9EC37FA3252825DBC466346140890A1CE7C5BF8FDA7BD84B49C577E76E0431E4CE9104CC152694FC0029CCBF40890A1CE7C5BF8FDA7BD84B49C577E76E0431E4CE9104CC152694FC0029CCBF |
MD5 | A15352BADB11DD0E072B265984878A1CAE500D2F4C8C487B8768374B16915F79AF0E33CF527B9C678A49D22801A4F5DCAF0E33CF527B9C678A49D22801A4F5DC |
Size | 312613312636312645 |
Variant | There are different versions of this malware. |
Description | This is an entry point for this malicious software. This script is using injected PowerShell script and invoking .NET Unpacker. Also, this script is infecting other hosts. |
injected_powershell.ps1 (name is not original) | |
SHA-256 | 3B119B738D8A366417809BA57BEAA6A35C0183C8A4CE7D1AD8AE4DA53CEF1F92 |
MD5 | 20111656F108D137DF15C1535F26D898 |
Size | 350032 |
Description | The file contains .NET Unpacker source code |
.NET Unpacker Source code (name is not original) | |
SHA-256 | E8AC84E3B71E3BF706D1F1F72DEF653801121A31C2F83BF88294FD0EB9C04050 |
MD5 | 11A95237348C0E2169046D8DE28BDE29 |
Size | 172858 |
Description | Source code for .NET component. This code compiles and executes by update.ps1. This code is unpacking the binary unpacker and invoking it. |
Binary Unpacker (name is not original) | |
SHA-256 | C2E2A9E40D688D865CB86D01D3F52CCF6BCD0875E584549D8FECB7AB7B032D02 |
MD5 | 129BBC7D5E009E7742C5A7C0CA1095B7 |
Size | 119620 |
Description | This software is unpacking malware and invoking it. |
Malware (name is not original) | |
SHA-256 | C8BC6A9997BFDB5E991E7CDD1456BE7ECF77E392AA3EECDE8006BF59BDAC7126 |
MD5 | 1F7B82052634FA4E22A2B4F767E59D1D |
Size | 105272 |
Description | This is the actual malicious component that is encrypting files on the victim’s computer and infecting other hosts. |
1.4 Malware architecture
Initially, this malicious file consists of a PowerShell script with the name “update.ps1”. In the process of executing this script, the malicious file runs another script that invokes the decompressor (.Net), which in turn invokes another decompressor (binary code), which at last invokes the malware itself (.Net).
Following process flow shows the malware execution that consists of 5 different components (two PowerShell scripts, 1 C-Sharp source code, 1 Binary and 1 C-Sharp compiled code) which are incapsulated into each other.


2 Malware analysis
2.1 Initial PowerShell script ‘update.ps1’
2.1.1 General overview
The initial script is an executable PowerShell file with the name “update.ps1” (or “update{{number}}.ps1”). This script consists of 2 parts – encoded data and executable code.
The first 9 lines of this script are just a concatenation of Base64 strings into one. These strings are quite long (more than 300.000 characters, hence not pasted in this report). The image below represents the rest of the script.


2.1.2 malicious activity on the current computer
Lines 10 and 11 are decoding base64 string that was initialized before to data (variable ‘a’) 2 times. Line 12 is executing command ‘iex’ (alias for Invoke-Expression command) and passing decoded base64 value as an argument.
Code (lines 13-19) is checking whether this script was already executed by checking the specific file that is being created during the script execution. If this file already exists, it means that the script has been executed. In this case execution is aborting.
Code (lines 20-27) is searching processes with specific name. In this case the name is ‘svchost’, but in other cases the name can be ‘notepad’. After this the code is trying to execute the function ‘Do’ passing the ID of the selected process (this script will be described in the next paragraph). After the action the script is waiting for a specified time (in this case, 900 seconds) and aborting this loop if the file “c:\logdb.txt.locked” exists (the file is being created during malware execution).
2.1.3 Infecting other hosts
The code (lines 29-48) is receiving hosts’ IP-addresses and trying to filter only local-addresses by filtering them by first part (is must be equal to “10.”, “172.”, “192.”).
After this, the code (lines 49-62) is going through all local network interfaces and trying to execute the follow code for all accessible hosts. The malware uses ‘net’ command to copy the files to other hosts and uses WMI calls to execute the copied file with specified credentials (username and password),


2.2 Injected Powershell Script
2.2.1 General overview
This paragraph describes the code that is encoded twice with base64 and placed in the beginning of the PowerShell script.
To extract this code, it is necessary to execute the first 11 lines of the PowerShell script and then save the value of variable $a to a specified file.
2.2.2 Analysis of extracted data
After extracting the data and researching it was concluded that the current script contains a string variable ‘code’ with C-Sharp code and one Add-Type command. The content of this file is represented on the image below (the actual code was collapsed to save the space; it will be described in the next paragraph).


This PowerShell code is executed by the initial PowerShell script that was described in the previous paragraph. This means that the attached code will be compiled as a C-Sharp executable file with the .Net framework and will be executed by the initial script.
2.3 C-Sharp unpacker
2.3.1 General overview
This paragraph contains the research of C-Sharp source code that was attached to the injected PowerShell script. To analyse it, this code was extracted from PowerShell script and placed into a new file ‘unpacker.cs’.
2.3.2 Code analysis
This source code doesn’t have any “Main” function, the initial PowerShell script is calling function “Do(Int32 PIDP)”. This function code is represented on the image below.


Since this component was obtained in the source code, all names of functions and variables are original. Firstly, the process ID that was received from the initial script is validated by the function ‘static PROC_VALIDATION ValidateProc(Int32 ProcId)’. If the process is valid and is not using Wow64 (a subsystem of the Windows operating system capable of running 32-bit applications on 64-bit Windows), the function ‘static void CastleKingside(String Path, BerlinDefence.PROC_VALIDATION Pv, Int32 ProcId, Boolean Clean)’ is being called.
The source code of this function is represented on the image below.


On line 390 the shellcode is read (this process will be described below), after this there are 2 function calls – MapLocalSection and MapRemoteSection which are allocating a section and mapping this section to the specific process with the selected ID. When the shellcode is copied to the allocated memory a new thread is created which is executing this shellcode.
The source code of the “ReadShellcode” function is represented below.


This code is initially encoded with Base64. Hence this code is decoded and transformed to the byte array.
2.4 Binary unpacker
2.4.1 General Overview
After extraction this code was loaded to IDA Pro with the following parameters:
- Virtual address: 0x0000_0000
- CPU Architecture: x86-64 bit
By reverse engineering the binary we were able to create the memory map of this executable file.


This executable file has entry point at zero offset (call instruction to start the executable code).


The image below contains a part of a function called “x_main”. This function has atypical prolog – the first instruction is “pop rcx”. This technique is used in order to determine the starting point of this memory page with the shellcode block, as this page is dynamically allocated. Due to this, all calls and references are relative to the starting point.


2.4.2 System call analysis
Since this code is injected into another process and it is using system calls, it is necessary to find the addresses of these system functions without the import table. In order to find the system function, this code is using the function called “x_get_sys_func_by_hash”. Example of calling this function is provided below.


The code is calling this function with one argument – 8 bytes proprietary hash for the function, which depends on the library name and function name.
The code of the function “x_get_sys_func_by_hash” is showcased below.


This executable is using a well-known technique – with TEB table (pointer is stored in the memory gs:0x0000_0030) they are accessing PEB table (offset 0x60 for 64-bit architecture) and PEB_LDR_DATA *Ldr (offset 0x18 for 64-bit architecture) and to LIST_ENTRY InLoadOrderModuleList with the list of all modules.
After the executable received the pointer to the modules list, it is going to try and locate the function that is matching the input hash. If the function was found, the current code is returning the pointer to the found function.
With use of reverse engineering techniques, we were able to generate a list with all the functions that are used by this code.
kernel32_LoadLibraryA | wininet_InternetCrackUrlA |
kernel32_GetProcAddress | wininet_InternetOpenA |
kernel32_GetModuleHandleA | wininet_InternetConnectA |
kernel32_VirtualAlloc | wininet_InternetSetOptionA |
kernel32_VirtualFree | wininet_InternetReadFile |
kernel32_VirtualQuery | wininet_InternetCloseHandle |
kernel32_VirtualProtect | wininet_HttpOpenRequestA |
kernel32_Sleep | wininet_HttpSendRequestA |
kernel32_MultiByteToWideChar | wininet_HttpQueryInfoA |
kernel32_GetUserDefaultLCID | mscoree_CorBindToRuntime |
kernel32_WaitForSingleObject | mscoree_CLRCreateInstance |
kernel32_CreateThread | combase_CoInitializeEx |
kernel32_GetThreadContext | combase_CoCreateInstance |
kernel32_GetCurrentThread | combase_CoUninitialize |
shell32_CommandLineToArgvW | ntdll_RtlEqualUnicodeString |
oleaut32_SafeArrayCreate | ntdll_RtlEqualString |
oleaut32_SafeArrayCreateVector | ntdll_RtlUnicodeStringToAnsiString |
oleaut32_SafeArrayPutElement | ntdll_RtlInitUnicodeString |
oleaut32_SafeArrayDestroy | ntdll_RtlExitUserThread |
oleaut32_SafeArrayGetLBound | ntdll_RtlExitUserProcess |
oleaut32_SafeArrayGetUBound | ntdll_RtlCreateUnicodeString |
oleaut32_SysAllocString | ntdll_RtlGetCompressionWorkSpaceSize |
oleaut32_SysFreeString | ntdll_RtlDecompressBufferEx |
oleaut32_LoadTypeLib | ntdll_NtContinue |
2.4.3 Code Analysis
The current code is allocating a buffer and decrypting another executable code into this buffer. This code is .Net code, so to execute it, the current executable is using a sequence of system calls in the function “x_dot_net_env_settings”.


Before this action the executable is disabling AMSI so Anti-Virus software can’t detect or block the malware. The next functions by patching their prolog.
- amsi_AmsiScanBuffer
- amsi_AmsiScanString
- wldp_WldpQueryDynamicCodeTrust
- wldp_WldpIsClassInApprovedList
After all these actions, the actual malware is being executed.
2.5 C-Sharp Ransomware file
2.5.1 General Overview
The malware is written in C-Sharp. To receive a source code, the malware has been decompiled. After this it was concluded that the code was obfuscated:
- Almost all strings were encoded with Base64;
- Some strings were reversed;
- All names of variables and classes were changed to random strings.
To make the research easier all strings were decoded and during the research most of the names were renamed to meaningful ones.
2.5.2 Code Analysis
This malware has a hardcoded config. All other config names were obfuscated, but with reverse engineering techniques some of them were recovered.


This malware is starting with the Main function and all actions are performing in its body. Separate blocks can be noticed. The part of this code is represented on the image below.
The most significant part of this malware will be described below.


2.5.3 Process detection and anti-virus bypass analysis
One of the first actions of this malware, kill all processes, can be used by a researcher to investigate the malware. On the image below we can see a part of the code that is being called.


In the function “killAllReverseProcesses” all processes which contain the name from the list below will be killed.
http analyzer stand-alone | intercepter | procexp64 |
fiddler | Intercepter-NG | RDG Packer Detector |
effetech http sniffer | ollydbg | CFF Explorer |
firesheep | x64dbg | PEiD |
IEWatch Professional | x32dbg | protection_id |
dumpcap | dnspy | LordPE |
wireshark | dnspy-x86 | pe-sieve |
wireshark portable | de4dot | MegaDumper |
sysinternals tcpview | ilspy | UnConfuserEx |
NetworkMiner | dotpeek | Universal_Fixer |
NetworkTrafficView | ZG90cGVlazY0 | NoFuserEx |
HTTPNetworkSniffer | ida64 | |
tcpdump | procexp |
2.5.4 Disabling security options
After disabling all researching software, the malware is trying to disable other security features:
Disable controlled folder access:


Disable Windows Defender:


Disable different services and other features:


In order to stop the Anti-Virus software, all of the below commands will be executed:
stop avpsus /y | stop VSNAPVSS /y |
stop McAfeeDLPAgentService /y | stop VeeamTransportSvc /y |
stop mfewc /y | stop VeeamDeploymentService /y |
stop BMR Boot Service /y | stop VeeamNFSSvc /y |
stop NetBackup BMR MTFTP Service /y | stop veeam /y |
stop DefWatch /y | stop PDVFSService /y |
stop ccEvtMgr /y | stop BackupExecVSSProvider /y |
stop ccSetMgr /y | stop BackupExecAgentAccelerator /y |
stop SavRoam /y | stop BackupExecAgentBrowser /y |
stop RTVscan /y | stop BackupExecDiveciMediaService /y |
stop QBFCService /y | stop BackupExecJobEngine /y |
stop QBIDPService /y | stop BackupExecManagementService /y |
stop Intuit.QuickBooks.FCS /y | stop BackupExecRPCService /y |
stop QBCFMonitorService /y | stop AcrSch2Svc /y |
stop YooBackup /y | stop AcronisAgent /y |
stop YooIT /y | stop CASAD2DWebSvc /y |
stop zhudongfangyu /y | stop CAARCUpdateSvc /y |
stop stc_raw_agent /y | stop sophos /y |
2.5.5 Malware Installation for Autorun
There is a part of this code that can install this software to run automatically. The code is presented below.


This code fetches the random name from below list and copy this software to the autorun directory.
lsass.exe | calc.exe | spoolcv.exe |
svchst.exe | mysqld.exe | ctfmom.exe |
crcss.exe | dllhst.exe | SkypeApp.exe |
chrome32.exe | opera32.exe | |
firefox.exe | memop.exe |
However, this action will be executed only if variable “cnfInstallToAutoRun” is set to “yes”. Yet in this version of this software, this variable is set to “No”, hence it means that this software will not be installed as autorun software and will be executed only once.
2.5.6 Encryption key generation
Depending on the configuration, a key to encrypt files can be hardcoded or generated with random Base64 string 32 characters long.


In this malware the variable is set to “No”, so the key will be generated at random.
The key will be used to encrypt all of the required files. The encryption and decryption algorithm will be described below. So, it means that it is impossible to predict the key value of the determined host. To generate the string 24 crypto-random bytes are used. Therefore, there are approximately 1058 different password options and it is practically impossible to find the correct one with brute force.
This key for file encryption is saved in the specific file, but before being saved this key is encrypted via asymmetrical algorithm RSA. There is a hardcoded 2048-bit public key. The symmetric key for encryption is being encrypted with this public key.


The scheme below is describing the process of symmetric key usage.


Therefore, without the private key (which supposedly belongs to the attacker) it is practically impossible to restore the key to decrypt these files. This encrypted key is stored in the file with the name “HOW_TO_DECYPHER_FILES.txt”. Allegedly, an attacker, in exchange for a ransom, decrypts an encrypted symmetric encryption key and send it back to the victim to decrypt all files on his computer.
2.5.7 Ransomware Execution Analysis
A part of the code that is encrypting files on the victim’s computer is presented below.


The first argument is an array with all the root directories which will be encrypted. Second argument is the list of file’s extensions that will be encrypted. Last 2 arguments are the key for the symmetric encryption and the new file extension. Table below show the respective file extensions.
dat | ppt | mdb | odg | backup | aiff | mp3 | gpg | mov |
txt | doc | dbf | raw | flac | tiff | edb | java | |
jpeg | docx | odb | nef | cert | m4a | vsd | xls | p12 |
gif | sxi | myd | svg | docm | csv | accdb | mpeg | ost |
jpg | sxw | php | psd | xlsm | sql | mp4 | qbb | htm |
png | odt | java | vmx | dwg | ora | 7z | xdw | mrimg |
php | hwp | cpp | vmdk | bak | mdf | wav | class | rtf |
cs | tar | pas | vdi | qbw | ldf | djvu | csr | dim |
cpp | bz2 | asm | lay6 | nd | ndf | aes | pst | pptx |
rar | mkv | key | sqlite3 | tlg | dtsx | sql | xlsx | accdb |
zip | eml | pfx | sqlitedb | lgb | rdl | avi | ods | pem |
html | msg |
A part of the code that is responsible for encryption is presented below.


To encrypt these files “RijndaelManaged” class is using algorithm – AES. After the encryption all original files will be deleted.
3 Conclusion
3.1 Analysis summary
- The malware consists of 5 different components (two PowerShell scripts, 1 C-Sharp source code, 1 Binary and 1 C-Sharp compiled code) which are incapsulated into each other. Our malware analysis has revealed that the first point of trigger is a PowerShell script. The actual malware is written in C-Sharp (.NET).
- It is observed that there are at least 4 similar versions of the initial PowerShell script with minor insignificant differences in the code. The attacker preserved to make it difficult to detect and block this script with only a hash. Other 4 components have been determined to be the same, even in the occasion that the initial scripts were different.
- During the execution the malware is disabling several protection mechanisms of the operating system and checks if it the malware is being researched in a sandbox.
- The key for file encryption is generated at random. It is practically impossible to brute force it. For the file encryption the malware is using AES in CBC (Cipher Block Chaining) mode.
- The key is encrypted with asymmetric RSA cipher with public key that is hardcoded into the malware. To restore the file encryption, the private key is necessary. Allegedly, the attacker, in an exchange for a ransom, decrypts an encrypted symmetric encryption key and sends it back to the victim to decrypt all files on their computer.
- There is obviously no guarantee that when paying a ransom, the attacker can or will decrypt the data of the victim.
- The malware is spreading across the local network with mask 255.255.255.0. The malware has hardcoded credentials with a username and password in place to allow the malware to spread effectively. This has been an indication that the attacker had knowledge about the credentials and the current malware was tailored, compiled and build for the specific organization.
- After the malware execution, the evidence remains – the script in the “C:\Windows\” directory with name “update.ps1” or “update{{number}}.ps1”.
- We have determined that the script execution did not result in data exfiltration to the attacker. Only one malicious action was detected, namely ‘file encryption’.
- We have determined that the attacker has used “Thanos builder” for building new malware instances that could have different hashes. This means that it is very difficult to ban this file only with hash. Furthermore, the attacker is able to tailor the malware to be used to attack other organizations.
3.2 Threat mitigation
Reference is made to chapter ‘3.1 Malware assets’ that depicts the list of hashes we have identified. Note that the attacker can generate, with use of the Thanos framework, a new version of the ransomware that will result in a new hash. Therefore, we recommend following actions to detect and block the ransomware effectively:
- Adopt an EDR solution that allows to carry out behaviour analysis on processes and binaries for the existence of the malware;
- Block PowerShell for users and allow only on a need to use basis;
- Restrict the use of PowerShell to not allow script execution;
- Disable WMI between workstations;
- Enable security monitoring rules on ‘net.exe’ command execution and other relevant network applications.