
在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/