Salim Bitam

Elastic 安全实验室深入分析 r77 rootkit

用于部署 XMRIG 加密货币矿机的开源用户层 rootkit。

阅读时长 23 分钟恶意软件分析
Elastic Security Labs steps through the r77 rootkit

要点总结

  • r77 是一款隐蔽的开源 rootkit,用于部署 XMRIG 加密货币矿机
  • r77 使用多个模块来成功安装并保持持久性
  • 攻击活动发起者大量依赖开源工具和脚本,可能是为了隐藏攻击来源或降低开发成本

前言

Elastic 安全实验室发现了一个恶意加密货币矿机,该矿机已在多个亚洲国家部署。该活动的所有者正在使用一个名为 r77 的开源用户层 rootkit。

r77 的主要目的是通过钩取重要的 Windows API 来隐藏系统上其他软件的存在,这使其成为网络犯罪分子进行隐蔽攻击的理想工具。通过利用 r77 rootkit,恶意加密货币矿机的作者得以躲避检测并继续其攻击活动而不被发现。

在本研究中,我们将重点介绍 r77 rootkit 的内部运作方式,并探讨其如何与加密货币矿机结合使用。我们希望提高人们对网络犯罪分子持续威胁的认识,并鼓励个人和组织采取积极措施来保护其系统和网络。

代码分析

概述

该 rootkit 由 4 个不同的模块组成

  1. 安装程序模块。
  2. 加载器模块。
  3. 服务模块。
  4. 核心模块。

我们将在下文中详细介绍每个模块和阶段。

安装程序模块

它的第一个任务是将加载器模块 PE 存储在注册表中,这是恶意软件作者常用的一种技术,用于在其系统上持久存储恶意代码。一旦加载器模块存储在注册表中,安装程序模块就会构建一个 PowerShell 命令,该命令从注册表中加载加载器模块并执行它,然后安装程序模块创建一个计划任务来运行该 PowerShell 命令。

安装程序查找存储为名为 EXE 的 PE 资源的加载器模块,然后在 HKEY_LOCAL_MACHINE\SOFTWARE 配置单元中创建一个名为 $77stager 的新注册表项,并将加载器模块写入该注册表项。

然后,安装程序构建一个 PowerShell 命令,使用 [Reflection.Assembly]::Load 方法以反射方式在内存中加载 .NET 加载器。此外,通过修补 AmsiScanBuffer API,使其始终返回一个 AMSI_RESULT_CLEAN 响应,从而绕过 Microsoft 的反恶意软件扫描接口 (AMSI)。AMSI_RESULT_CLEAN 表示扫描的内容为“已知良好”。未发现检测结果,并且结果在未来定义更新后可能不会更改。”然后,通过将变量名称替换为随机字符串来混淆 PowerShell 命令。

最后,安装程序创建一个计划任务,以使用 COM 对象执行 PowerShell 命令,该任务配置为使用 SYSTEM 帐户在启动时执行。

加载器模块

加载器是一个基于 .NET 的二进制文件,它负责取消钩取 DLL、调整 SeDebugPrivilege 设置、解密和解压服务模块,以及注入服务模块。这是通过 PPID 欺骗技术将进程挖空技术用于另一个合法进程下的新生成进程来实现的。

API 取消钩取

为了击败终端解决方案设置的用户层内联 API 钩取,加载器模块首先完全取消钩取包含 rootkit 使用的 API 的两个重要 DLL,即 NTDLL.dllKERNEL32.dll

此技术涉及以下步骤

  1. 检索 DLL:加载器模块从磁盘读取目标 DLL 文件。
  2. 将 DLL 映射到内存:加载器模块使用 CreateFileMapping 函数创建一个新的文件映射,这允许将 DLL 加载到进程的内存中。
  3. 分析 DLL 的节表:加载器模块分析新映射的 DLL 的节表,以识别存储可执行代码的相关节(通常称为 .text 节)。
  4. 覆盖代码节:一旦识别出 .text 节,加载器模块将已加载 DLL 中相应节的内容替换为来自新 .text 节的代码。

SeDebugPrivilege

接下来,加载器模块尝试获取 SeDebugPrivilege,这允许它检查和调整其他进程的内存。

此技术会触发 Elastic 的 可疑进程启用 SeDebugPrivilege 检测规则。

服务模块解密和解压缩

在加载器的资源部分中存储了同一服务模块的两个版本,一个 32 位版本和一个 64 位版本,将根据系统架构进行部署。

有效负载使用 GZip 压缩算法进行压缩,并使用简单的 XOR 进行解密。解压缩后,加载器使用前 4 个字节作为 XOR 密钥来解密剩余的数据。

父 PID 欺骗

为了使进程挖空注入看起来合法,使用了父 PID 欺骗技术来躲避威胁猎人和安全工具。此技术允许攻击者在他们想要的任何父进程下运行进程。

恶意软件首先获取正在运行的 winlogon.exe 进程的进程 ID,这是 Microsoft Windows 操作系统的一个组件。

然后它使用 5 个 Windows API

  1. OpenProcess:获取父进程句柄。
  2. InitializeProcThreadAttributeList:初始化属性列表。
  3. UpdateProcThreadAttribute:通过 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 属性设置父进程句柄。
  4. CreateProcess:在新欺骗的父进程下创建一个新进程

![父进程 PID 欺骗](/assets/images/elastic-security-labs-steps-through-the-r77-rootkit/image8.jpg

此技术会触发 Elastic 的 父进程 PID 欺骗 检测规则。

进程挖空

恶意软件利用进程挖空技术将其有效负载注入到看起来合法的 Microsoft 进程中,它根据恶意软件和计算机架构选择 C:\Windows\System32\dllhost.exeC:\Windows\SysWow64\dllhost.exe。为了进一步混淆其存在,恶意软件会生成一个随机 GUID 并生成一个命令行字符串,将其分配给新创建的进程。此命令行字符串包括 /processid: 参数和 GUID,以模仿真正的 dllhost.exe 进程的行为,并使其更难以检测。

![恶意软件执行进程挖空技术](/assets/images/elastic-security-labs-steps-through-the-r77-rootkit/image9.jpg

服务模块

服务模块是 r77 rootkit 的另一个基本组件,负责执行关键任务,例如在注册表中进行配置设置。服务模块的主要任务之一是将 rootkit 的核心注入到系统上运行的每个进程中。

取消钩取 DLL

使用与加载器中使用的相同技术,二进制文件取消钩取 NTDLL.dllKERNEL32.dll

配置设置

服务模块将配置存储为注册表项;它首先在 HKEY_LOCAL_MACHINE** SOFTWARE$77config** 文件中创建一个密钥,该密钥可由计算机上的任何用户修改。

然后,它会将运行服务模块的当前进程 ID 存储在注册表项 HKEY_LOCAL_MACHINE** SOFTWARE$77config\pid** 下名为 “svc32”“svc64” 的键值中。svc32/64 键的名称取决于系统架构。

注入核心 Rootkit

服务模块的最终任务是创建两个回调,负责注入最终的 Rootkit 核心。核心是一个 DLL,作为资源存储在每个正在运行的进程中,除了威胁行为者在编译 Rootkit 之前在配置中指定的一些进程。

第一个回调负责将 Rootkit 的核心注入到每个正在运行的进程中,它通过每 100 毫秒枚举所有正在运行的进程来实现。

第二个回调负责将核心注入到已感染父进程新创建的子进程中。服务和已感染进程之间使用进程间通信来捕获子进程的创建。

Rootkit 的核心会钩住多个 Windows API。其中一个重要的 API 是 NtResumeThread。父进程调用此 API 以在创建子进程后启动线程执行。安装的钩子通过命名管道将子进程的 PID 发送到服务模块,然后,如果条件允许,服务模块会将其注入到子进程中。

威胁行为者故意避免将代码注入到以下特定进程中:

  • MSBuild.exe
  • Services.exe
  • regsvr32.exe
  • Svchost.exe
  • WmiPrvSE.exe
  • OffOn.exe
  • OnOff.exe
  • rutserv.exe
  • rfusclient.exe
  • RMS.exe
  • msiexec.exe
  • Ma_ss.exe
  • masscan.exe
  • NLBrute.exe
  • run.exe
  • Checker.exe
  • Xfit.exe
  • cracker64.exe
  • SSH_Checker.exe
  • ViewLog.exe

Rootkit 的核心

最后一个模块是核心模块,负责在重要的 Windows API 上安装钩子,并根据 Rootkit 的配置过滤所述 API 的输出。它是一个 DLL,由服务模块加载到正在运行的进程中。它的主要目的是使用 Detours 项目在重要的 Windows API 上设置钩子,这些 API 包括:

  • NtQuerySystemInformation
  • NtResumeThread
  • NtQueryDirectoryFile
  • NtQueryDirectoryFileEx
  • NtEnumerateKey
  • NtEnumerateValueKey
  • EnumServiceGroupW
  • EnumServicesStatusExW
  • NtDeviceIoControlFile

![Hooking NT Windows APIs](/assets/images/elastic-security-labs-steps-through-the-r77-rootkit/image8.jpg

这些原生 Windows API 用于枚举/获取有关系统的信息。一个例子是 regedit,它严重依赖 NtEnumerateKeyNtEnumerateValueKey 来枚举系统的注册表项。安装的钩子能够枚举这些键,并过滤掉威胁行为者配置的键,其余的则转发到 regedit 进程。

通过过滤 Windows API 的输出,核心模块能够选择性地从系统用户和安全工具中隐藏特定的文件、进程或注册表项。

打包的 PowerShell

经过进一步检查,我们的团队在矿工活动中发现了一个额外的二进制文件:$77_loader.exe。此文件使用 SAPIEN PowerShell Studio 打包,是一个 .NET 二进制文件,它会加载嵌入的 PowerShell 脚本并执行它。此 PowerShell 脚本充当整个矿工活动的协调器,指导成功安装和运行合法且流行的加密货币矿工所需的各种流程和操作。PowerShell 脚本负责下载开源 XMRIG 矿工的编译版本。具体而言,此活动中使用的版本是 6.15.2,该版本于 2021 年 10 月发布。有趣的是,下载似乎来自域名 msupdate[.]info,这是一个有据可查的恶意域名。

![PowerShell 脚本尝试下载 XMRIG](/assets/images/elastic-security-labs-steps-through-the-r77-rootkit/image9.jpg

该脚本包含配置和执行 r77 rootkit 的代码,并负责打开特定的防火墙端口,包括 703708757999808044380144442444434444。该脚本还下载并设置了 远程操作系统 (RMS) 工具,这是一个由俄罗斯公司 TektonIT 开发的用于远程管理的闭源程序,可用于远程控制受感染的机器并从远程位置发出命令。最后,该脚本在目标系统上创建了一个新的管理员用户 (adm),这可能会被用来执行其他攻击或窃取敏感数据。

检测逻辑

预防

检测

YARA

Elastic Security 创建了 YARA 规则来识别此活动。以下是用于识别 r77 rootkit 的 YARA 规则。

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
}

参考

以下内容在上述研究中被引用

观察结果

所有可观察对象也可在 下载 中以 ECS 和 STIX 格式提供。

本研究中讨论了以下可观察对象。

指示器类型名称参考
msupdate[.]info域名不适用C2
5.133.65.53IPV4不适用C2
5.133.65.54IPV4不适用C2
5.133.65.55IPV4不适用C2
5.133.65.56IPV4不适用C2
916c805b0d512dd7bbd88f46632d66d9613de61691b4bd368e4b7cb1f0ac7f60SHA-256$77_Install.exe安装程序模块
9fb38412cac94255a3abbec80f15620098a0c85247690850c302a9ff060b5c0cSHA-256不适用暂存模块
96849108e13172d14591169f8fdcbf8a8aa6be05b7b6ef396d65529eacc02d89SHA-256不适用64 位核心模块
aeb6a7b9ca890dc08259d7c239eb188e466210d48a17640671cba398bf69392fSHA-256不适用32 位核心模块
91c6e2621121a6871af091c52fafe41220ae12d6e47e52fd13a7b9edd8e31796SHA-256不适用64 位服务模块
29bc88a316e3f34ed29c5358e459b9fbf3b7962a72cac388ab5c977dd990ea77SHA-256不适用32 位服务模块
10165e27e0db0a6708f346ddea657ab0409499f93eb8426a80864a966f0f401eSHA-256RMS.exe远程操作系统 (RMS)
757fa687a9b4d461ffda78d93e4d812003307a9b9747dce7fb469625429cc551SHA-256$77_oracle.exeXMRIG 矿工
a7e31abe10be6bca44f0a846d631e578efe78c14f6bf1cf834cfb15469fc1d3aSHA-256$77_Loader.exe加载 PowerShell 脚本的 .NET 二进制文件