Key takeaways
- r77 is a stealthy open source rootkit that is being used to deploy the XMRIG crypto miner
- r77 uses several modules as a way to successfully install and maintain persistence
- Campaign authors are leaning heavily on open source tools and scripts, possibly to abstract attribution or reduce development costs
Preamble
Elastic Security Labs has uncovered a malicious crypto miner that had been deployed in several Asian countries. The campaign owners are using an open source userland rootkit, called r77.
r77’s primary purpose is to hide the presence of other software on a system by hooking important Windows APIs, making it an ideal tool for cybercriminals looking to carry out stealthy attacks. By leveraging the r77 rootkit, the authors of the malicious crypto miner were able to evade detection and continue their campaign undetected.
In this research, we will highlight the inner workings of the r77 rootkit and explore how it was used in conjunction with the crypto miner. We hope to raise awareness of the ongoing threat posed by cybercriminals and encourage individuals and organizations to take proactive steps to protect their systems and networks.
Code analysis
Overview
The rootkit is comprised of 4 distinct modules:
- The installer module.
- The stager module.
- The service module.
- The core module.
We will cover each module and phase in detail below.
Installer module
Its first task is to store the stager module PE in the registry, a technique commonly used by malware authors to persistently store their malicious code on a system. Once the stager module is stored in the registry, the installer module builds a PowerShell command that loads the stager module from the registry and executes it, the installer module then creates a scheduled task to run the PowerShell command.
The installer locates the stager module stored as a PE resource named EXE , it then creates a new registry key called $77stager in the HKEY_LOCAL_MACHINE\SOFTWARE hive and writes the stager module to the key.
The installer then builds a PowerShell command to reflectively load the .NET stager in memory, using the [Reflection.Assembly]::Load method. Additionally, Microsoft’s Antimalware Scan Interface (AMSI) is circumvented by patching the AmsiScanBuffer API so that it will always return an AMSI_RESULT_CLEAN response. AMSI_RESULT_CLEAN means that the scanned content is “Known good. No detection found, and the result is likely not going to change after a future definition update.” The PowerShell command is then obfuscated by replacing variable names with random strings.
Finally, the installer creates a scheduled task to execute the PowerShell command using COM objects, the task is configured to execute at startup with the SYSTEM account.
Stager module
The stager is a .NET-based binary and it is responsible for unhooking DLLs, adjusting the SeDebugPrivilege setting, decrypting and decompressing the service module, and injecting the service module. This is accomplished using a process hollowing technique into a newly spawned process under another legitimate process through PPID spoofing.
API unhooking
To defeat the userland inline API hooking set by endpoint solutions, the stager module first completely unhooks two important DLLs that contain the API used by the rootkit, namely NTDLL.dll and KERNEL32.dll.
This technique involves the following steps:
- Retrieving the DLL : The stager module reads the target DLL file from the disk.
- Mapping the DLL to memory : The stager module creates a new file mapping using the CreateFileMapping function, which allows the DLL to be loaded into the process's memory.
- Analyzing the DLL's section table : The stager module analyzes the section table of the newly mapped DLL to identify the relevant section where the executable code (often referred to as the .text section) is stored.
- Overwriting the code section : Once the .text section is identified, the stager module replaces the contents of the corresponding section in the already loaded DLL with the code from the fresh .text section.
SeDebugPrivilege
The stager module next attempts to obtain the SeDebugPrivilege which allows it to inspect and adjust the memory of other processes.
This technique triggers Elastic’s SeDebugPrivilege Enabled by a Suspicious Process detection rule.
Service module decryption and decompression
Two versions of the same service module are stored in the resource section of the stager, a 32-bit and 64-bit version that will be deployed according to the system architecture.
The payload is compressed using the GZip compression algorithm and it uses a simple XOR for decryption. After decompression, the stager uses the first 4-bytes as an XOR key to decrypt the rest of the data.
Parent PID spoofing
To make the process hollowing injection appear legitimate, the parent PID spoofing technique is used to evade threat hunters and security tooling. This technique allows attackers to run processes under any parent process they want.
The malware first gets the process ID of the running winlogon.exe process which is a component of the Microsoft Windows operating system.
It then uses 5 Windows APIs:
- OpenProcess : Get the parent process handle.
- InitializeProcThreadAttributeList : Initialize the attribute list.
- UpdateProcThreadAttribute: Set the parent process handle via the PROC_THREAD_ATTRIBUTE_PARENT_PROCESS attribute.
- CreateProcess: Creates a new process under the spoofed parent
 tool, a closed source program for remote administration, developed by the Russian company TektonIT, which could be used to remotely control the infected machine and issue commands from a remote location. Finally, the script created a new admin user ( adm ) on the targeted system, which could potentially be used to carry out additional attacks or exfiltrate sensitive data.
Detection logic
Prevention
- Parent Process PID Spoofing
- Unusual Parent-Child Relationship
- Suspicious PowerShell Engine ImageLoad
- Privilege Escalation via EXTENDED STARTUPINFO
- Unusual Process Running as Antimalware Protected
Detection
- Parent Process PID Spoofing
- Unusual Parent-Child Relationship
- Suspicious PowerShell Engine ImageLoad
- Process Created with an Elevated Token
YARA
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the r77 rootkit.
rule Windows_Rootkit_R77_1 {
meta:
author = "Elastic Security"
creation_date = "2022-03-04"
last_modified = "2022-04-12"
license = "Elastic License v2"
os = "Windows"
arch = "x86"
category_type = "Rootkit"
family = "R77"
threat_name = "Windows.Rootkit.R77"
reference_sample = "cfc76dddc74996bfbca6d9076d2f6627912ea196fdbdfb829819656d4d316c0c"
strings:
$a = { 01 04 10 41 8B 4A 04 49 FF C1 48 8D 41 F8 48 D1 E8 4C 3B C8 }
condition:
all of them
}
rule Windows_Rootkit_R77_2 {
meta:
author = "Elastic Security"
creation_date = "2023-05-09"
last_modified = "2023-05-09"
license = "Elastic License v2"
os = "Windows"
arch = "x86"
category_type = "Rootkit"
family = "R77"
threat_name = "Windows.Rootkit.R77"
reference_sample = "21e7f69986987fc75bce67c4deda42bd7605365bac83cf2cecb25061b2d86d4f"
strings:
$a1 = { 8C 20 88 00 00 00 42 8B 44 21 10 42 8B 4C 21 1C 48 2B D0 49 }
$a2 = { 53 00 4F 00 46 00 54 00 57 00 41 00 52 00 45 00 5C 00 24 00 37 00 37 00 63 00 6F 00 6E 00 66 00 69 00 67 00 }
condition:
all of them
}
rule Windows_Rootkit_R77_3 {
meta:
author = "Elastic Security"
creation_date = "2023-05-09"
last_modified = "2023-05-09"
license = "Elastic License v2"
os = "Windows"
arch = "x86"
category_type = "Rootkit"
family = "R77"
threat_name = "Windows.Rootkit.R77"
reference_sample = "3dc94c88caa3169e096715eb6c2e6de1b011120117c0a51d12f572b4ba999ea6"
strings:
$a1 = { 5C 00 5C 00 2E 00 5C 00 70 00 69 00 70 00 65 00 5C 00 24 00 37 00 37 00 63 00 68 00 69 00 6C 00 64 00 70 00 72 00 6F 00 63 00 36 00 34 00 }
$a2 = { 5C 00 5C 00 2E 00 5C 00 70 00 69 00 70 00 65 00 5C 00 24 00 37 00 37 00 63 00 68 00 69 00 6C 00 64 00 70 00 72 00 6F 00 63 00 33 00 32 00 }
condition:
all of them
}
rule Windows_Rootkit_R77_4 {
meta:
author = "Elastic Security"
creation_date = "2023-05-18"
last_modified = "2023-05-18"
license = "Elastic License v2"
os = "Windows"
arch = "x86"
category_type = "Rootkit"
family = "R77"
threat_name = "Windows.Rootkit.R77"
reference_sample = "91c6e2621121a6871af091c52fafe41220ae12d6e47e52fd13a7b9edd8e31796"
strings:
$a = { 33 C9 48 89 8C 24 C0 00 00 00 4C 8B CB 48 89 8C 24 B8 00 00 00 45 33 C0 48 89 8C 24 B0 00 00 00 48 89 8C 24 A8 00 00 00 89 8C 24 A0 00 00 00 }
condition:
$a
}
rule Windows_Rootkit_R77_5 {
meta:
author = "Elastic Security"
creation_date = "2023-05-18"
last_modified = "2023-05-18"
license = "Elastic License v2"
os = "Windows"
arch = "x86"
category_type = "Rootkit"
family = "R77"
threat_name = "Windows.Rootkit.R77"
reference_sample = "916c805b0d512dd7bbd88f46632d66d9613de61691b4bd368e4b7cb1f0ac7f60"
strings:
$r77_str0 = "$77stager" wide fullword
$r77_str1 = "$77svc32" wide fullword
$r77_str2 = "$77svc64" wide fullword
$r77_str3 = "\\\\.\\pipe\\$77childproc64" wide fullword
$r77_str4 = "SOFTWARE\\$77config"
$obfuscate_ps = { 0F B7 04 4B 33 D2 C7 45 FC 34 00 00 00 F7 75 FC 66 8B 44 55 90 66 89 04 4B 41 3B CE }
$amsi_patch_ps = "[Runtime.InteropServices.Marshal]::Copy([Byte[]](0xb8,0x57,0,7,0x80,0xc3)" wide fullword
condition:
($obfuscate_ps and $amsi_patch_ps) or (all of ($r77_str*))
}
rule Windows_Rootkit_R77_6 {
meta:
author = "Elastic Security"
creation_date = "2023-05-18"
last_modified = "2023-05-18"
license = "Elastic License v2"
os = "Windows"
arch = "x86"
category_type = "Rootkit"
family = "R77"
threat_name = "Windows.Rootkit.R77"
reference_sample = "96849108e13172d14591169f8fdcbf8a8aa6be05b7b6ef396d65529eacc02d89"
strings:
$str0 = "service_names" wide fullword
$str1 = "process_names" wide fullword
$str2 = "tcp_local" wide fullword
$str3 = "tcp_remote" wide fullword
$str4 = "startup" wide fullword
$str5 = "ReflectiveDllMain" ascii fullword
$str6 = ".detourd" ascii fullword
$binary0 = { 48 8B 10 48 8B 0B E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 08 48 8B 4B 08 E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 10 48 8B 4B 10 E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 18 48 8B 4B 18 E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 20 48 8B 4B 20 E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 28 48 8B 4B 28 E8 ?? ?? ?? ?? 85 C0 }
$binary1 = { 8B 56 04 8B 4F 04 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 08 8B 4F 08 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 0C 8B 4F 0C E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 10 8B 4F 10 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 14 8B 4F 14 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 18 8B 4F 18 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 1C 8B 4F 1C }
condition:
(all of ($str*)) or $binary0 or $binary1
}
References
The following were referenced throughout the above research
- https://github.com/microsoft/Detours
- https://github.com/xmrig/xmrig
- https://ru.wikipedia.org/wiki/Remote_Manipulator_System
Observations
All observables are also available for download in both ECS and STIX format.
The following observables were discussed in this research.
Indicator | Type | Name | Reference |
---|---|---|---|
msupdate[.]info | Domain | n/a | C2 |
5.133.65.53 | IPV4 | n/a | C2 |
5.133.65.54 | IPV4 | n/a | C2 |
5.133.65.55 | IPV4 | n/a | C2 |
5.133.65.56 | IPV4 | n/a | C2 |
916c805b0d512dd7bbd88f46632d66d9613de61691b4bd368e4b7cb1f0ac7f60 | SHA-256 | $77_Install.exe | Installer module |
9fb38412cac94255a3abbec80f15620098a0c85247690850c302a9ff060b5c0c | SHA-256 | n/a | Stager module |
96849108e13172d14591169f8fdcbf8a8aa6be05b7b6ef396d65529eacc02d89 | SHA-256 | n/a | 64 bit core module |
aeb6a7b9ca890dc08259d7c239eb188e466210d48a17640671cba398bf69392f | SHA-256 | n/a | 32 bit core module |
91c6e2621121a6871af091c52fafe41220ae12d6e47e52fd13a7b9edd8e31796 | SHA-256 | n/a | 64 bit service module |
29bc88a316e3f34ed29c5358e459b9fbf3b7962a72cac388ab5c977dd990ea77 | SHA-256 | n/a | 32 bit Service module |
10165e27e0db0a6708f346ddea657ab0409499f93eb8426a80864a966f0f401e | SHA-256 | RMS.exe | Remote Manipulator System(RMS) |
757fa687a9b4d461ffda78d93e4d812003307a9b9747dce7fb469625429cc551 | SHA-256 | $77_oracle.exe | XMRIG miner |
a7e31abe10be6bca44f0a846d631e578efe78c14f6bf1cf834cfb15469fc1d3a | SHA-256 | $77_Loader.exe | .NET binary loading a PowerShell script |