原文链接:Getting gooey with GULOADER: deobfuscating the downloader
译者:知道创宇404实验室翻译组
GULOADER 也被称为 CloudEyE,是一类较活跃的恶意软件,表现为一种难以追踪且不断更新的 Shellcode 下载器。Elastic Security Labs发现该恶意软件通过VEH(Vectored Exception Handling)程序中添加异常处理功能,来增强了 VEH 的反分析能力。
虽然 GULOADER 的核心功能在过去几年中保持相对稳定,但其不断进化的混淆技术仍然给安全分析带来了时间和资源上的挑战。本文将从以下方面进行探究:
在我们的示例中,GULOADER 预先打包在 NSIS(Nullsoft Scriptable Install System)安装程序中。当安装程序被提取时,主要组成部分包括:
通过在执行 GULOADER 后监控 SysInternal 的 Process Monitor 事件,可快速定位托管 Shellcode 的文件。在这种情况下, Shellcode 从文件(ReadFileFibroms.Hag)中进行读取。
GULOADER 通过使用不同的 Windows API 函数的回调来执行 Shellcode,而非 WinAPI(如CreateRemoteThread和WriteProcessMemory)进行检测。我们发现 GULOADER 使用了 EnumResourceTypesA 和 CallWindowProcW。
通过检查 EnumResourceTypesA 的 MSDN 文档,可以看到第二个参数需要一个指向回调函数的指针,且新分配的 Shellcode 就放置在这个参数中。
最近,GULOADER 在初始 Shellcode 中增加了不同的无用指令和跳转,这使反分析下载器处理进程更加复杂。这些混淆设计能破坏某些工具的反汇编和控制流,使寻找 Shellcode 的初始调用变得耗时且耗费资源。
一种方法是利用 x64dbg 内的图形视图,自下而上寻找 call eax 指令。
另一种方法是利用反向工程框架 Miasm。以下是一个快速示例,我们可以传入 shellcode 并反汇编指令来跟踪流程:
from miasm.core.locationdb import LocationDB
from miasm.analysis.binary import Container
from miasm.analysis.machine import Machine
with open("proctoring_06BF0000.bin", "rb") as f:
code = f.read()
loc_db = LocationDB()
c = Container.from_string(code, loc_db)
machine = Machine('x86_32')
mdis = machine.dis_engine(c.bin_stream, loc_db=loc_db)
mdis.follow_call = True
mdis.dontdis_retcall = True
asm_cfg = mdis.dis_multiblock(offset=0x1400)
Miasm 通过分析一段包含 142 条指令的代码,识别并导航穿过垃圾指令,这些垃圾指令在 EAX 的调用指令处停止(地址:jmp0x3bde)。
JMP loc_3afd
-> c_to:loc_3afd
loc_3afd
MOV EBX, EAX
FADDP ST(3), ST
PANDN XMM7, XMM2
JMP loc_3b3e
-> c_to:loc_3b3e
loc_3b3e
SHL CL, 0x0
PSRAW MM1, MM0
PSRLD XMM1, 0xF1
JMP loc_3b97
-> c_to:loc_3b97
loc_3b97
CMP DL, 0x3A
PADDW XMM3, XMM5
PXOR MM3, MM3
JMP loc_3bde
-> c_to:loc_3bde
loc_3bde
CALL EAX
VEH 功能是 GULOADER 的一个标志性技术,它可以使 Windows 应用程序在进入标准流程之前进行拦截和异常处理。一些恶意软件与软件保护程序利用 VEH,让分析师和工具程序难以跟踪恶意代码。
GULOADER shellcode 在执行过程中,通过使用 RtlAddVectoredExceptionHandler,故意放置了能触发这些不同异常的代码。当这些异常被触发时,VEH 会检查硬件断点。如果未被触发,GULOADER 会通过 CONTEXT 结构直接修改 EIP,使用每个样本都会变化的字节 XOR 密钥和一个字节的偏移量(从异常发生的地方开始)。我们将在后续部分回顾这种技术的一个具体示例。以下是我们样本的 VEH 反编译:
尽管这种技术并不新奇,但随着时间的推移,GULOADER 会继续添加新的异常;过去几个月增加了以下两种情况:
随着新的异常被添加到 GULOADER,研究人员的加速分析过程工具可能会被破坏。
我们仔细分析了最近添加的两种异常来了解 VEH 的工作流程。第一个异常(EXCEPTION_PRIV_INSTRUCTION)在不被允许的特权级别执行处理器指令时发生。某些指令,如下面的示例 WRSMR,需要内核级别的权限,当程序以用户模式运行时,就会因权限不正确而触发异常。
程序在尝试执行无效或未定义的 CPU 指令时被触发异常,如vmclear 或 vmxon 这类英特尔虚拟化指令。
一旦发生异常,GULOADER 的 VEH 代码将首先确定是由哪个代码导致的。在我们的样本中,如果异常与以下五个中的任何一个匹配,代码将呈现出相同的路径。
接下来,GULOADER 会检查通过遍历位于 EXCEPTION_POINTERS 结构中的 CONTEXT 记录中是否有任何硬件断点。如果在不同的调试寄存器中发现硬件断点,GULOADER 将返回一个 0 到 CONTEXT 记录中,这将最终导致 shellcode 崩溃。
如果没有硬件断点,GULOADER 将检索一个距离引发异常地址 7 字节远的单个字节。以 vmclear 为例,它将检索位于 0x8A 地址的字节。
然后,使用该字节,它将执行一个与不同硬编码字节的 XOR 操作。在我们的案例中(0xB8),这个字节是每个样本独特的。现在,有了一个派生的偏移量(0x32),GULOADER 将直接从 CONTEXT 记录中修改 EIP 地址,通过在引发异常的前一个地址(0xB8 ^ 0x8A)加上 0x32,使下一段代码从地址 0x7697662 开始执行。
在不同的无用指令之间反复触发异常(我们在样本中统计有 229 个独特的异常),不难看出 GULOADER 为什么会破坏不同的工具并增加分析师的工作时间。
为了更容易跟踪控制流,可以通过追踪执行过程、记录异常,并利用之前讨论的 EIP 修改算法来修补 shellcode,从而绕过 VEH。对于这个程序,我们利用了由 hasherezade 编写的 TinyTracer,这是一个利用 Pin(一种动态二进制仪表框架)的工具,能使我们捕获触发异常的不同地址。例如上面的 vmclear 示例,我们可以看到地址是 0x7697630,生成了一个 KiUserExceptionDispatcher 的异常调用,这是一个负责处理用户模式异常的函数。
收集并过滤所有异常后,可以将这些异常传递到 IDAPython 脚本中。在该脚本中,我们遍历每个地址,使用第 7 个字节和 XOR 密钥(0xB8)来计算偏移量,然后用短跳跃来修补产生异常的所有指令。
下图是一个修补触发地址 0x07697630 和 0x0769766C 处异常指令的示例。
下图代表在全局应用修补之前的控制流,包含 vmclear 指令的基本块。通过实施 VEH,GULOADER 扁平化了控制流图,使得追踪程序逻辑变得更加困难。
在使用 jmp 指令修补 VEH 之后,将基本块连接在一起来进行转换,以此降低 shellcode 流程的复杂程度。
使用这种技术可以加快清理过程,但值得注意的是,这并不是一个万无一失的方法。在这种情况下,仍然会有相当多的代码/功能需要分析,但通过移除 VEH,便能大大简化代码。这是完整的 POC 脚本。
GULOADER 具有许多不同的特性,这些特性可以破坏反汇编,阻碍控制流,并使研究人员的分析变得困难。尽管这样,我们仍可以通过不同的静态或动态过程来抵消这些特性,以帮助减少分析时间。例如,我们观察到,即使在 VEH 中增加了新的异常,我们仍然可以追踪并修补 shellcode。这个过程将使分析师进一步访问 GULOADER 的核心功能。
Elastic Security 创建了不同的 YARA 规则来识别这种活动。以下是一个 YARA 规则的示例,用于识别 GULOADER。
rule Windows_Trojan_Guloader {
meta:
author = "Elastic Security"
creation_date = "2023-10-30"
last_modified = "2023-11-02"
reference_sample = "6ae7089aa6beaa09b1c3aa3ecf28a884d8ca84f780aab39902223721493b1f99"
severity = 100
arch = "x86"
threat_name = "Windows.Trojan.Guloader"
license = "Elastic License v2"
os = "windows"
strings:
$djb2_str_compare = { 83 C0 08 83 3C 04 00 0F 84 [4] 39 14 04 75 }
$check_exception = { 8B 45 ?? 8B 00 38 EC 8B 58 ?? 84 FD 81 38 05 00 00 C0 }
$parse_mem = { 18 00 10 00 00 83 C0 18 50 83 E8 04 81 00 00 10 00 00 50 }
$hw_bp = { 39 48 0C 0F 85 [4] 39 48 10 0F 85 [4] 39 48 14 0F 85 [7] 39 48 18 }
$scan_protection = { 39 ?? 14 8B [5] 0F 84 }
condition:
2 of them
}
所有可观察数据也可用于下载,格式包括 ECS(Elastic Common Schema)和 STIX(Structured Threat Information eXpression)。
以下是在这项研究中讨论的可观察数据。
观察对象 | 类型 | 名称 | 参考数据 |
---|---|---|---|
6ae7089aa6beaa09b1c3aa3ecf28a884d8ca84f780aab39902223721493b1f99 | SHA-256 | Windows.Trojan.Guloader | GULOADER downloader |
101.99.75[.]183/MfoGYZkxZIl205.bin | url | NA | GULOADER C2 URL |
101.99.75[.]183 | ipv4-addr | NA | GULOADER C2 IP |
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/3088/