“无文件”恶意软件的最新藏匿处

 人参与 | 时间:2025-11-26 22:49:32

在2022年2月,无文件卡巴斯基实验室的恶意研究人员首次观察到将shellcode放入Windows事件日志的技术 。该技术允许在文件系统中隐藏“无文件”最后stager的软件木马 。这种对活动中事件日志的新藏关注不仅限于存储 shellcode 。 Dropper 模块还修复了与事件跟踪 (ETW) 和反恶意软件扫描接口 (AMSI) 相关的匿处 Windows 原生 API 函数,以使感染过程更加隐蔽 。无文件

除了事件日志之外,恶意攻击者的软件工具集中还有许多其他技术 。其中 ,新藏开发者在功能中增加了侦察,匿处可以模仿合法域名的香港云服务器无文件 C2 Web 域名 ,以及受害者使用的恶意现有和软件的名称 。为了使攻击更加隐蔽 ,软件攻击者使用 Linode 、新藏Namecheap、匿处DreamVPS 上的虚拟专用服务器。

一种更常见的方法是使用大量的反检测解密器。攻击者使用不同的编译器,从微软的建站模板 cl.exe 或 MinGW 下的 GCC 到最新版本的 Go 。此外,为避免被检测到 ,某些模块使用数字证书进行签名 。研究人员认为它是由攻击者发布的,因为遥测数据没有显示任何与之签名的合法软件,只有这次活动中使用的恶意代码。

关于最后stager的特洛伊木马,攻击者决定使用多个基于 HTTP 和命名管道。模板下载显然,除了事件日志之外 ,攻击者还痴迷于内存注入 ,许多 RAT 命令与它相关并且被大量使用 。除了上述自定义模块和技术外,攻击者还使用了一些商业渗透测试工具,如 Cobalt Strike 和 SilentBreak 的工具集。

感染链

研究人员从内存中的最后一个stager开始研究,然后使用遥测技术,重建了几个感染链 ,该活动的针对性很强 ,且使用的大量工具还包括商业工具。高防服务器

该活动包括各种技术和模块 ,让我们把它分成几类来从技术上描述这个活动 ,比如商业渗透测试套件、围绕它们的自定义反检测包装器和最后stager的木马 。

商业工具集有 :

反检测包装器——大量使用系统调用库的Go 解密器 ,这可以使Cobalt Strike 模块多次编码  ,并使用 AES256 CBC 加密 blob,这是首次观察到 拥有Cobalt Strike 的Go的使用情况。反检测包装器——一个库启动器,在 MinGW 环境下使用 GCC 编译 。云计算这个stager唯一可能的原因是反检测。反检测包装器——AES 解密器,使用 Visual Studio 编译器编译;最后stager RAT—— 基于 HTTP 的木马 ,可能的原始名称是 ThrowbackDLL.dll 和 drxDLL.dll ,但代码比 SilentBreak 的 Throwback 的旧版本更复杂。最后stager RAT—— 基于管道的命名木马 ,可能的原始名称是服务器租用 monolithDLL.dll 和 SlingshotDLL.dll。根据文件名 ,最后stager模块可能是商业 Slingshot 版本的一部分。

同样 ,我们认为定制的一些模块(如包装器和最后stager)可能是商业产品的一部分。分类之后 ,我们准备一个一个地分析模块。

初始感染

我们观察到的最早攻击stager发生在 2021 年 9 月。Cobalt Strike 模块的传播是通过说服目标下载合法站点 file.io 上的 .rar 链接并自行运行来实现的 。内部 Cobalt Strike 模块的数字证书如下(在使用相同的活动期间,从 wrapper 到 last stagers 签署了 15 个不同的 stager):

由于所有目标主机的感染情况不同,我们将仅描述观察到的一种情况 。由于能够使用木马将代码注入任何进程,攻击者可以自由地广泛使用此功能将下一个模块注入 Windows 系统进程或受信任的应用程序(如 DLP) 。

记住截断的进程注入 ,甚至模仿 Web 域注册 ,我们可以将攻击过程描述为非常迭代(quite iterative) :对一些模块进行初始侦察 ,然后准备额外的攻击 。

商业工具集

关于商业工具,这次活动中使用 SilentBreak 和 Cobalt Strike 工具集的痕迹非常明显 。名为 ThrowbackDLL.dll 和 SlingshotDLL.dll 的木马让我们想起 Throwback 和 Slingshot ,它们都是 SilentBreak 框架中的工具 ,而与 dropper (sb.dll) 关联的“sb”可能是供应商名称的缩写。

这里我们要提一下,二进制文件中的几个 .pdb 路径包含项目的目录 C:\Users\admin\source\repos\drx\ 以及其他未以 Throwback 或 Slingshot 命名的模块 ,例如 drxDLL.dll 。但是 ,加密函数与公开可用的 Throwback 代码中的相同。

反检测设计

对于反检测包装器,使用了不同的编译器  。除了 MSVC ,Go 编译器 1.17.2 和 MinGW 下的 GCC 都在使用  。解密器差异很大 ,它们包含的功能如下表所示 :

几个编译器——可以使用 Go 和 C++ 模块完成相同的 AES256 CBC 解密;列入白名单的启动器——WerFault.exe 的自动运行副本将启动器映射到进程地址空间;数字证书 ——15 个文件使用“Fast Invest” 证书签名  ,我们没有观察到任何用它签名的合法文件修复 ntdll.dll 的日志记录导出——为了更加隐蔽 ,Go dropper 将与日志记录相关的 API 函数(如 EtwEventWriteFull)修复到具有空功能的自地址空间中;在事件日志中保留 shellcode——这是攻击者的主要创新,使用 next stager 加密的 shellcode 被分成 8 KB 的block并保存在事件日志的二进制部分中;C2 网络域名模仿——攻击者在使用标题中 ,注册了一个ERP网络域名;

这层感染链解密、映射到内存并启动代码  。本文我们将仅介绍 Cobalt Strike 的 Go 解密启动器。

主包中的函数名称被混淆了  ,Main.init 从与事件日志创建相关的 kernel32.dll 和 ntdll.dll 库(WriteProcessMemory 和其他函数)中解码 Windows API 函数名称。二进制文件中的每个名称都连续四次使用 base64 编码 。使用 WriteProcessMemory ,拥有“xor rax, rax; ret”的dropper在内存中编码以下函数 :EtwNotificationRegister、EtwEventRegister、EtwEventWriteFull、EtwEventWriteFull、EtwEventWrite 。

在 Main.start 中 ,恶意软件会检查主机是否在域中 ,并且只有在它为真时才起作用。然后动态解析上述函数的地址。下一个stager使用 AES256(CBC 模式)加密,密钥和 IV 使用 base64 编码。

使用这种方法,研究人员需要编写一些脚本来收集下一个模块的加密部分。解密后 ,要获得最终的可移植可执行文件,还需进一步转换数据 。

最后stager类型

Last stager 有两种通信机制——使用RC4加密的HTTP通信机制和使用命名管道的非加密通信机制。后一种方式在技术上能够与任何网络可见的外部主机通信,但在Windows环境中,命名管道是建立在SMB协议之上的,它几乎不会对外部网络开放 。所以这些模块很可能用于横向移动 。

在对恶意软件集进行了介绍之后  ,我们现在将描述感染链,研究人员使用 Cobalt Strike 渗透测试套件进行Dropper注入。

用DLL中的Dropper实现order劫持

研究人员从 wrapper-dropper 动态库开始自定义模块分析。此代码被注入到诸如 explorer.exe 之类的 Windows 进程中 。在加载到启动程序进程的虚拟地址空间后 ,在其单个入口点 ,dropper 删除由先前stager或执行创建的文件。

首先,该模块将原始合法的操作系统错误处理程序 WerFault.exe 复制到 C:\Windows\Tasks 。然后,它将一个加密的二进制资源放置到同一目录中的wer.dll文件中,以进行典型的DLL order劫持 。为了持久化 ,该模块将新创建的WerFault.exe设置为自动运行 ,在Software Microsoft\Windows\CurrentVersion\Run Windows系统注册分支中创建一个Windows问题报告值。

dropper 不仅将启动器放在磁盘上进行侧载,而且还会将带有 shellcode 的信息消息写入现有的 Windows KMS 事件日志 。

被删除的wer.dll是一个加载器 ,如果没有隐藏在Windows事件日志中的shellcode ,它不会造成任何伤害  。dropper在事件日志中搜索类别为 0x4142(ASCII 中的“AB”)并以密钥管理服务作为源的记录。如果没有找到,则通过 ReportEvent() Windows API 函数(lpRawData 参数)将 8KB 的 shellcode 块写入信息记录消息。从 1423 开始 ,创建的事件 ID 会自动递增 。

wer.dll 中的启动器

这个启动器 ,被第一个stager放到 Tasks 目录中 ,它代理所有对wer.dll的调用,并将其导出到原始合法库。在入口点,一个单独的线程将所有上述 8KB 片段组合成一个完整的 shellcode 并运行它 。由合法 WerFault.exe 的副本创建的相同虚拟地址空间用于所有这些代码 。

为了防止 WerFault 继续其错误处理过程 ,DLL 使用典型的 Blackbone trampoline修复启动器的入口点

阻止合法启动器执行的方法很新颖。在主线程中 ,wer.dll 找到它的入口点并用一个简单的函数对其进行修复。上面屏幕截图中的 WaitAndExit() 只会使用日志收集线程 ID 调用 WaitForSingleObject() ,然后退出,这意味着永远不会执行真正的 WerFault.exe 错误处理代码:映射到其地址空间的欺骗性 DLL 会阻止它。

Windows 事件日志中的Shellcode

启动器将控制传输到收集的 shellcode 的第一个字节 。在本文中 ,研究人员为下一个函数准备了三个参数 :

下一个stager木马的地址,它也包含在从事件日志中提取的数据中;导出函数名称的标准 ROR13 哈希在此木马中加载 (0xE124D840);字符串“dave”和常量“4”的地址 ,它们成为导出函数的参数  ,可以通过哈希找到;

解析下一个 Windows 可移植可执行文件以定位其入口点的做法是非常典型的 。为了让下一个stager的木马不那么显眼 ,攻击者清除了标题中的“MZ”魔法 。在木马的入口点调用代码后 ,shellcode 还会搜索请求导出并调用它。

除了搜索入口点并调用它,shellcode 还通过硬编码哈希搜索木马导出 ,并使用参数“dave”和“4”运行找到的函数

HTTP木马

相比之前的辅助模块,对于最后一个stager ,我们会介绍的更详细一些。 C++ 模块显然使用了 SilentBreak(现为 NetSPI)的 Throwback 公共存储库中的代码:基于 XOR 的加密函数 ,一些示例的原始文件名 ,例如 ThrowbackDLL.dll 等。让我们从前面提到的Load()导出函数开始  。这就像上面的WerFault补丁(函数在主木马线程上等待),但是它忽略了任何参数,所以“dave”和“4”没有被使用。这个启动器可能支持比这个更多的模块 。

目标搜索

该模块使用单字节 XOR 密钥解密 C2 域 ,在此示例中,只有一个域 eleed[.]online 。该木马能够处理其中的许多,以“|”字符分隔并加密。为了进一步通过普通HTTP进行通信 ,木马从用户代理“Mozilla 5.0”的集合中随机选择一个C2。

该恶意软件通过收集以下信息生成一个追踪字符串 ,也用“|”分隔 :

SOFTWARE\Microsoft\Cryptography 中 MachineGUID 的值;计算机名称;使用 GetAdaptersInfo 获取的本地 IP 地址;架构(x86 或 x64);操作系统版本;当前进程是否有SeDebugPrivilege;

追踪识别器还将“1.1”附加到字符串(可能是恶意软件版本)和当前配置的睡眠时间。

与C2进行加密的HTTP通信

在HTTP通信之前  ,该模块使用硬编码的32字节长的RC4密钥发送空(但仍然加密)的ICMP数据包来检查连接 。与任何其他字符串一样 ,此密钥使用基于Throwback xor的算法加密。

如果ping端口为80的控制服务器成功 ,则将上述追踪数据发送到该控制服务器 。作为回应 ,C2共享木马主循环的加密命令。

木马命令

代码的命令功能:

0——再次对目标进行追踪识别;1——执行命令 ,木马在新进程中执行接收到的命令并将结果发送回C2;2——从 URL 下载并保存到给定路径;3——设置新的睡眠时间 ,如果 C2 尚未响应要执行的命令 ,则将此时间(以分钟为单位)用作超时 。随机化公式为(0,9 - 1,1之间的随机数)*睡眠时间;4——在不改变配置的情况下休眠指定的分钟数。5——列出具有 PID 、路径、所有者、名称和父数据的进程;6——将 shellcode 注入并运行到目标进程的地址空间 。要注入同一个进程 ,命令参数应该是“local”。与事件日志中的 shellcode 一样,该代码将运行提供的 PE 的入口点以及通过哈希找到的特定导出。99——终止木马和C2之间的会话。

本次活动中使用的另一个木马是基于管道命名的,这样命令系统更有意义,包括特权升级、截图、非活动时间测量等 。继续使用另一种最后stager的木马类型 ,发现它被注入到了像edge.exe这样的进程中 。

基于管道命名的木马

木马的位置是 C:\Windows\apds.dll ,具有相同名称的原始合法 Microsoft 帮助数据服务模块库位于 C:\Windows\System32 中 。木马的主要工作周期是在一个单独的线程。该恶意软件还导出一个Load()函数 ,其唯一目的是等待一个工作线程,这是该活动的模块的典型 。

首先,木马主线程获取原始apds.dll并导出,并将其保存到内存中木马映像之后的一个已分配的新堆缓冲区中 。然后 ,木马会编辑自己导出的函数数据,这样它就可以通过如下精心制作的存根调用原始的apds.dll导出,其中的地址就是从真正的apds.dll解析出来的地址 :

这个trampoline代码取自Blackbone Windows内存黑客库(remotemmemory::BuildTrampoline函数)。DLL劫持并不是什么新鲜事,我们已经多次看到这种技术被用于代理合法函数,但仅用短存根重新创建自导出来调用原始合法函数却很不寻常。然后,该模块创建一个双工命名的管道“MonolithPipe”,并进入它的主循环 。

工作周期

在对导出函数进行上述操作后 ,该模块会轻微地使用架构和 Windows 版本信息对主机进行追踪识别。木马还使用提到的稀有常量初始化一个随机的 11 字节 ASCII 字符串 ,例如这里的 init_keys 函数  。结果用作唯一的会话 ID。

恶意软件连接到端口 443 上的硬编码域(在本例中为 https://opswat[.]info:443) ,并向 C2 端的 submit.php 发送 POST 请求 。 HTTPS 连接选项设置为接受服务器端的自签名证书。在本例中,C2通信使用Dhga(81K1!392-!(43<KakjaiPA8$#ja密钥的RC4算法加密。对于基于管道命名的木马 ,常用的命令有:

0——将“continue”标志设置为 False 并停止工作;1—— N/A,保留至今;2——获取自上次用户输入以来的时间(以分钟为单位);3——获取当前进程信息 :PID 、架构、用户、路径等;4——获取主机域和用户帐户;5——使用提供的凭据模拟用户;6——获取当前进程的可用权限;7——使用 cmd.exe 解释器执行命令;8——使用与给定主机(地址和端口)的原始 TCP 套接字测试的连接;9——获取正在运行的进程信息  :路径 、所有者、名称 、父进程 、PID等;10——使用提供的 ID 的进程令牌模拟用户;11——列出目录中的文件;12——截取屏幕截图;13——将内容写入文件;14——读取文件内容;15——删除文件;16——将提供的代码注入到具有给定名称的进程中 。17——在C2上运行shellcode;

研究人员现在已经介绍了该活动的三个层面,有趣的是,研究人员观察到一个木马具有如上表所示的完整命令集 ,但仍然使用rc4加密的HTTP与C2通信,而不是指定管道 。最后一个stager的示例看起来像一个模块化的平台,攻击者能够根据他们当前的需要组合其功能。

基础设施

研究人员认为这些代码是自定义的(木马 、包装器),与以前已知的活动或以前注册的SilentBreak工具集模块没有相似之处 。现在研究人员不愿意给这个活动命名 ,而是坚持只用“SilentBreak”。

本文翻译自 :https://securelist.com/a-new-secret-stash-for-fileless-malware/106393/

顶: 3踩: 62344