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 媒体调整器
sppcommdlg.dll软件许可 UI API

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

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

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

考虑以下样本,作为本次分析的 BLISTER 代表。此样本还用于开发最初的 BLISTER 家族 YARA 签名、配置提取脚本以及针对未知 x32 和 x64 BLISTER 样本评估工具。

执行流程

执行流程包括以下阶段:

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

启动/入口点

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

Rundll32 execution arguments

rundll32.exe "BLISTER.dll,LaunchColorCpl"

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

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

解密第二阶段

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

解密例程从基于循环的睡眠开始,以逃避检测。

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

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

混淆

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

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

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

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

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

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

最后,它返回打包 PE 的起始指针,该指针位于 0x644 字节 blob 之后。

请参阅附录中的配置结构

基于时间的反调试

加载配置后,并且根据是否设置了 **kEnableSleepBasedAntiDebug** 标志 (0x800),BLISTER 将调用其基于时间的反调试函数。

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

主线程将使用 **NtDelayExecution** 休眠,直到休眠线程退出。

最后,当休眠线程至少运行了 9 分半钟时,该函数将返回 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** 函数一起使用,例如:

LdrLoading Windows 库和移除 Hook

映射 32 位和 64 位 **NTDLL** 版本后,BLISTER 将 **LdrLoad** 几个 Windows 库并移除潜在的 Hook。

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

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

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

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

然后,BLISTER 使用已加载的库作为重定位计算的基地址,对映射的库应用重定位。

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

如果该节可执行,则将其替换为映射的节,从而移除任何 Hook。

x64 API 调用

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

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

解压 Payload

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

解密

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

解压缩

解密阶段完成后,Payload 将使用 **RtlDecompressBuffer** 函数和 LZNT1 压缩格式进行解压缩。

持久化机制

为了实现持久化,BLISTER 利用 Windows 快捷方式,在 Windows 启动文件夹中创建一个 LNK 文件。它使用 **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 中,文件名是 UNIQUE STRING\>.lnk。

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

注入 Payload

BLISTER 实现 3 种不同的注入技术来根据配置标志执行 Payload。

Shellcode 执行

解密 Shellcode 后,BLISTER 可以使用 **NtAllocateVirtualMemory** API 将其注入到新分配的读写内存区域中,然后将 Shellcode 复制到该区域,并使用 **NtProtectVirtualMemory** 将内存区域设置为读写执行,然后执行它。

自身进程注入

BLISTER 可以反射式地在自身的内存空间中执行 DLL 或可执行文件 Payload。它首先使用 **NtCreateSection** API 创建一个节。

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

相反,如果 Payload 是 DLL,它将首先取消映射当前进程映像的内存区域,然后在 Payload 的首选地址映射该已创建节的视图。

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

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

进程空洞攻击

BLISTER 能够对远程进程执行 进程空洞攻击

首先,它会检查特定的模块哈希值 (0x12453653),如果匹配,BLISTER 将对 Internet Explorer 可执行文件执行进程空洞攻击。

如果不匹配,恶意软件将使用 **Werfault.exe** 执行远程进程空洞攻击。BLISTER 遵循进程空洞攻击的标准技术。

此函数中有一条路径:如果满足某些条件(匹配 Windows 操作系统版本和内部版本号),则通过在 **AppData** 文件夹中放置名为 **Bg.Agent.ETW** 的临时文件(带有显式扩展名)来执行空洞攻击技术。

恶意软件使用此文件读取和写入恶意 DLL 到此文件中。BLISTER 启动 Werfault.exe,然后将此临时 DLL 的内容加载到 Werfault 进程的内存中,并在之后立即删除该文件。

配置提取器

自动从 BLISTER 提取配置和 Payload 是威胁狩猎的关键方面,因为它可以了解攻击者的活动和部署的恶意软件,使我们能够及时发现新的未知样本和 Cobalt Strike 实例。

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

为了让社区能够进一步防御现有的和新的 BLISTER 加载程序变体,我们将配置提取器开源,并采用 Apache 2 许可证。配置提取器的文档和二进制文件可以在这里下载 here

结论

BLISTER 仍然是一个强大的威胁,影响力远超其自身级别,分发流行的恶意软件家族和植入程序,导致重大安全问题。Elastic Security 已经跟踪 BLISTER 数月,我们没有看到该家族减缓的迹象。

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

附录

配置结构

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
}

参考文献

工件

工件也可以在这里下载 download,格式为 ECS 和 STIX,打包在一个 zip 文件中。