概括
Lumma Stealer 于 2022 年首次被发现,至今仍是一个重大威胁,它不断改进其策略、技术和程序 (TTP),以紧跟新兴趋势。它通过基于订阅的恶意软件即服务 (MaaS) 模式在暗网上传播。Lumma 旨在检测虚拟环境和沙盒环境,从而避免被依赖沙盒环境评估文件行为的安全系统检测到。该恶意软件能够窃取敏感数据,包括来自 Web 浏览器、电子邮件应用程序、加密货币钱包的信息以及存储在关键系统目录中的其他个人身份信息 (PII)。
Trellix 高级研究中心一直在追踪Lumma Stealer 背后的威胁行为者近期的攻击活动,并分析其 TTP 的演变。在本篇博文中,我们将对 Lumma 如何实现以下目标进行技术分析。
-
代码流混淆
-
API哈希解析
-
天堂之门
-
禁用 ETWTi 回调
-
反沙牛技术
-
指挥与控制、渗透
-
感染链
图 1:Lumma 窃取程序的感染链
我们发现一个威胁行为者通过混淆的 PowerShell 脚本分发 Lumma。这些脚本包含两个 Base64 编码格式的可执行文件,
-
名为 GOO.dll 的 .NET 可执行文件(加载器)
-
Lumma 有效载荷
图2:混淆的Powershell脚本
PowerShell 脚本使用反射 API 加载 .NET 可执行文件,然后在程序集中找到“R2”类,并调用其“Run()”方法。传递给“Run”方法的参数存储在 $YOO 变量中。第一个参数是 RegSvcs.exe 的路径(“C:WindowsMicrosoft.NETFrameworkv4.0.30319RegSvcs.exe”),第二个参数是 Lumma 有效载荷 ($hgh)。
Powershell$YOO=[object[]]('C:WindowsMicrFFosoft.NFFETFraDDmewDDorkv4.0.30319RegSvcs.exe'.replace('FF','').replace('DD',''),$hgh)
使用 Crypto Obfuscator 进行混淆的 .NET 二进制文件会将 Lumma 二进制文件注入 RegSvcs.exe 进程。注入的 Lumma 有效载荷随后继续运行,伪装成合法的 RegSvcs.exe 实用程序。
图3:打包机信息
图 4:.NET 程序集和用于调用 Lumma 有效载荷的函数
图 5:Powershell 生成 Regsvcs.exe
Lumma Stealer的技术分析
在对衍生样本进行分析的过程中,由于命令和控制 (C2) 服务器处于非活动状态,导致行为分析不完整。为了给读者提供更全面的分析,我们详细描述了最新 Lumma 样本的观察行为,该样本可能通过之前讨论过的技术传递到受害者的环境中。
示例哈希(SHA256):80741061ccb6a337cbdf1b1b75c4fcfae7dd6ccde8ecc333fcae7bcca5dc8861
对 Lumma 的二进制文件进行代码分析后发现,其主要功能首先将加密字符串传递给解密例程。第一个需要解密的字符串是“ntdll.dll”。同样,其他重要库的名称(例如 kernel32.dll、user32.dll、winhttp.dll 和 crypt32.dll)也在运行时被解密。
解密后的字符串作为参数传递给一个函数,该函数利用 Windows 中的进程环境块 (PEB) 数据结构来解析库在内存中的地址。通过这种技术,Lumma 避免调用 LoadLibrary 和 GetProcAddress 等非常常见的受监控 API,这些 API 受到 EDR 和其他安全系统的严格审查。
代码流混淆
Lumma 采用了先进的代码流混淆技术,大大增加了分析难度。因此,该恶意软件使得反编译器(恶意软件分析中常用的工具)难以完全反编译代码。
因此,静态分析方法无法揭示程序的完整逻辑。
图 6:通过计算 ECX 来确定下一条指令,其中绿色框突出显示了用于得出 ECX 的计算
从上图中可以看出,较大的方框突出显示了负责计算下一个跳转指令的例程,而较小的方框则显示了一条跳转指令,该指令包含“ecx”寄存器中的下一个指令地址。结果,代码块分散,彼此之间没有任何静态链接,链接(即指向下一个有效代码块的地址)是动态计算的,这导致反编译器无法准确分析代码,代码流被破坏。Lumma Stealer 将这种混淆技术扩展到控制流语句,例如 If-Else 和 Do-While,这进一步增加了分析的复杂性。
此外,每次跳转的计算结果都会有所不同,这使得代码难以自动化或有效清理。在本例中,跳转指令指向地址 ECX = 0067BCD6 处的下一条指令(参见图片)。
API哈希解析
Lumma 使用 API 哈希技术在运行时动态解析 API 函数,这是恶意软件根据需要定位 API 的常用方法。
下面列出了 Lumma 动态解析的一些 API,
-
RtlAllocateHeap
-
RtlReAllocateHeap
-
RtlFreeHeap
-
RtlExpandEnvironmentStrings
此外,网络所需的 API 也使用相同的函数进行解析。
Lumma 样本是 32 位的,它使用天堂之门技术在 64 位机器上执行时运行 64 位代码。
天堂之门
Lumma 通过比较代码段 (CS) 寄存器的值来识别它是在 32 位还是 64 位机器上运行。
如果值为 0x23,则表示它是 32 位机器。
如果值为 0x33,则表示它是一台 64 位机器。
在 64 位系统上运行时,Lumma 使用“ jmp far 33”指令转换为 64 位代码。
图 7:Jmp far 指令用于 32 位到 64 位的转换
为了调用 NTAPI 函数,Lumma 构建了一个包含 Syscall Hashes 和 Syscall Indexes 的表。它遍历 ntdll.dll 库的导出表,为以“Nt”开头的 API 名称(例如 NtQueryInformationFile 和 NtOpenFile)生成自定义哈希值。
Lumma 根据操作码模式对系统调用进行哈希处理。具体来说,
-
以操作码 B8 开头并以返回操作码 C2 或 C3 结尾的系统调用将被考虑进行哈希处理
图 8:哈希标准
下图描述了与上面讨论的模式匹配的系统调用。
例如:
-
NtYieldExecution 系统调用以 B8 开头,并使用“C3”操作码返回
-
NtAddAtom 系统调用以 B8 开头,并使用“C2”操作码返回
图 9:调试器代码片段
另一方面,像 NtCurrentTeb 这样不以 B8 开头的系统调用被排除在 Syscall 哈希表之外。
图 10:NtCurrentTeb Syscall 模式不符合哈希标准
系统调用哈希/索引表
图 11:Syscall 哈希表
上图显示了系统调用表,一个 DWORD(哈希)后跟另一个包含“系统调用索引”的 DWORD。
例如,第一个 DWORD 是 NtAcceptConnectPort/ZwAcceptConnectPort API 的哈希值(索引 = 2),第二个 DWORD 是系统调用索引(2)。每当 Lumma 需要调用 NTAPI 时,它都会通过遍历表并匹配相应的哈希值来找到系统调用索引。
图 12:ZwAcceptConnectionPort Syscall 模式
NTDLL 重新映射
Lumma 利用系统调用表根据系统架构重新映射 ntdll.dll。通过检查代码段 (CS) 寄存器的值来确定 DLL 的正确版本(32 位或 64 位)。
在 32 位系统上,knowndlls32/ntdll.dll 被映射。
在 64 位系统上,knowndlls/ntdll.dll 被映射。
下面列出的 NTAPI 系统调用索引使用其各自的哈希值进行解析
表 1:API、恶意软件生成的相应哈希值以及 Syscall 索引
根据重新映射的 NTDLL,系统调用表被重新生成,之前创建的哈希表被覆盖,目前尚不清楚该过程为何重复两次。恶意软件很可能通过从磁盘加载 NTDLL 来获取干净、未挂钩的 DLL 版本,这样一来,由于挂钩尚未到位,EDR 就无法检测到其活动。
下图描述了内存中加载的两个 NTDLL 库,红色突出显示的是最初加载的 NTDLL 模块库,绿色突出显示的是重新映射的 NTDLL 库。
图 13:Lumma 重新映射 NTDLL 库
系统调用生成后,使用“NtUnMapViewOfSection”取消映射新加载的 NTDLL,并使用“NtClose”关闭其句柄。
禁用 ETWTi 回调
Lumma 调用 NtSetInformationProcess API,并传递一个修改 ProcessInformation 类的结构体。通过将结构体中的 Callback 字段设置为 0,可以删除由 ETW(Windows 事件跟踪)等安全软件设置的回调,从而阻止这些软件监视 Lumma 窃取程序发出的系统调用。
图 14:传递给 NtSetInformationProcess 的参数
图 15:12 个空字节作为 ProcessInformation 参数传递
上图显示了 NtSetinformationprocess 的参数,其中第三个参数(ProcessInformation)设置为回调函数的 null
反沙盒技术
为了避免在沙盒环境中被检测到,Lumma 会检查是否存在特定的沙盒或与杀毒软件相关的 DLL。恶意软件会使用存储在 Lumma .rdata 段中的硬编码哈希值来验证这些 DLL 是否已加载到内存中。
验证完成后,Lumma 进入下一阶段。我们编写了一个 Python 哈希算法实现,以获取以下经过 Lumma 验证的进程名称列表,用于检测沙盒环境。
表 2:Lumma 动态哈希的分析细节
为了实现反分析,Lumma 包含一项可选功能,用于检测虚拟机 (VM) 环境。此检查基于来自命令和控制 (C2) 服务器的响应执行,具体是通过验证响应中是否包含设置为“true”的名为“vm”的属性。下文的命令和控制部分包含对此功能的详细分析。
针对特定区域执行
Lumma 还包含针对特定地区的执行检查。如果将“用户默认语言”设置为俄语(语言代码为 0x419),恶意软件将退出并提示不支持该国家/地区。
图 16:使用动态 API 哈希解析 GetUserDefaultUILanguage API
指挥与控制、渗透
动态分析显示,Lumma 在调用合法的“steamcommunity.com”之前调用了多个域。
图 17:Lumma 尝试连接到嵌入式域列表
所有与 C2 通信相关的字符串(包括域、备份域、标头和 HTTP 方法)都以加密格式存储。
例如,加密的 C2 域被解密为“mercharena[.]biz”。
图18:Wireshark捕获的分析细节
对于每个解密的域,使用以下请求参数进行连接尝试(POST)
表3:POST请求参数
图 19:POST 请求参数以备用域、端点、内容类型和请求正文开始
预计服务器的响应是“ok”。
图 20:Lumma 验证服务器的响应是否与字符串“ok”匹配。值得注意的是,该字符串是加密的,而不是以纯文本形式存储的。
Steam 作为备用域名
Lumma 会检查主域名是否可用,如果不可用,则会尝试访问备用域名。如果所有备用域名均无响应,Lumma 将使用游戏网站 Steam[.]com 生成 C2 URL。
Lumma 通过以下 URL 向 Steam 社区资料发起请求:
hxxps://steamcommunity.com/profiles/76561199724331900
Lumma 从响应中提取 Steam 用户名,并用它来获取 C2 URL。下图展示了威胁行为者过去使用的用户名。用户名以加密形式表示 C2 域名。
图 21:威胁行为者频繁修改 Steam 用户名
例如,个人资料页面中的 HTML 标题标签可能是:<title>Steam Community :: ytvzwlj-czxlyzg.df</title>
用户名最初是加密的,但 Lumma 对其进行解密以获取最终的 C2 URL,即:
-
hxxps://nikolay-romanov[.]su/
对于此样本,域名“mercharena[.]biz”处于活动状态,并返回了预期的“ok”响应。然后,Lumma 发送另一个 POST 请求,其主体包含 action(act) 属性,其内容为“recive_message”(拼写错误,其中 receive 一词拼写错误),版本为“4.0”,许可证 ID 为“f9tVYj--testik1”。
“act=recive_message&ver=4.0&lid=f9tVYj--testik1&j=”
表 4:恶意软件构建 ID 和命令与控制域
C2 返回了一个加密的配置文件。解密后,内容显示为 JSON 格式的恶意软件配置文件,其中详细记录了 Lumma 想要窃取的具体数据,包括浏览器数据、钱包信息、密码管理器详细信息以及关键文件路径。
图 22:加密的 Lumma 响应
下图显示了 JSON 格式的解密配置文件。
图 23:包含构建版本、钱包名称的解密响应
反虚拟机
分析 JSON 文件后发现,“v”属性表示 Lumma 的版本。“se”属性设置为“true”,似乎负责截取屏幕截图。
在此示例中,“vm”属性设置为“false”,但启用后,Lumma 会使用“CPUID”指令检查其是否在虚拟机环境中运行。
CPUID 函数传递了 EAX 值 0x40000000,并将 ECX 中的返回值与以下 VM 值进行比较:
-
564B4D56 - VMware
-
43544743 - QEMU
-
4D566572 - VMware
-
786F4256 - VirtualBox
-
65584D4D - Xen
IOC
http:[//]blast-hubs.com/ http:[//]blastikcn.com/http:[//]generalmills.pro/http:[//]mercharena.biz/ http:[//]naturewsounds.help/http:[//]nestlecompany.pro/http:[//]stormlegue.com/https:[//]nikolay-romanov[.]su/
SHA256 Hashes
80741061ccb6a337cbdf1b1b75c4fcfae7dd6ccde8ecc333fcae7bcca5dc8861 (Lumma)e9e568dce12ca4392001860c693292203b2bfcbbb277a484e4d2ebb5b0449207 (Lumma)1345ad4c782c91049a16ec9f01b04bfc83a4f0e1e259cfed2b535f8ec6b75590 (Lumma)4abe068f8e8632a9074556f2adb39dd2c52a1bf631abbf5bfd47888059c35350 (Lumma)629618eb8225361b068a11ce07f46eefd0ce4098266f274f0d56b75fb5a77321 (Lumma)7034406778028fd6edbb340fdaeddbbec3d1f8665e8332063edc75dfaee482d1 (Lumma)aa2dfa4e02b2eb688c7ba0d29619e082214251930e39727e35b53a436766825a (Lumma)c2ab516bb3a39832d963770d813ab77027d454a087ad9fae8ce24336a78f9073 (Lumma)c340bf332f68794afa171c68efadf9b1e742e4ad577582adfed61567a65aa91c (Lumma)e52f5fcfc8034e46e0f3ff826d437ce69f7d9da30019115008f823c9b7ffb929 (Lumma)eb69158f493de304592e67de21a42cd094693bda13fb211c46353248706df696 (Lumma)253cdcfd6f8b6e52133bc59df92563e432b335d2a207f2f8e01fac2423ccbac8 (Powershell script)90e35b4a519af394e32cd09d34c6d5f60b31726672aa41e37e2163c387f96a75 (Powershell script)B3428248caa364461d4521e2ff3c853228c38f9dc2fb5bcc9049e6652bb94ba2 (Lumma payload)B33648806f28bae6d57103a2081df7d8e8dd03db586c03057f9c60e9ac3b2bc0 (Lumma payload)101e4eabfde77d3a2d3877042a72bed101973d0c511ba031e6e27785d48f61fd (GOO.dll)A7f7a3c408c4839fb2dc28b7fc99f64f464d4e1aeedd75293937769626962c18 (GOO.dll)
原文始发于微信公众号(Ots安全):揭开不断演变的威胁:深入研究最新版本的 Lumma InfoStealer 及其代码流混淆技术
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论