BLISTER 加载器

BLISTER 加载器继续被积极用于加载各种恶意软件。

阅读 20 分钟恶意软件分析
BLISTER Loader

主要发现

  • BLISTER 是一款持续保持低调的加载器,被积极用于加载各种恶意软件,包括剪贴板劫持器、信息窃取器、木马、勒索软件和 shellcode
  • 深入分析表明,它严重依赖 Windows 原生 API、多种注入能力、多种逃避检测的技术以及反静态/动态分析
  • Elastic Security 正在提供一个配置提取器,可用于识别恶意软件的关键元素,并转储嵌入式有效负载以进行进一步分析
  • 在 Elastic Security 最初报告 BLISTER 加载器 40 天后,我们观察到二进制文件发生更改,以包含其他架构。这表明这是一个积极开发的工具,并且作者正在关注防御性对策

有关 BLISTER 恶意软件加载器和活动观测的信息,请查看我们的博客文章和详细介绍此内容的配置提取器

概述

自去年年底首次发布以来,Elastic Security 团队一直在持续监控 BLISTER 加载器。该系列仍然基本未被发现,新样本的检测率很低。

BLISTER 作者的一个显著特征是他们篡改合法 DLL 以绕过静态分析的方法。在过去的一年中,Elastic Security 观察到以下被 BLISTER 恶意软件修补的合法 DLL

文件名描述
dxgi.dllDirectX 图形基础设施
WIAAut.DLLWIA 自动化层
PowerCPL.DLL电源选项控制面板
WIMGAPI.DLLWindows 映像库
rdpencom.dllRDPSRAPI COM 对象
colorui.dllMicrosoft 颜色控制面板。
termmgr.dllMicrosoft TAPI3 终端管理器
libcef.dllChromium 嵌入式框架 (CEF) 动态链接库
CEWMDM.DLLWindows CE WMDM 服务提供商
intl.dll适用于 Windows NT/2000/XP/Vista/7 和 Windows 95/98/ME 的 LGPLed libintl
vidreszr.dllWindows Media 调整大小工具
sppcommdlg.dll软件许可 UI API

由于恶意代码嵌入在原本良性的应用程序中的方式,BLISTER 对于依赖某些形式的机器学习的技术来说可能具有挑战性。结合代码签名防御规避,BLISTER 的设计似乎考虑了安全技术。

我们的研究表明,BLISTER 正在积极开发,并且在公开报告中链接LockBit 勒索软件和 SocGholish 框架;此外,Elastic 还观察到 BLISTER 与以下系列有关:AmadeyBitRATClipbankerCobalt StrikeRemcosRaccoon 以及其他。

在本文中,我们将解释 BLISTER 如何继续秘密运行,重点介绍加载器的核心功能(注入选项、混淆和反分析技巧),并提供一个配置提取器,该提取器可用于转储 BLISTER 嵌入的有效负载。

请考虑以下代表 BLISTER 的样本以进行此分析。此样本还用于开发初始 BLISTER 系列 YARA 签名、配置提取脚本以及评估针对未知 x32 和 x64 BLISTER 样本的工具。

执行流程

执行流程包括以下阶段

  • 解密第二阶段
  • 检索配置和打包的有效负载
  • 有效负载解包
  • 持久化机制
  • 有效负载注入

启动/入口点

在执行流程的第一阶段,BLISTER 嵌入在 colorui.dll 库的合法版本中。威胁参与者使用先前获得的立足点,通过调用导出函数 LaunchColorCpl ,使用 Windows 内置的 rundll32.exe 实用程序加载 BLISTER

Rundll32 execution arguments

rundll32.exe "BLISTER.dll,LaunchColorCpl"

下图演示了如何修改 BLISTER 的 DLL,指出导出起始位置已使用函数调用(第 17 行)修补到恶意软件入口点。

如果我们将其中一个恶意加载器与其伪装的原始 DLL 进行比较,我们可以看到进行修补的位置,该函数不再存在

解密第二阶段

BLISTER 的第二阶段在其资源部分 (.rsrc) 中被加密。

解密例程以基于循环休眠开始,以逃避检测

然后,BLISTER 枚举并哈希 ntdll 的每个导出,将导出名称与加载的模块名称进行比较;专门搜索 NtProtectVirtualMemory API

最后,它通过搜索特定的内存模式来查找 100,832 字节的内存区域,从返回地址开始搜索,并将我们引导到 .rsrc 部分。找到后,BLISTER 对具有四字节密钥的内存区域执行异或 (XOR) 操作,通过调用 NtProtectVirtualMemory 将其页面保护设置为 PAGE_EXECUTE_READ,并使用解密密钥作为参数调用其第二阶段入口点

混淆

BLISTER 的第二阶段涉及混淆函数,通过使用无条件跳转分割其基本块和随机化基本块的位置来扰乱其控制流。下面显示了一个示例。

BLISTER 将垃圾代码插入到基本块中,作为另一种形式的防御规避,如下所示。

检索配置和打包的有效负载

BLISTER 使用上一阶段的四字节密钥来查找和解密其配置。

该例程首先从返回地址开始,搜索其内存中与硬编码值异或运算的四字节密钥作为内存模式

找到后,将 0x644 字节的配置复制并使用相同的四字节密钥进行 XOR 解密

最后,它返回指向打包 PE 开头的指针,该指针位于 0x644 字节 blob 之后

请参阅附录中的配置结构

基于时间的防调试

加载配置后,如果设置了 kEnableSleepBasedAntiDebug 标志 (0x800),BLISTER 会调用其基于时间的防调试函数

此函数首先创建一个线程,该线程以 Sleep Windows 函数作为起始地址,以 10 分钟作为参数

主线程将使用 NtDelayExecution 进入休眠状态,直到休眠线程退出。

最后,当休眠线程至少运行 9 分 30 秒后,该函数将返回 0。

否则,该函数将返回 1,并且进程将被终止。

Windows API

BLISTER 的 GetModuleHandle

BLISTER 实现了自己的 GetModuleHandle 来逃避检测。该函数接收库名称哈希值作为参数,遍历进程的 PEB LDR 模块,并将模块的哈希名称与参数中传递的名称进行比较。

BLISTER 的 GetProcAddress

BLISTER 的 GetProcAddress 接收目标 DLL 和导出的哈希值作为参数,它还会接收一个标志,该标志告知该函数该库是 64 位的。

DLL 可以被加载或映射,然后该函数遍历 DLL 的导出函数名称,并将其哈希值与参数中传递的哈希值进行比较。

如果找到导出项,并且其虚拟地址不为空,则将其返回。

否则,该 DLL 将被 LdrLoaded,并且再次调用 BLISTER 的 GetProcAddress,并传入新加载的 DLL。

库手动映射

BLISTER 使用 NtCreateFile 手动映射库,以便在 DLL 文件上打开句柄。

接下来,它通过调用 NtCreateSection 并使用 SEC_IMAGE 属性来使用该句柄创建节,该属性告诉 Windows 将二进制文件作为 PE 加载。

在映射函数中使用的 NtCreateSection

最后,它使用 NtMapViewOfSection 映射该节。

x32/x64 Ntdll 映射

在调用其反调试函数之后,BLISTER 会手动映射 32 位和 64 位版本的 NTDLL。

它首先映射 x32 版本。

然后,它禁用 SysWOW64 重定向

然后,映射 64 位版本。

如果可用,映射的库将与 GetProcAddress 函数一起使用,即

Ldr加载 Windows 库并删除钩子

在映射 32 位和 64 位 NTDLL 版本之后,BLISTER 将 LdrLoad 几个 Windows 库并删除潜在的钩子。

首先,它尝试通过将哈希值与已知哈希值的固定列表进行比较来将哈希值转换为库名称。

如果找到哈希值,BLISTER 会使用 LdrLoad 加载库。

然后,BLISTER 在其自己的进程中搜索相应的模块。

并使用模块的 FullDllName 映射库的新副本。

然后,BLISTER 将重定位应用于映射的库,并将加载的库作为重定位计算的基址。

接下来,BLISTER 遍历加载库的每个节,以查看该节是否是可执行的。

如果该节是可执行的,则将其替换为映射的节,从而删除所有钩子。

x64 API 调用

BLISTER 可以通过使用特殊的 64 位函数包装器来调用 64 位库函数。

为了进行此调用,BLISTER 使用旧的 Heaven’s Gate 技术在 32 位代码和 64 位代码之间切换。

解包有效负载

在有效负载的解包过程中,恶意软件首先使用 NtAllocateVirtualMemory 分配内存并传入配置信息。memcpy 函数用于将加密/压缩的有效负载的副本存储在缓冲区中以进行下一阶段(解密)。

解密

BLISTER 利用 Rabbit 流 密码,传入先前分配的包含加密有效负载的缓冲区,压缩数据大小以及 16 字节的解密密钥和 8 字节的 IV。

解压缩

在解密阶段之后,然后使用带有 LZNT1 压缩格式的 RtlDecompressBuffer 解压缩有效负载。

持久性机制

为了实现持久性,BLISTER 通过在 Windows 启动文件夹内创建一个 LNK 文件来利用 Windows 快捷方式。它使用 CreateDirectoryW 函数创建一个新目录,该目录在配置文件中具有唯一的硬编码字符串,例如:C:\ProgramDataUNIQUE STRING\\>

然后,BLISTER 将 C:\System32\rundll32.exe 和自身复制到新创建的目录,并将文件分别重命名为 UNIQUE STRING\>.exe 和 UNIQUE STRING\>.dll。

BLISTER 使用 CopyModuleIntoFolder 函数和 IFileOperation Windows COM 接口,以便在复制和重命名文件时绕过 UAC

恶意软件使用 IShellLinkW COM 接口创建一个 LNK 文件,并将其存储在 C:\Users\<username>\AppData\Roaming\Microsft\Windows\Start Menu\Startup as UNIQUE STRING\\>.lnk 中。

该 LNK 文件设置为运行新复制的恶意软件的导出函数 LaunchColorCpl,并使用 rundll32 的重命名实例。C:\ProgramData\UNIQUE STRING\>\UNIQUE STRING\>.exe C:\ProgramData\UNIQUE STRING\>\UNIQUE STRING\>.dll,LaunchColorCpl

注入有效负载

BLISTER 根据配置标志实现了 3 种不同的注入技术来执行有效负载。

Shellcode 执行

在解密 shellcode 之后,BLISTER 能够使用 NtAllocateVirtualMemory API 将其注入到新分配的读写内存区域,然后将 shellcode 复制到其中,并使用 NtProtectVirtualMemory 将内存区域设置为读写执行,然后执行它。

自身进程注入

BLISTER 可以在其内存空间中反射性地执行 DLL 或可执行有效负载。它首先使用 NtCreateSection API 创建一个节。

然后,BLISTER 尝试在有效负载的首选基址上映射创建的节的视图。如果首选地址不可用,并且有效负载是可执行文件,它将简单地在随机地址上映射创建的节的视图,然后进行重定位。

相反,如果有效负载是 DLL,它将首先取消映射当前进程映像的内存区域,然后使用有效负载的首选地址映射创建的节的视图。

然后,BLISTER 调用一个函数来复制 PE 标头和节。

最后,BLISTER 从其入口点开始执行内存中加载的有效负载(如果有效负载是可执行文件)。如果有效负载是 DLL,它将根据配置文件中的哈希值查找其导出函数并执行它。

进程镂空

BLISTER 能够对远程进程执行 进程镂空

首先,会检查特定的模块哈希值 (0x12453653),如果满足,BLISTER 会针对 Internet Explorer 可执行文件执行进程镂空。

如果不是,则恶意软件会使用 Werfault.exe 执行远程进程镂空。BLISTER 遵循用于进程镂空的标准技术。

此函数中有一条路径:如果满足某些匹配 Windows OS 版本和内部版本的条件,则镂空技术是通过在 AppData 文件夹中放置一个名为 Bg.Agent.ETW 且具有显式扩展名的临时文件来执行的。

恶意软件使用此文件来读取恶意 DLL 并将其写入到此文件中。Werfault.exe 由 BLISTER 启动,然后此临时 DLL 的内容被加载到 Werfault 进程的内存中,并且文件在不久后被删除。

配置提取器

当涉及到威胁狩猎时,自动化从 BLISTER 中提取配置和有效负载是一个关键方面,因为它使我们能够了解活动的可见性以及威胁参与者部署的恶意软件,这使我们能够及时发现新的未知样本和 Cobalt Strike 实例。

我们的提取器使用 Rabbit 流密码实现,并使用 -d 选项获取样本目录,或使用 -f 获取单个样本。

为了使社区能够进一步防御现有和新的 BLISTER 加载器变体,我们正在 Apache 2 许可证下开源配置提取器。可以在此处访问配置提取器文档和二进制文件下载。

结论

BLISTER 仍然是一个强大的威胁,它以超出其自身重量级别的能力,分发流行的恶意软件系列和植入程序,从而导致重大泄露。Elastic Security 几个月来一直在跟踪 BLISTER,我们没有看到这个系列放缓的迹象。

通过对 BLISTER 进行逆向工程,我们的团队能够识别关键功能,例如不同的注入方法、使用反调试/反分析功能进行防御规避的多种技术以及对 Windows 本机 API 的严重依赖。我们还发布了一个配置提取器,该提取器可以静态地从 BLISTER 样本中检索可操作的信息,以及转储嵌入的有效负载。

附录

配置结构

BLISTER configuration structure

struct Config {
  uint16_t flag;
  uint32_t payload_export_hash;
  wchar_t w_payload_filename_and_cmdline[783];
  size_t compressed_data_size;
  size_t uncompressed_data_size;
  uint8_t pe_deciphering_key[16];
  uint8_t pe_deciphering_iv[8];
};

配置的标志

BLISTER configuration files

enum Config::Flags {
  kDoPersistance = 0x1,
  kOwnProcessReflectiveInjectionMethod = 0x2,
  kOwnProcessHollowingMethod = 0x8,
  kRemoteProcessHollowingMethod = 0x10,
  kExecutePayloadExport = 0x20,
  kExecuteShellcodeMethod = 0x40,
  kInjectWithCmdLine = 0x80,
  kSleepAfterInjection = 0x100,
  kEnableSleepBasedAntiDebug = 0x800,
};

哈希算法

BLISTER hashing algorithm

uint32_t HashLibraryName(wchar_t *name) {
  uint32_t name {0};
  while (*name) {
 hash = ((hash >> 23) | (hash  << 9)) + *name++;
  }
  return hash ;
}

指标

指标类型备注
afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2SHA256BLISTER DLL

YARA 规则

此更新的 YARA 规则在检测率方面提高了 13%。

BLISTER YARA rule

rule Windows_Trojan_BLISTER {
    meta:
        Author = "Elastic Security"
        creation_date = "2022-04-29"
        last_modified = "2022-04-29"
        os = "Windows"
        arch = "x86"
        category_type = "Trojan"
        family = "BLISTER"
        threat_name = "Windows.Trojan.BLISTER"
        description = "Detects BLISTER loader."
        reference_sample = "afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2"

    strings:
        $a1 = { 8D 45 DC 89 5D EC 50 6A 04 8D 45 F0 50 8D 45 EC 50 6A FF FF D7 }
        $a2 = { 75 F7 39 4D FC 0F 85 F3 00 00 00 64 A1 30 00 00 00 53 57 89 75 }
        $a3 = { 78 03 C3 8B 48 20 8B 50 1C 03 CB 8B 78 24 03 D3 8B 40 18 03 FB 89 4D F8 89 55 E0 89 45 E4 85 C0 74 3E 8B 09 8B D6 03 CB 8A 01 84 C0 74 17 C1 C2 09 0F BE C0 03 D0 41 8A 01 84 C0 75 F1 81 FA B2 17 EB 41 74 27 8B 4D F8 83 C7 02 8B 45 F4 83 C1 04 40 89 4D F8 89 45 F4 0F B7 C0 3B 45 E4 72 C2 8B FE 8B 45 04 B9 }
        $b1 = { 65 48 8B 04 25 60 00 00 00 44 0F B7 DB 48 8B 48 ?? 48 8B 41 ?? C7 45 48 ?? ?? ?? ?? 4C 8B 40 ?? 49 63 40 ?? }
        $b2 = { B9 FF FF FF 7F 89 5D 40 8B C1 44 8D 63 ?? F0 44 01 65 40 49 2B C4 75 ?? 39 4D 40 0F 85 ?? ?? ?? ?? 65 48 8B 04 25 60 00 00 00 44 0F B7 DB }
    condition:
        any of them
}

参考

工件

工件还以 ECS 和 STIX 格式的组合 zip 包提供下载