macOS.ZuRu 恶意软件重现 | 修改版 Khepri C2 隐藏在篡改的 Termius 应用中

本文详细分析了macOS.ZuRu恶意软件的最新变种,包括其通过篡改Termius应用分发、使用修改版Khepri C2框架进行通信的技术细节,以及持久化机制和检测方法。

macOS.ZuRu 重现 | 修改版 Khepri C2 隐藏在篡改的 Termius 应用中

2025年7月10日
作者:Phil Stokes & Dinesh Devadoss

macOS.ZuRu 是一个后门程序,最初于2021年7月由一位中国博主发现,通过百度搜索结果中的恶意链接分发。用户搜索流行的终端模拟器 iTerm2 时,会被重定向到一个托管特洛伊木马化版本应用的恶意网站。随后的 ZuRu 变种使用了相同的模式,针对其他流行的 macOS 工具(包括 SecureCRT、Navicat 和 Microsoft 的 Remote Desktop for Mac)在百度搜索结果中投毒。这些被篡改的应用选择表明,恶意软件作者的目标是使用 SSH 和其他远程连接工具的后端工具用户。

2024年1月,JAMF 的研究人员发现了使用类似技术指标的盗版 macOS 应用,但现在利用开源的 Khepri C2 框架进行感染后操作。2025年5月下旬,一个特洛伊木马化跨平台 SSH 客户端和服务器管理工具 Termius 的新样本在社交媒体上曝光。

这个最新样本使用了一种新方法来特洛伊木马化合法应用,以及一个修改版的 Khepri 信标。在本文中,我们提供了这个恶意软件最新版本的技术分析,以及新的技术指标,以帮助检测工程师和威胁猎人。

特洛伊木马化应用包

恶意软件通过 .dmg 磁盘映像分发,包含一个被篡改的正版 Termius.app。正版 Termius 的磁盘映像大小约为225MB,而特洛伊木马化版本由于添加了恶意二进制文件,略大为248MB。

正版 Termius(上)和特洛伊木马(下)带有两个额外的二进制文件

由于磁盘映像中的应用包已被修改,攻击者用自己的临时签名替换了开发者的代码签名,以通过 macOS 代码签名规则。

除了修改签名外,特洛伊木马还在嵌入的 Termius Helper.app 中添加了两个可执行文件。正版 Termius Helper 二进制文件(约248KB)被替换并重命名为 .Termius Helper1。执行时,植入的 Termius Helper 二进制文件(一个巨大的25MB Mach-O)会启动恶意软件加载器 .localized 和 .Termius Helper1,以确保父应用按用户预期运行。在后台,.localized 从 download.termius[.]info 下载另一个二进制文件,并将其写入 /tmp/.fseventsd。这个下载是一个 Khepri C2 信标。

虽然 Khepri 的使用在早期版本的 ZuRu 中已经出现,但这种特洛伊木马化合法应用的方法与威胁行为者之前的技术不同。在旧版本的 ZuRu 中,恶意软件作者通过添加一个引用外部 .dylib 的额外加载命令来修改主包的可执行文件,动态库作为 Khepri 后门和持久化模块的加载器。

通过 LaunchDaemon 持久化

执行时,.localized 二进制文件连接到 download.termius[.]info 并向用户请求提升权限。如果权限被授予,它会将一个持久化 plist 文件(标签为 com.apple.xssooxxagent)写入域级文件夹 /Library/LaunchDaemons/。

持久化模块硬编码在 .localized 二进制文件中,旨在每小时执行一次位于 /Users/Shared/com.apple.xssooxxagent 的 .localized 副本。

macOS.ZuRu 丢弃的恶意 LaunchDaemon

为了管理写入磁盘后的恶意守护进程,.localized 使用函数 _writePlistAndStartDaemon() 执行以下命令:

1
2
3
launchctl bootout system/com.apple.xssooxxagent;
launchctl bootstrap system/com.apple.xssooxxagent;
sleep 1

恶意软件还使用 Security 框架的已弃用 API AuthorizationExecuteWithPrivileges 来请求持久化模块的权限。

请求提升权限的伪代码使用已弃用的 API

函数 _copySelfToShare() 使用 [NSBundle mainBundle].executablePath 获取当前可执行文件的路径,并检查是否包含字符串 /Users/Shared/。如果不包含,它将自身复制到 /Users/Shared/com.apple.xssooxxagent,首先删除可能已存在于该路径的任何文件。

.localized 的 _copySelfToShare() 函数

.localized 加载器和 md5 更新机制

除了安装持久化,加载器还执行一些检查和安装任务。

.localized 的主要任务是设置和安装恶意软件组件

函数 _LockManager() 通过将锁文件写入 /tmp/apple-local-ipc.sock.lock 来确保只有一个恶意软件实例在运行。尽管名称如此,锁文件与 IPC 或套接字无关。_LockManager() 使用 flock 获取文件的独占锁,如果另一个进程已经持有锁,则退出。如果文件锁成功,恶意软件会将自己的 PID 写入文件。

_LockManager 函数确保只有一个恶意软件实例在运行

函数 _checkFileAndDownloadIfNeeded() 下载、验证并执行第二阶段有效负载。它首先检查有效负载是否已存在于 /tmp/.fseventsd。如果不存在,它从 C2 的 http[:]//download.termius[.]info/bn.log.enc 获取有效负载,使用硬编码密钥 my_secret_key 解密。我们注意到这个 URL 模式与早期版本的 ZuRu 非常相似,例如 hxxp://download[.]finalshell[.]cc/bd.log。

如果文件存在,该函数计算其 md5 哈希值,并与通过调用 http[:]//download.termius[.]info/bn.log.md5 远程接收的值进行比对。如果值不匹配,则从 C2 下载新版本的文件。这很可能是一个更新机制,允许恶意软件检查是否有更新或不同版本的有效负载可从 C2 获取,但它也可能用于确保有效负载未被损坏或篡改。

有趣的是,我们在这个二进制文件中看到一些可能表明恶意软件源代码是从早期活动中重用或至少有过早期开发的痕迹。例如,函数 _startBackgroundProcess() 在代码中未被调用,并且与 _runfile(_maziFilePath) 函数功能几乎相同。后者由 _main 调用,接受文件路径参数 /tmp/.fseventsd,然后分叉并执行有效负载。_startBackgroundProcess() 函数做类似的事情,但它不接受参数,而是将文件路径 /tmp/check_id 硬编码到其他相同的函数体中。这个文件路径在执行恶意软件时未被使用,并且除了冗余的 _startBackgroundProcess() 函数外,似乎没有其他交叉引用。

类似地,代码包含一个早期版本的 _writePlistAndStartDaemon() 函数,称为 _startLaunchDaemon。后一个函数从未被调用,并使用 kickstart 参数而不是 launchctl 的 bootout/bootstrap 参数,如我们在前一节中所述。

修改的 ZuRu 有效负载解密例程

我们注意到早期版本的 ZuRu 使用了自定义 XOR 例程。JAMF 研究人员描述了一个函数:

“接受一个编码字节,应用 XOR 和减法操作与 XOR 密钥 0x7a 的组合,并产生一个解密字节。XOR 和减法的使用使加密比简单的 XOR 密码稍微复杂。与 0xff 的掩码确保所有操作保持在字节的有效范围内,考虑了减法期间的任何下溢。”

在我们分析的新版本中,解密仍然使用 XOR 并结合加法和减法。然而,单字节 XOR 密钥 0x7a 已被密钥字符串 my_secret_key 替换。解密函数 _decryptData() 迭代输入数据的每个字节,并按顺序应用四个操作。

.localized 中的 _decryptData() 函数

首先,它通过从密钥中取一个字节,依次循环 my_secret_key 的13个字节,并执行模3操作,向输入添加一个字节。这确保了要添加的字节有效地为0、1或2。接下来,为了确保结果保持在0-255的有效范围内(即可以存储为单个字节),它添加 0x100(256),然后再次除以 0x100 取余数。第三步根据字节在数据中的位置减去0、1或2(再次模3)。最后,它与原始密钥字节进行 XOR 操作。我们可以用伪代码更简单地表示逻辑如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
for (i = 0; i < inputLength; i++) {
    byte = input[i];
    // 步骤1:从密钥添加一个伪随机字节
    byte += key[i % keyLength] % 3;
    // 步骤2:用模256归一化
    byte = (byte + 0x100) % 0x100;
    // 步骤3:基于 i % 3 减去偏移量
    byte -= (i % 3);
    // 步骤4:再次与相同的密钥字节 XOR
    byte ^= key[i % keyLength];
    output[i] = byte;
}

XOR 例程的对称性确保相同的代码可用于编码和解码传输的数据。然而,像这样的自创例程不提供真正的加密,主要用于混淆自动化分析和检测引擎的数据。

修改的 Khepri 命令与控制植入

从 C2 获取的有效负载是一个约174KB的通用 Mach-O,携带一个标识为 beacon_arm64_x86_64 的临时签名。可执行文件需要 Sonoma 14.1(2023年10月发布)或更高版本,表明攻击者不期望其目标用户运行旧版本的 macOS。

有效负载是一个修改的 Khepri C2 信标,首次于2024年12月5日在 VirusTotal 上出现。嵌入的字符串表明,托管在 GitHub 上的原始开源版本 Khepri 已被定制用于 Termius 特洛伊木马。

Khepri 是一个全功能的 C2 植入,具有以下能力:

  • 文件传输
  • 系统侦察
  • 进程执行和控制
  • 命令执行与输出捕获

Khepri C2 任务列表

信标可以以 -s 或 -bd 作为标志启动,或者都不使用。如果未使用 -s,代码尝试获取 /tmp/my_unique_process.lock 文件的锁。如果锁失败,信标退出;否则,它查找 -bd 标志。如果在启动时提供了 -bd,信标调用 runInBackground() 函数将进程守护进程化。如果使用了 -s,信标跳过检查锁文件并继续检查 -bd。

Khepri 信标可以在“跳过”模式或“后台守护进程”模式下运行,或两者兼有

信标设置了一个恒定的5秒心跳间隔,比开源版本中的10秒默认值稍快,并将 C2 设置为端口53,一个常用于 DNS 的端口。它使用合法域名 www.baidu[.]com 作为诱饵,而实际上连接到 ctl01.termius[.]fun。C2 解析到阿里云 IP 47[.]238.28[.]21,遵循早期 ZuRu 恶意软件工件的模式,特别是 ctl01.macnavicat[.]com,解析到 47[.]242.144[.]113,并在2024年被先前研究人员报告。

SentinelOne Singularity 检测 macOS.ZuRu

SentinelOne Singularity 检测并保护 against macOS.ZuRu。当启用 Protect 策略时,所有恶意组件都被阻止在设备上执行。如果策略设置为 Detect,SentinelOne Singularity 检测 macOS.ZuRu 尝试安装持久化并立即终止所有相关进程并隔离其恶意组件。

结论

macOS.ZuRu 的最新变种继续了威胁行为者特洛伊木马化开发者和 IT 专业人员使用的合法 macOS 应用的模式。从 Dylib 注入到特洛伊木马化嵌入式助手应用的技术转变可能是为了规避某些类型的检测逻辑。即便如此,行为者继续使用某些 TTPs——从目标应用的选择和域名模式到文件名、持久化和信标方法的重复使用——表明这些在缺乏足够端点保护的环境中继续取得成功。

SentinelOne 客户受到保护,免受 macOS.ZuRu 的侵害;没有这种保护的组织建议查看下面提供的指标和上面呈现的技术细节。

入侵指标

文件路径

  • /Library/LaunchDaemons/com.apple.xssooxxagent.plist
  • /Users/Shared/com.apple.xssooxxagent
  • /private/tmp/Termius
  • /tmp/.fseventsd
  • /tmp/apple-local-ipc.sock.lock

文件

SHA-1 名称 描述
a7a9b0f8cc1c89f5c195af74ce3add74733b15c0 .fseventsd Khepri C2 信标
ace81626924c34dfbcd9a485437cbb604e184426 Termius Helper 特洛伊木马 Mach-O
de8aca685871ade8a75e4614ada219025e2d6fd7 Termius9.5.0.dmg 特洛伊木马磁盘映像
fa9b89d4eb4d47d34f0f366750d55603813097c1 .localized, Termius, com.apple.xssooxxagent 恶意软件加载器

网络通信

  • http[:]//download.termius[.]info/bn.log.enc
  • http[:]//download.termius[.]info/bn.log.md5
  • ctl01.termius[.]fun
  • 47[.]238.28[.]21
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计