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






