面向即时通讯工具的输入伪装与检测绕过:银狐类生态中 Hook 组件的技术迭代
腾讯安全威胁情报 2026-09-09 19:33 上海

无 PE 头内存样本切入,揭秘银狐 Hook 输入来源接口、伪装硬件操作及持续升级加载器对抗的技术演进链路。
开篇
SEO 投毒、高强度对抗、拉群扩散,这些都是银狐组织的典型传播手法。现今成熟的即时通讯工具会对系统环境和用户输入的真实性进行校验,使简单的模拟点击和自动发消息难以直接奏效。银狐样本如何绕过这些校验,将自动化操作伪装成真实用户行为?
最近我们从沙箱集群捕获了一个高度可疑的无 PE 头内存 dump ,沿代码特征逐层扩线,最终定位了样本来源于银狐家族,并且深入还原了银狐类生态中面向即时通讯工具的 Hook 组件技术迭代。我们根据关联特征捕获到了多个早期关联样本,这些样本与 2026样本共享同一个核心手法:Hook Windows 输入来源查询 API,把软件合成输入改归为硬件输入类别;基于功能丰富度和构建时间可以推测出一条演进关系。围绕这个核心,设计者在不同版本间动态调整验证封堵和自隐藏策略,并在 2024-05 版将防护对抗上移到独立的外层加载器。
核心发现
• 我们定位了样本注入即时通讯工具绕过检测的核心机制:通过 Hook
GetCurrentInputMessageSource把IMO_INJECTED合成输入改写为IMO_HARDWARE硬件输入类别,绕过即时通讯工具对自动化输入来源的校验。2026样本与 Hunt 到的早期样本均共享此特征• 我们通过特征溯源识别到多个早期版本:版本之间的迭代呈现出极强的对抗适应性
• 我们通过IOC溯源定位样本来自银狐组织,以中等置信度归为银狐类一致活动,明确排除具有国家背景的APT行为体
调查起点:一个无 PE 头的内存 dump
2026年7月,我们从威胁情报沙箱集群捕获了一个高度可疑的样本,运行过程中释放一个无PE头的内存dump。我们的调查从这里开始。文件 shellcode.bin 大小 114,688 字节(0x1C000),SHA-256 e5a9de2b6dad1cd9005e816965c047c6441e194e52759d24c50b9512fbdfd491,文件偏移 0 直接是正常 x86 函数序言而非 PE DOS 头。这是一个加载后 x86 DLL 从 RVA 0x1000 起的连续内存映像,缺少首个 0x1000 PE 头页,不能作为完整 PE 或独立 shellcode 运行。
通过代码中的绝对地址引用可反推 ImageBase = 0x16FE0000,文件偏移 0 对应 VA 0x16FE1000。由于 PE 头缺失,节边界由绝对地址引用、链接器 section-contribution 元数据和内容类型共同恢复:

dump 中可见 .detour、.dogec、.doged 节名和 MSVC CRT 相关字符串,说明模块静态链接了 Microsoft Detours。.dogec / .doged 是样本对 Detours 上游 .detourc / .detourd 数据节的改名,非微软默认节名。它们说明 Detours 代码谱系,但单独不能判恶,合法使用 Detours 的软件也可能存在这些节。
5 个 API 名、注册表路径、value 名和 mutex 并非明文保存,而是由栈上常量经 SSE/XOR 临时解密。普通 strings 看不到它们。dump 中偶然出现的明文 Policy 来自 CRT 字符串 AppPolicyGetProcessTerminationMethod,不能当作恶意 value-name 的明文证据。
文件偏移 0x15D98 存在宿主进程路径明文。该字符串更可能是 CRT/运行时进程路径状态,只能证明 dump 与 32 位即时通讯工具进程环境有关,不能单独证明固定投递目标或初始入口。
Hook 组件的技术演进与样本关系
2026样本的分析:三层防御规避体系
下文将捕获的样本称为 2026样本。它在所有已知样本中功能最丰富,在被注入进程内构建了三层防御规避体系:输入来源伪装、Raw Input 交叉验证封堵、TCP 连接表自省欺骗。这个版本没有编译时间戳,无法确定其具体出现的时间,但活跃时间明显定位在 2026 年的时间窗口。三层规避机制叠加的目标是在被注入进程内制造一个自洽的可信操作环境。
核心层:GetCurrentInputMessageSource 输入来源伪装
Hook 位于 VA 0x16FE1740,精确行为如下:
BOOL hook(INPUT_MESSAGE_SOURCE *source) {
BOOL result = real_GetCurrentInputMessageSource(source);
if (source->originId == 2) // IMO_INJECTED
source->originId = 1; // IMO_HARDWARE
return result;
}Windows 中 INPUT_MESSAGE_SOURCE.originId 标识输入来源:IMO_INJECTED (2) 表示普通非 UIAccess 应用通过 SendInput 注入的合成输入,IMO_HARDWARE (1) 表示硬件设备输入或由 UIAccess 应用注入。样本把普通软件注入输入改归为硬件/UIAccess 来源类别。
上述行为可直接从样本字节复核。值 1 代表硬件或 UIAccess 来源类别,不严格等于物理硬件。样本不生成输入、不记录键盘,也不改变底层设备事件。让目标进程把 SendInput 注入的合成输入判定为硬件输入,可能直接绕过即时通讯工具对自动化输入来源的校验,但样本中没有宿主检测函数可证明具体绕过对象。
交叉验证封堵层:GetRawInputData 屏蔽
仅有输入来源伪装不足以应对具备交叉验证能力的宿主。Hook 位于 VA 0x16FE1990,精确行为如下:
UINT hook_GetRawInputData(..., PUINT pcbSize, ...) {
if (pcbSize != NULL)
*pcbSize = 0;
return 0;
}Hook 不调用真实 API,直接将输出参数 pcbSize 置零并返回 0。这一行为可直接从样本字节复核。GetRawInputData 是应用获取 Raw Input 原始数据的唯一用户态接口,无论调用方查询所需缓冲区长度还是读取实际 RAWINPUT 数据,都会得到零长度,即没有原始输入数据可读。
这一机制与输入来源伪装配合:宿主检测到 GetCurrentInputMessageSource 返回硬件输入类别,但 GetRawInputData 读不到对应的原始硬件事件数据,交叉验证通道即被封堵,输入伪装的假象在进程内自洽。该功能是屏蔽 Raw Input 交叉检查,不是键盘记录。
网络环境自省欺骗层:三个 TCP 表 Hook
第三层针对宿主进程对自身网络环境的自省检查。三个 Hook 分别位于 VA 0x16FE1A70(GetTcpTable)、0x16FE19B0(GetTcpTable2)和 0x16FE1760(GetExtendedTcpTable),共享相同逻辑:
status = real_api(...);
if (status == NO_ERROR) {
for each IPv4 row {
if (row.dwState != MIB_TCP_STATE_LISTEN)
row.dwRemoteAddr = generated_private_address;
}
}
return status;伪造地址字节为 0A, rand()%256, rand()%256, (rand()%252)+2,显示为 10.x.x.[2..253],每次以 time(NULL) / srand 初始化随机种子(非密码学随机)。三个 API 的结构差异如下:

上述行为可直接从样本字节复核。Hook 只修改被注入进程的用户态返回缓冲区,端口、PID、TCP 状态、内核连接、真实报文和外部 EDR 视图不变。这三个 API 不是网络客户端,不能证明 DLL 创建了 socket、发送数据或连接 C2。宿主进程检查自身 TCP 连接表时,看到的远端全是 10.x.x.x 私有地址。
2026样本功能组合的整体效果
2026样本同时具备输入来源类别改写、Raw Input 查询屏蔽、进程内 TCP 表远端 IPv4 欺骗、当前小时 Policy 门禁、mutex 单实例和 Detours Hook 安装/卸载。三层叠加后,被注入进程的视图是:输入来自硬件、没有 Raw Input 矛盾、网络连接远端是内网地址。上述功能均可由样本字节直接复核。组合用途高度符合绕过即时通讯工具对自动化输入、远控输入或运行环境风险的交叉检查,但样本中没有宿主检测函数或操作者配置可证明具体绕过对象。外部 EDR、内核遥测或另一个未被注入的进程仍可看到真实情况。

2024-03 版:精简与自隐藏
依据 2026样本中的 Detours 节名特征、注册表门禁代码和 Hook 语义组合,我们提取特征进行样本狩猎(Hunt),获得两枚 2024-03-13 编译的 x64 DLL。这是目前已知最早的编译版本:

两文件加载后的有效映像和行为相同,是同一构建的四字节尾部变体。
功能变化:输入伪装不变,引入自隐藏,不具备封堵层
2024-03 版与 2026样本共享核心 GetCurrentInputMessageSource Hook(VA 0x180001000),originId 2 → 1 的改写逻辑逐字节一致。2024-03 版额外引入 Module32NextW Hook(VA 0x180001030):
// 伪代码
BOOL hook_Module32NextW(HANDLE snapshot, LPMODULEENTRY32W me) {
BOOL result = real_Module32NextW(snapshot, me);
if (result && wcscmp(me->szExePath, own_dll_path) == 0) {
return real_Module32NextW(snapshot, me); // 跳过自身,再取下一项
}
return result;
}Module32NextW 是 Toolhelp 进程/模块快照枚举的核心 API。当枚举结果的模块路径等于自身 DLL 路径时,Hook 再调用一次真实 API 跳过自身,使该 DLL 不出现在进程的模块枚举结果中。
上述行为可直接从 DLL 字节复核。Hook 只影响调用该 API 的当前进程的 Toolhelp 枚举结果,不会从内核、EDR、内存扫描或其他模块枚举机制中全局消失。即时通讯工具或其安全模块用 Toolhelp 遍历自身加载的 DLL 列表时,该 DLL 会从列表中消失。
2026样本具备 Raw Input 屏蔽和三个 TCP 表 Hook,2024-03 版不具备这两项功能。
Oreans-family VM 保护入口跳板
DLL 入口附近使用 Oreans-family 控制流虚拟机保护启动跳板。PE entry 位于 0x180004008,VM 链为 0x180004040 → 0x180036A2B → 0x18004B5C1,DLL_PROCESS_ATTACH 路径执行 36,006 条 VM 指令后到达 CRT entry 0x180003ED4。还原后入口语义仅为:
BOOL RecoveredDllEntry(HINSTANCE module, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH)
__security_init_cookie();
return _DllMainCRTStartup(module, reason, reserved);
}上述还原结果可由离线仿真轨迹直接复核。.m<g 是 Oreans-family 控制流 VM,主要保护 DLL 启动跳板,不是隐藏第二个网络载荷的自解密容器。还原后的业务逻辑中没有第二个网络模块,也没有支持 getaddrinfo 解出 C2 的调用路径。分析方式使用受控离线 CPU 仿真器解释入口指令语义,未在宿主 Windows 原生加载/运行或联网。
设计意图推断
2024-03 版面向不做 Raw Input/TCP 自省检查的目标环境,只需绕过输入来源校验和模块枚举检测即可。任务分工有所调整,部分验证封堵交由上游组件完成。
2024-05 版:极简核心 + 外层强化
2024-05-07 编译的双架构 DLL 及其外层 loader 是目前已知最晚的构建版本。DLL 本体缩减至只剩输入来源伪装这一个核心 Hook,防护对抗和注入能力全部上移到独立的外层加载器(loader)。
DLL 本体:仅具备输入来源伪装
内嵌 x86 DLL(SHA-256 97965e9127928d0a0d387ed211f356d78cc0fca2e307cc4dfe08674f147035ad,链接时间 2024-05-07 12:12:59 UTC)和 x64 DLL(SHA-256 8d6af90b48574e8f6d3c46dc60893e49d9bd1ae53e73eb948839b3b5bc16fac5,链接时间 2024-05-07 12:10:22 UTC)相隔 157 秒构建,使用 Microsoft linker 14.29,无导出、无 TLS callback、无资源载荷和 overlay。
两枚 DLL 的唯一自定义恶意功能是当前小时门禁、单实例 mutex 和 GetCurrentInputMessageSource Hook。attach 路径如下:
BOOL payload_attach(void) {
if (DetourIsHelperProcess())
return TRUE;
if (!policy_gate())
return FALSE;
mutex = CreateMutexA(NULL, FALSE, "AAAAAAAAAAAAAAAAB");
if (!mutex || GetLastError() == ERROR_ALREADY_EXISTS)
return FALSE;
DetourRestoreAfterWith();
real_api = GetProcAddress(LoadLibraryA("user32.dll"),
"GetCurrentInputMessageSource");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&real_api, hook_wrapper);
return DetourTransactionCommit() == NO_ERROR;
}上述行为可直接从 DLL 字节复核。2026样本具备的 Raw Input/TCP Hook 不存在于这两枚 DLL,2024-03 版的 Module32NextW Hook 也不存在于 2026样本。两枚 DLL 实现相同的源码级行为,仅适配不同进程架构。
外层 loader 接管防护对抗
外层样本 SHA-256 4f3b57fc0d48f9f36ead99d010830f5d84290dc6d4d7e3511101367c0ca67ea8,PE32/x86 GUI,1,589,760 字节,链接时间 2024-05-07 12:27:29 UTC。保护层将原始节内容的 raw size 清零,真实 .text / .rdata / .data / .1Q[ 以四条 raw LZMA1 流(lc=3, lp=0, pb=2, dict=16 MiB)保存在高熵 .sc= 节中。
ApplicationData ChaCha20 门禁
loader 读取 HKLM\SOFTWARE\IMUpdate\ApplicationData(64 位注册表视图,最多 0x100 字节),用标准 20 轮 ChaCha20 解密:
key = 7b2afa6c5f6a06061453bdb5f735e129c131b926ef1bded8e403d6635242745c
nonce = 313939310d0ad6cc954e1a20
counter = 0
rounds = 20解密后逐字节要求:值至少为 2,且不能被 2..sqrt(byte) 中任何整数整除。任一字节非素数即退出。
Defender 排除
loader 的 Defender worker 每 3 秒循环,每第 10 次检查 msmpeng.exe(约 30 秒一次)。发现后用 ShellExecuteA(..., "powershell", ..., SW_HIDE) 隐藏启动:
-c if (Get-Process -Name HAhahaha) {} else {"Add-MpPreference -ExclusionPath $env:localappdata,'C:\','C:\Windows','%s',([environment]::CurrentDirectory) -ExclusionExtension '.png' -Force"}%s 替换为 loader 自身路径。意图是排除 LocalAppData、整个 C:\、C:\Windows、自身文件、当前目录和 .png 扩展名。
代码构造并隐藏启动 PowerShell 的行为可直接从 loader 字节复核,意图是排除 LocalAppData、整个 C:\、C:\Windows、自身文件、当前目录和 .png 扩展名。但字符串放在双引号中可能只产生字符串表达式,即使 cmdlet 被执行,Tamper Protection、策略和权限也可阻止生效。
双架构注入
loader 启用 SeDebugPrivilege 后每 3 秒轮询目标即时通讯工具进程,根据目标位数选择 x86 或 x64 反射注入:
RtlAdjustPrivilege(20, TRUE, FALSE, &old_state); // SeDebugPrivilege
for (;;) {
pid = find_process_by_name("IM.exe");
if (pid && payload_mutex_B_not_alive()) {
write_current_hour_policy();
if (target_is_x86(pid))
inject_x86(pid);
else inject_x64_from_wow64(pid);
}
Sleep(3000);
}x86 目标使用 VirtualAllocEx → WriteProcessMemory → VirtualProtectEx → CreateRemoteThread。x64 目标由 32 位 WoW64 loader 经 Heaven's Gate 解析 64 位 ntdll,调用 NtAllocateVirtualMemory、NtWriteVirtualMemory、NtProtectVirtualMemory、RtlCreateUserThread 完成注入。反射 blob 所有字节静态 +1,使用前 -1 恢复;内嵌 DLL 的 DOS magic 从 MZ 改为 0D 0A 以躲避简单 PE 扫描。外层 mutex 为 AAAAAAAAAAAAAAAAC,注入 DLL mutex 为 AAAAAAAAAAAAAAAAB。
上述注入路径可直接从 loader 代码复核。loader 主动轮询某即时通讯工具的可执行文件,这个目标与 2026样本中的另一个即时通讯工具路径来自不同构建。loader 具备 x86 与 x64 两条完整远程注入路径,调用 Native API,不等于直接 syscall。
设计意图推断
2024-05 版 DLL 极简化,环境准备和防护对抗上移到 loader 层。目标进程不做 Raw Input 交叉验证和 TCP 自省检查,只需绕过输入来源校验即可。loader 接管注入和防护对抗后,DLL 只需保留最小核心功能。

演进关系推测
以下演进关系基于功能丰富度和构建时间的推测。2026样本编译时间未知,三个样本之间仅有同源证据,除 loader→内嵌 DLL 外无直接父子链。2024-03 版与 2024-05 版内嵌 x64 DLL 的 32 字节窗口覆盖率为 .text 67.43%,支持同源码主干不同构建版本的判断,但不支持严格的线性迭代主张。
核心功能:输入来源伪装
GetCurrentInputMessageSource 是三个样本唯一共有的 Hook。从 2024-03-13 的旧 x64 DLL 到 2024-05-07 的双架构内嵌 DLL,输入来源类别改写逻辑(originId 2 → 1)逐字节一致。让合成输入被判定为硬件输入,是整个设计的核心不变需求,直接对应银狐远程控制即时通讯工具发送消息、拉群扩散的操作目标:自动化操作必须通过输入来源校验才能被执行。
变化部分:验证封堵策略的取舍

功能从丰富到精简可以解读为迭代升级,也可以解读为面向不同目标的定制裁剪。现有证据支持同一源码主干的不同构建版本,不支持严格的线性迭代主张。2026样本功能最丰富但编译时间未知,不能仅凭功能丰富度推断其为最早版本。2024-03 版面向具备模块枚举检测的环境,采取自隐藏策略;2024-05 版将 DLL 精简到只剩核心 Hook,防护对抗完全上移到 loader。
攻击链分工的差异
三个样本的攻击链分工呈现明显差异。2026样本 DLL 自带全套功能(Hook + 封堵 + 隐藏),是一个全功能组件。2024-03 版不具备 Raw Input 屏蔽和 TCP 表 Hook,但引入了模块枚举自隐藏。2024-05 版 DLL 只做核心 Hook,loader 负责注入、权限提升、Defender 排除和目标进程轮询。这种分工使 DLL 体量更小、行为更隐蔽,同时 loader 可以复用通用注入框架。
上游仍有缺失:ApplicationData 由未找到的更上游组件写入,4f3... 依赖外部预置的启动凭据,不是已知最初 dropper。
本地样本中未证实的功能
本地样本中未发现键盘记录、账号凭据窃取、屏幕截图、文件窃取或远控协议的任何证据。这套 Hook 组件属于环境准备层,服务于上游自动化操作或远控操作,上层意图需要其他载荷或主机遥测证明。
样本谱系与同源证据
哈希链与关系定位
通过外层 loader 的静态解包和反射 blob 恢复,可以建立从外层到内嵌 DLL 的直接父子关系。同时,2026样本与内嵌 x86 DLL 之间存在强同源关系,旧 x64 DLL 与内嵌 x64 DLL 之间属于同源码主干的不同构建。

上述关系可直接从样本字节和恢复产物复核。4f3... 是 2024-05 双架构载荷直接容器,非 be5 / 7eada 精确文件的母体,也不是已证明的最初 dropper。修复 DLL、reflective blob、静态内存布局和去 VM 副本均为分析派生产物,不能当端点原始落盘哈希。
构建时间线

紧邻构建时间、同一外层直接嵌入、相同业务逻辑三项共同证明 5 月代是一套双架构构建产物。
关联基础设施与组织溯源
我们根据威胁情报数据的样本关联和IOC活跃记录,定位到以下关联的IoC
关联 IoC

上述IoC与样本行为特征整体与银狐类黑灰产投递生态使用云对象存储分发多阶段载荷、再接入 ValleyRAT/Gh0st 衍生远控的技术模式相符。对银狐类生态关联可给出中高置信度。
MITRE ATT&CK 映射

• 注:旧报告使用的 T1562.001 由 T1685 替代;T1562.006 不适合 TCP/Raw Input/模块枚举 Hook,已移除。
检测与防护
IoC 表

检测建议
进程行为
• 伪装为更新组件的进程启动 +
SeDebugPrivilege提权 + 轮询即时通讯工具进程• 隐藏启动 PowerShell 执行
Add-MpPreference• WoW64 进程经 Heaven's Gate 解析 64 位
ntdll
Defender 排除项审计
• 检查
Add-MpPreference排除路径是否包含C:\、C:\Windows、LocalAppData、.png扩展名• 注意:排除项可能已被 Tamper Protection 阻止,需查 Defender 事件日志确认
Hook 检测
• 交叉比对
GetCurrentInputMessageSource返回值与 Raw Input 数据一致性• 检测
GetRawInputData持续返回零长度的异常模式• 比对进程内 TCP 表查询结果与内核/EDR 视图的远端地址差异
小结
本次分析从一个无 PE 头的内存 dump 出发,通过代码特征逐层扩线,定位了银狐类生态中面向即时通讯工具的 Hook 组件谱系。我们获得了三个样本:2024-03-13 编译的 x64 DLL、2024-05-07 编译的双架构 DLL 及外层 loader、以及 2026 年从失陷机器取得的 dump(2026样本)。三个样本共享同一个核心手法:Hook GetCurrentInputMessageSource 把合成输入改写为硬件输入类别,originId 2→1 逻辑逐字节一致。
围绕这个核心功能,各版本的功能组合存在明显差异。2026样本构建了三层防御规避体系(输入来源伪装、Raw Input 屏蔽、TCP 表欺骗),是功能最丰富的全功能组件。2024-03 版引入 Module32NextW 模块枚举自隐藏,不具备 Raw Input/TCP 封堵。2024-05 版将 DLL 缩减至仅输入伪装,防护对抗和注入能力上移到 loader。三个样本之间有同源证据,但除 loader→内嵌 DLL 外无直接父子链,功能差异可解读为迭代升级或面向不同目标的定制裁剪。
这套 Hook 组件属于环境准备层,服务于上游自动化操作或远控操作。本地样本中未发现键盘记录、账号凭据窃取、屏幕截图或远控协议,上层意图需要其他载荷或主机遥测证明。整体与银狐类黑灰产使用云对象存储分发多阶段载荷、再接入 ValleyRAT/Gh0st 衍生远控的技术模式相符。