银狐木马虚拟机分析日报
1. 缘起:从 Edge 下载的“deepseek 电脑版”
这次分析的样本来自 Edge 搜索下载的所谓“deepseek 电脑版”。把它放进隔离虚拟机后,表面上几乎没有任何动作:没有明显窗口、没有稳定的网络行为、连预期中的安装流程也没有出现。
起初怀疑是样本损坏。后来结合静态分析的入口结构和系统重启后出现的异常,才怀疑它存在虚拟机环境检测,并进一步发现它释放了驱动级组件、修改了系统代码完整性策略。整个过程并不顺利,但留下的证据链比较完整,值得整理成一篇日报。
2. 启动路径:一段可疑的运行时初始化
样本的入口 start 非常短,只做了三件事:
1 | start |
sub_14001CE6C 依次调用 GetSystemTimeAsFileTime、GetCurrentProcessId、GetCurrentThreadId、GetTickCount 和 QueryPerformanceCounter,把这些结果异或组合成一个运行时值,保存在 qword_14003D0A8,同时在 qword_14003D0B0 保存它的按位取反结果。
单看这段代码,它更像安全 cookie / 运行时值初始化,并不能单独证明存在虚拟机检测。真正引起怀疑的是后面的启动路径:
1 | sub_140001106 |
在虚拟机中运行原始文件时,样本没有继续表现出明显行为。为了确认这个条件分支的含义,我在隔离环境中做了一次最小 patch 实验。
3. 验证分支含义:一次最小 patch 实验
方案 A 很直接:把 test rax, rax 后面的
1 | jz short loc_14000112F |
改成两个字节的 NOP NOP(90 90),让“检测失败”也不再跳向退出分支:
1 | call sub_14000113C |
最初的担心是样本存在内存完整性校验:进程启动后会校验 .text 段内存是否与磁盘原始内容一致,一旦发现被 patch 就判定篡改并退出。实际测试发现该样本没有 CRC 校验,修改后成功在虚拟机中继续运行。
调试器中的观察也印证了这一点:在 install_q0_3_02+0x166a8 下断,单步进入 sub_14001CE6C 后 rax=00002b992ddfa233,qword_14003D0A8 与取反值均已初始化;随后跳入 sub_140001106,当 sub_14000113C 返回 rax=2 时,test rax, rax 后不会走退出分支。
这个实验支持“启动条件判断 / 环境检测”的假设,但必须保持克制:它只能证明该分支控制样本是否继续执行,不能单独断言样本只检测虚拟机。条件判断可能混合了调试器、系统版本、权限、网络或其他运行环境特征。
4. 一次代价很高的失误
确认启动分支后,我继续运行样本,却没有提前在关键位置设置足够的断点和行为监控。结果样本跑飞,感染了虚拟机并自动重启。
这次失误的教训很直接:“能跑起来”并不等于“值得继续跑”。对驱动级样本,运行前必须准备好快照、行为监控和关键点断点,否则一次误操作就会污染整个实验环境,让后续分析从“分析样本”变成“处理事故”。
5. 重启后的异常:驱动加载被代码完整性策略拦截
重启之后,虚拟机中的 SnowSword 驱动加载出现异常,用户态调用 ZwLoadDriver 返回 0xC0E90002,但用户态功能尚可使用。同时,干掉了银狐驱动 ranchserv.jpg 的服务后,它还会被自动拉起。
奇怪的是,挂上 WinDbg 后,同一个驱动又表现为可以加载。这个差异不能简单归结为“驱动文件时好时坏”。沿着内核加载路径下断点,经过 NtLoadDriver → IopLoadDriverImage → IopLoadDriver → MmLoadSystemImage 后,WinDbg 直接给出了关键提示:
1 | violated SI policy, will fail to load for scenario 0 ! |
这说明加载失败是由 SI(代码完整性)策略拦截导致的,而不是文件损坏或注册表缺失;BD 可以理解为内核调试器附加状态。调试器附加后允许加载,恰好解释了“普通启动失败、挂 WinDbg 成功”的表象,但它不能证明驱动签名有效,也不能证明系统策略已经恢复。
6. CodeIntegrity 日志与 SiPolicy.p7b 时间戳
在 Microsoft-Windows-CodeIntegrity/Operational 日志中,SnowSword.sys 对应了两类关键事件:
- 事件 3077:代码完整性判断该驱动不满足 Authenticode 签名级别要求,或违反了当前代码完整性策略(Policy ID:
{a244370e-44c9-4c06-b551-f6016e563076}); - 事件 3004:系统无法验证映像完整性,提示找不到文件哈希,可能是签名错误、文件损坏或未知来源软件。
日志时间覆盖 2026/8/27 16:29、17:23 和 2026/8/28 7:27、7:30,被加载对象均为 C:\Users\21607\Desktop\SnowSword.sys。
查看 System32\CodeIntegrity 目录时,SiPolicy.p7b 的大小为 24,972 字节,LastWriteTime 为 2026/8/27 17:54:50,明显晚于同目录下其他代码完整性策略文件。结合样本已经具备修改文件、注册表和内核状态的高风险能力,可以提出一个较强的分析判断:系统代码完整性策略文件被样本篡改,或者至少被置于与干净系统明显不同的状态。不过,在没有同版本干净系统基线、文件哈希和签名链之前,仍应把它表述为“基于现有证据的高度疑似篡改”,而不是绝对结论。
如果需要恢复,正确做法是从干净的同版本 Windows 10 机器导出出厂默认策略,替换虚拟机中被篡改的 SiPolicy.p7b。同时要注意 EFI 分区中仍保留 SiPolicy.p7b 的副本,需要一并修改,否则启动链可能继续使用被篡改的策略。
7. 伪装驱动 ranchserv.jpg 的接口
样本释放出的一个关键文件名是 ranchserv.jpg。从扩展名看它像图片,但实际被当作驱动文件加载。对这个驱动的派遣函数反编译后,可以看到它根据 IRP_MJ_DEVICE_CONTROL 的控制码分派不同功能,其中三个接口尤其值得关注:
| 控制码 | 行为 | 潜在风险 |
|---|---|---|
0x22E04C |
接收文件路径,打开文件后执行未公开操作 | 可篡改文件内容、清零 PE 头或签名,导致目标驱动被内核判定为无效镜像 |
0x22E048 |
打开并操作注册表键 | 可删除或修改安全工具的服务项,或修改驱动加载相关注册表配置 |
0x22E014(材料标注) |
向某个内核结构中的函数指针数组写入任意值 | 若该结构是文件系统过滤回调、映像加载通知或对象管理器回调,可挂钩或破坏驱动加载路径,使安全工具驱动加载被拦截或返回错误 |
此外,0x22E044 附近还有版本查询分支,会向调用方返回 2.0.2 之类的字符串;其余分支则处理数据复制、结构初始化等操作。
这个接口集合解释了后续现象:如果攻击者通过用户态客户端向该驱动传入 ARK/HIPS 驱动文件路径,它可以清零 PE 头或篡改签名;如果传入注册表路径,它可以破坏安全工具的服务项;而内核结构写入能力则可以直接干预驱动加载路径,使安全工具在加载阶段就被拦截。
8. 隐藏与对抗:安全模式下仍然看不见
分析过程中还发现了一个隐蔽手法:在安全模式下,即使勾选“显示隐藏文件”,C:\ProgramData 的普通 dir 也看不到银狐的可执行文件,只能看到 Dbg、Huorong、Microsoft 等常规目录。
使用 dir /a 后,才暴露出:
1 | C:\ProgramData>dir /a |
原因是被设置了“系统”+“隐藏”双重属性:只勾选“显示隐藏文件”不足以看到它们,必须同时勾选“显示系统文件”才会显形。
处置时,删除文件后不能直接留空,否则服务或残留进程可能会把它重新创建。更稳妥的做法是:删除后用同名空目录占位,取消 SYSTEM、Everyone 和当前账户对该空目录的全部访问权限,并把目录所有者设为 SYSTEM,让恶意组件既无法重建文件,也无法通过目录权限写入新副本。
9. 处置思路与证据保全
样本已经执行过驱动级动作并触发自动重启后,继续在原虚拟机中“修修补补”并不是优先选择。更稳妥的顺序是:
- 立即断开网络,保存虚拟磁盘、内存和事件日志副本;
- 记录服务项、驱动文件路径、文件哈希、创建时间和签名验证结果;
- 对
CodeIntegrity/Operational、System、Service Control Manager 和启动日志做时间线整理; - 使用可信来源重新建立同版本系统快照,再对比
System32\CodeIntegrity及 EFI 分区中的策略文件; - 只有在证据已经保全后,才在副本上进行策略恢复和驱动加载验证。
恢复策略时应使用与目标系统版本和补丁级别匹配的可信基线,并先确认恢复操作不会破坏取证证据。EFI 分区中的副本也需要纳入检查范围;只替换系统目录中的单个文件,不能自动证明启动链已经恢复。恢复后应重新启动并复核代码完整性事件、策略状态和驱动签名,而不是只看一次 ZwLoadDriver 返回值。
10. IOC 与复核清单
目前能确认或需要重点复核的线索包括:
| 类型 | 线索 |
|---|---|
| 伪装驱动 | ranchserv.jpg,实际按驱动用途加载;对应服务被删除后会被自动拉起 |
| 可疑样本 | 从 Edge 搜索下载的所谓“deepseek 电脑版”安装包(调试符号名 install_q0_3_02)及其释放文件 |
| 落地文件 | C:\ProgramData\Oaxs10zK.exe(2,949,632 字节) |
| 随机目录 | C:\ProgramData\ePq5kdxo、C:\ProgramData\VMHKT1Zo |
| 系统影响 | 自动重启、ZwLoadDriver 返回 0xC0E90002、SnowSword 驱动加载异常、ranchserv.jpg 服务自动拉起 |
| 完整性日志 | CodeIntegrity 事件 3004、3077(Policy ID:{a244370e-44c9-4c06-b551-f6016e563076}) |
| 关键策略文件 | System32\CodeIntegrity\SiPolicy.p7b(24,972 字节,2026/8/27 17:54:50)及 EFI 分区对应副本 |
上表中的路径和文件名来自本次环境记录,不能直接当作通用 IOC。实际处置时还应补充 SHA-256、签名证书链、服务注册表路径、父子进程关系和网络连接记录,并在多个时间点重复采集,避免把残留文件误当成当前活动组件。
11. 复盘:这次不会忘记的几件事
- 在运行样本前先做快照,并准备第二份只读分析副本;
- 先建立基线,再运行样本,至少记录驱动、服务、代码完整性策略和启动项;
- 关键分支、服务创建、驱动加载和重启触发点必须提前布置观测手段;
- 不把反编译器命名当成事实,所有高风险结论都要结合交叉引用、调用栈和系统日志;
- “挂调试器后可以加载”只说明调试上下文改变了系统行为,不表示样本或驱动可信;
- 对驱动级样本,恢复快照通常比在已感染系统中继续操作更可靠;
- 排查隐藏文件时,要同时勾选“显示系统文件”,不要只依赖“显示隐藏文件”。
总结
从目前证据看,这个银狐样本至少表现出三条值得警惕的线索:使用图片扩展名伪装驱动、通过高权限接口修改文件/注册表/内核状态,以及根据运行环境决定是否继续执行。随后出现的自动重启和 SnowSword 驱动加载失败,则把样本行为与系统代码完整性策略异常联系到了同一条证据链上:SiPolicy.p7b 的时间戳晚于其他策略文件,CodeIntegrity 日志持续报告 3077/3004,WinDbg 明确提示 SI policy 拦截,而 ranchserv.jpg 恰好具备能够造成这些影响的文件、注册表和内核写入能力。
安全分析仍然需要克制。一次虚拟机实验可以提出假设,却不能替代完整取证;一次日志告警可以指出策略冲突,却不能单凭时间戳证明所有文件都由同一个样本修改。只有把静态分析、运行时观测、代码完整性日志、可信基线和快照前后差异放在同一条证据链上,才能更接近可靠结论。
下一步会在全新快照中补齐文件哈希、服务时间线和策略文件签名信息,并继续完善 SnowSword 对异常驱动和代码完整性事件的关联展示。
相关项目与联系
项目SnowSword —— Windows 10/11 x64 内核分析与 Anti-Rootkit 工具,源码与发布包在 Gitee。
技术合作Windows 内核 / 驱动开发 / 逆向分析 / 兼容性开发,范围与边界见 技术合作。
联系2160752730@qq.com · QQ 2160752730 · 微信 lst_3258110
