早在2023年4月,就有研究人员详细介绍了一场针对macOS用户的复杂APT活动,该活动利用多阶段恶意软件,最终形成了能够在受感染的设备上下载和执行下一步恶意软件的Rust后门,将其称之为“RustBucket”。根据已有的证据,研究人员认为其幕后攻击者为朝鲜黑客组织“BlueNoroff”,“BlueNoroff”则通常被认为是Lazarus的分支。
今年5月,有机构发布了针对MacOS用户的第二个RustBucket变体的详细信息,随后在6月,又发现了第三个变体,其中包括新出现的持久化功能。
鉴于RustBucket所采取的反检测和反分析措施,需要我们进一步提高警惕,进行必要地防范。因此,本期《铭说》将带您解析以上攻击活动中使用的恶意软件有效载荷,并对RustBucket在部署过程中所采取的逃避检测和分析的方法进行剖析。
第一阶段 | AppleScript Dropper
攻击从伪装成PDF查看软件的Applet开始,Applet只是以某种格式保存的已编译的AppleScript.app。与常规MacOS应用程序不同,Applet通常缺乏用户界面,只作为开发人员向用户分发AppleScript的便捷方式。
图注:第一阶段执行三个“do shell script”命令来设置第二阶段
该脚本名为Internal PDF Viewer,包含三个“do shell script”命令,用于下载并执行下一阶段。将第二阶段写入该/Users/Shared/文件夹,由于该文件夹不需要权限,因此恶意软件无需绕过TCC即可访问。
第一阶段是整个攻击链中较为简单且容易被检测到的部分,“do shell script”会出现在MacOS的统一日志中,并作为命令行工具(例如ps实用程序)的输出。
第一阶段的成功与否在很大程度上取决于威胁行为发起者的诱导欺骗手段,通过其策划的诡计,利用伪装的PDF阅读器读取“受保护”文档,使受害者在被诱导执行第一阶段时,相信它能够帮助阅读PDF文件。事实上,第一阶段只是一个植入程序,旨在为第二阶段的执行提供基础。
第二阶段 |用Swift和Objective-C编写有效负载
我们发现第二阶段存在许多不同的有效负载,有一些是使用Swift编写,而另一些则是用 Objective-C编写,都是针对Intel和Apple 芯片架构编译而成的。第二阶段示例的大小和代码构件各不相同。
图注:RustBucket 第二阶段不同的样本
在这些示例中,可以找到各种用户名的字符串,目前在第二阶段二进制文件中观察到的内容包括:
尽管在大小和代码构件方面存在差异,但是第二阶段的有效负载都具有从命令和控制服务器检索第三阶段的任务。第二阶段的有效负载需要一个特制的PDF来解锁代码,从而下载第三阶段,并提供一个异或密钥来解码附加在PDF末尾的混淆C2。
在一些变体中,这些数据是在之前的研究人员所描述的downAndExecute函数中执行的,在其他情况下,可以注意到下一阶段的下载是在名为down_update_run的函数中执行。该函数本身因样本而异。例如,在b02922869e86ad06ff6380e8ec0be8db38f5002b中,它通过system()来运行硬编码命令。
图注:第二阶段通过system()调用执行 shell 命令来检索并运行第三阶段
然而,其他样本中的相同函数(例如,d5971e8a3e8577dbb6f5a9aad248c842a33e7a26)则使用NSURL API,存在完全不同的逻辑。
图注:示例中的代码差异很大,可能表明不同的开发人员
在用 Swift 编写的第二阶段的一个较新的变体中,User-Agent 字符串全部为小写,而在早期的Objective-C 示例中则不是。
图注:User-Agent从第二阶段的Objective-C版本更改为Swift版本
尽管User-Agent字符串本身不区分大小写,但如果这是一个有意的更改,则攻击者可能正在服务器端解析User-Agent字符串,以排除对C2的不必要调用。也就是说,在RustBucket样本的其他地方(例如,阶段1中的“/users/shared”)存在大小写方面的粗心,并且大小写差异可能是不同开发人员使用不同标准的结果。
在最新的样本中,第二阶段检索到的有效负载在受害者设备上执行之前会以“ErrorCheck.zip”的形式写入磁盘_CS_DARWIN_USER_TEMP(通常称为 $TMPDIRat /var/folders/…/../T/)。
第三阶段 | 新变体释放持久性 LaunchAgent
到目前为止,第三阶段的有效载荷有两种不同的变体:
A:182760chbe11fa0316abfb8b7b00b63f83159f5aa 第三阶段;
B:b74702c9b82f23ebf76805f1853bc72236bee57c 错误检查, 系统更新。
这两个变体都是从Rust源代码编译的Mach-O 通用二进制文件。在体积上,变体A比B大得多,前者的通用二进制文件大小为11.84MB,而后者为8.12MB。精简后的新变体导入的crate变少,并且更少使用两者中的sysinfo crate。值得注意的是,变体B取消了变体A中用于收集环境信息和通过查询system_profiler的SPHardwareDataType值来检查虚拟机中的执行情况的webT类。
图注:webT类出现在第三阶段有效负载的变体 A中
然而,变体B并没有清除代码中所有的webT构件,对缺失模块的引用仍然可以在字符串中找到。
图注:在第三阶段的变体B中仍然可以找到webT模块的字符串
子字符串"Trojan"没有出现在早期的变体中,也在同一字符串引用的文件路径中被找到。
而且变体B包含了一个在早期版本的RustBucket中不存在的持久机制。它采用硬编码LaunchAgent的形式,被写入磁盘~ /图书馆/ LaunchAgents/ com.apple.systemupdate.plist。ErrorCheck文件也将自己的副本写入~/Library/Metadata/System Update,并作为LaunchAgent的目标可执行文件。
因为第三阶段需要一个URL作为启动参数,所以在属性列表中作为Program Argument提供。让人感到困惑的是,在启动时传递给ErrorCheck的URL被附加到LaunchAgent plist中的这个硬编码URL。
图注:RustBucket LaunchAgent将硬编码的URL与启动时提供的URL连接起来
在代码中可以清楚地看到将提供的值附加到硬编码的URL上。
在变种A的webT方法中发现的许多恶意软件功能,隐藏在变种B的symm . updator::main函数中。它负责监视环境并解析启动时接收到的参数、处理命令等。这个庞大的函数超过22KB,包含501个基本块。研究人员正在对此进行分析,但除了前面描述的功能之外,该功能还收集磁盘信息,包括主机设备的磁盘是SSD还是机械硬盘。
图注:updator::main的众多任务之一是收集磁盘信息
在收集环境信息后,恶意软件调用symm . updator::send_request,使用以下User-Agent字符串(这次不是小写)将数据发布到C2:
恶意软件将比较两个硬编码值0x31和0x30的响应结果。
图注:检查C2的响应值
在分析的样本中, Ox31导致恶意软件自动终止,而0x30则允许操作者在_cs_darwin_user_temp目录中进一步删除有效载荷。
Rust的选择和第三阶段二进制文件的复杂性表明,威胁参与者投入了大量精力来阻止对有效负载的分析。由于已知的C2在进行分析时没有响应,因此无法获得恶意软件下一阶段的样本,但在操作时,恶意软件已经收集了大量的主机信息,并为进一步的恶意活动打开了后门。
结论
RustBucket活动说明,攻击者(之前的研究人员将其归于朝鲜的BlueNoroff APT)已经投入了大量资源,专门针对macOS用户开发了多阶段攻击,并不断尝试改进,以阻止安全人员进行分析。