在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的木马。 商业工具集有
: 同样,我们认为定制的一些模块(如包装器和最后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 都在使用 。解密器差异很大,它们包含的功能如下表所示: 这层感染链解密、映射到内存并启动代码
。本文我们将仅介绍 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 编码。 使用这种方法,研究人员需要编写一些脚本来收集下一个模块的加密部分
。解密后
,要获得最终的可移植可执行文件,还需进一步转换数据。 Last stager 有两种通信机制——使用RC4加密的HTTP通信机制和使用命名管道的非加密通信机制。后一种方式在技术上能够与任何网络可见的外部主机通信,但在Windows环境中 ,命名管道是建立在SMB协议之上的,它几乎不会对外部网络开放。所以这些模块很可能用于横向移动。 在对恶意软件集进行了介绍之后
,我们现在将描述感染链
,研究人员使用 Cobalt Strike 渗透测试套件进行Dropper注入。 研究人员从 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 会自动递增
。 这个启动器,被第一个stager放到 Tasks 目录中
,它代理所有对wer.dll的调用,并将其导出到原始合法库
。在入口点
,一个单独的线程将所有上述 8KB 片段组合成一个完整的 shellcode 并运行它 。由合法 WerFault.exe 的副本创建的相同虚拟地址空间用于所有这些代码 。 为了防止 WerFault 继续其错误处理过程
,DLL 使用典型的 Blackbone trampoline修复启动器的入口点 阻止合法启动器执行的方法很新颖 。在主线程中 ,wer.dll 找到它的入口点并用一个简单的函数对其进行修复
。上面屏幕截图中的 WaitAndExit() 只会使用日志收集线程 ID 调用 WaitForSingleObject() ,然后退出
,这意味着永远不会执行真正的 WerFault.exe 错误处理代码:映射到其地址空间的欺骗性 DLL 会阻止它 。 启动器将控制传输到收集的 shellcode 的第一个字节 。在本文中,研究人员为下一个函数准备了三个参数 : 解析下一个 Windows 可移植可执行文件以定位其入口点的做法是非常典型的 。为了让下一个stager的木马不那么显眼,攻击者清除了标题中的“MZ”魔法。在木马的入口点调用代码后
,shellcode 还会搜索请求导出并调用它
。 除了搜索入口点并调用它,shellcode 还通过硬编码哈希搜索木马导出 ,并使用参数“dave”和“4”运行找到的函数 相比之前的辅助模块
,对于最后一个stager,我们会介绍的更详细一些 。 C++ 模块显然使用了 SilentBreak(现为 NetSPI)的 Throwback 公共存储库中的代码
:基于 XOR 的加密函数 ,一些示例的原始文件名,例如 ThrowbackDLL.dll 等。让我们从前面提到的Load()导出函数开始。这就像上面的WerFault补丁(函数在主木马线程上等待) ,但是它忽略了任何参数 ,所以“dave”和“4”没有被使用。这个启动器可能支持比这个更多的模块。 该模块使用单字节 XOR 密钥解密 C2 域,在此示例中,只有一个域 eleed[.]online
。该木马能够处理其中的许多,以“|”字符分隔并加密 。为了进一步通过普通HTTP进行通信,木马从用户代理“Mozilla 5.0”的集合中随机选择一个C2
。 该恶意软件通过收集以下信息生成一个追踪字符串,也用“|”分隔: 追踪识别器还将“1.1”附加到字符串(可能是恶意软件版本)和当前配置的睡眠时间。 在HTTP通信之前,该模块使用硬编码的32字节长的RC4密钥发送空(但仍然加密)的ICMP数据包来检查连接
。与任何其他字符串一样 ,此密钥使用基于Throwback xor的算法加密
。 如果ping端口为80的控制服务器成功,则将上述追踪数据发送到该控制服务器 。作为回应 ,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算法加密
。对于基于管道命名的木马,常用的命令有: 研究人员现在已经介绍了该活动的三个层面,有趣的是,研究人员观察到一个木马具有如上表所示的完整命令集,但仍然使用rc4加密的HTTP与C2通信
,而不是指定管道。最后一个stager的示例看起来像一个模块化的平台
,攻击者能够根据他们当前的需要组合其功能。 研究人员认为这些代码是自定义的(木马
、包装器),与以前已知的活动或以前注册的SilentBreak工具集模块没有相似之处。现在研究人员不愿意给这个活动命名,而是坚持只用“SilentBreak”。 本文翻译自 :https://securelist.com/a-new-secret-stash-for-fileless-malware/106393/






