文章总结: 本文测评了一款Windows版Rootkit开源提示词生成的样本,该样本具备进程伪装、网络隐藏、文件隐藏、注册表隐藏、驱动镜像写回及驱动对象伪装等能力,代码量近5000行。测试发现其依赖关闭PatchGuard,存在硬编码偏移跨版本易崩、依赖未公开结构、卸载不干净等坑点。文章提供了检测思路与测试环境建议,指出该提示词可快速生成PoC骨架但未达工程标准。
综合评分: 85
文章分类: 恶意软件,逆向分析,红队,漏洞分析,安全工具
粉丝投稿: 对一款Windows木马开源提示词的测评
原创
刃无锋
刃无锋
轩公子谈技术
2026年9月30日 17:19
江苏
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
事情的起因是在大概2周前看到了v2ex上的一篇文章《我去,发现个好玩的,现在病毒木马都开始开源提示词了?》
我当时就进行了测试,还挺感慨的,本来打算立即写两篇测评文章,但是因为各种事情一直忙,就拖到了现在。简单说就是,木马没开源,但开源了提示词。开源提示词这事儿在今年年初就有这个苗头了,但是现在连木马开始都这么干了,感觉有蔓延的趋势。本篇文章是基于其中Windows版 Rootkit 提示词进行的实际测评和分析,下一篇会对Linux版的Rootkit提示词进行测评分析。
提示词相当工程化,怎么说呢,花费了大概3个多小时的时间才完成项目的最初版本,当然,这中间涉及到环境搭建。通过投喂AI提示词,确实生成了一个内核版本的Rootkit,而且可以伪装进程、隐藏文件、服务、注册表、网络,甚至会对内核文件自身进行伪装,功能齐全且强大。但是坑点也还是有的,反正我的测试机蓝屏了。
源码分析
样本功能
Windows版的提示词为“azure-wdm-agent-prompt.md”,原始文档是英文的,我英语不好,先翻译成了中文。文档中并未直接告诉AI生成的内核项目是什么名称,所以项目名称根据AI的发挥随机进行项目起名。项目能力和实现原理大致如下:
| 能力 | 模块 | 实现手段 |
| — | — | — |
| 进程 PID 伪装 | PidSpoof.c | 直接改写 EPROCESS.UniqueProcessId 为 4 |
| TCP 连接隐藏 | NetHide.c | Hook nsiproxy 的 IRP_MJ_DEVICE_CONTROL,在完成例程里压缩 TCP 表 |
| 文件/目录隐藏 | PathHide.c | MiniFilter:CREATE 返回 NOT_FOUND,目录枚举就地压缩 |
| 注册表键隐藏 | RegHide.c | CmRegisterCallbackEx:PreOpen 返回 NOT_FOUND,PostEnumerate 跳过子键 |
| 驱动镜像写回 | WriteBack.c | 加载时把 .sys 缓存进非分页池,关机/休眠时写回原路径 |
| 驱动对象伪装 | DriverObjectSpoof.c | 克隆 \Driver\Null 的 _DRIVER_OBJECT 元数据 + LDR 节点 |
首先对DriverEntry进行分析,代码很少,逻辑清晰
进程伪装
该样本并不是对进程进行隐藏,而是通过修改内核EPROCESS的UniqueProcessId字段,实现进程伪装,在本次测试中,伪装的PID始终为系统进程(PID=4)。首先是通过硬编码各个Windows版本的UniqueProcessId字段在EPROCESS下的偏移,如果不确定是哪个系统,统一当Win7处理。老实说,就这逻辑,也就AI干得出来,是个人都不敢这么写,否则早被公司开了。
修改EPROCESS实现伪装
网络隐藏
这部分在我看来,是难度较大的,Hook nsiproxy 的 IRP_MJ_DEVICE_CONTROL,但是NSI 的这些结构是未公开的。安装HOOK:用 ObReferenceObjectByName + *IoDriverObjectType 按名字拿到驱动对象,然后原子替换MajorFunction[IRP_MJ_DEVICE_CONTROL]。保存旧指针以便卸载时恢复;替换时用 InterlockedExchangePointer 而非直接赋值,确保多核并发下的原子写入,避免写撕裂(而非防止其他 hook 覆盖)。
之后注入完成例程,完成例程部分关键代码如下:
之后进行表压缩,TCP 表、状态表、PID 表是三个平行数组,删除一行必须三张表同时压缩,否则 PID 会错位到别的连接上。NhRemoveRow 用 RtlMoveMemory 把后续行整体前移。pidValid 的设计也很谨慎:PID 表缺失时 ByPid 规则一律不匹配,否则一张不存在的表会退化成人人命中,把整张连接表清空。
文件/目录隐藏
没什么好说的,就是通过Minifilter进行过滤
服务/注册表隐藏
通过注册注册表回调来实现注册表的隐藏,由于系统服务也存在于注册表中,所以同时可以实现对服务的隐藏。
配置里允许写人类习惯的 HKLM\...,回调里看到的却是 \Registry\Machine\...。把映射关系做成一张表(而不是 if/else 链)使扩展成本很低。转换函数还处理了两个边界。
因为注册表回调 API 没有提供「跳过这一项」的便利返回,跳过隐藏子键只能重写枚举结果。做法是:拿到当前项的索引,从 Index + 1 开始自己调 ZwEnumerateKey(用重入保护避免递归),找到第一个不隐藏的项,把它拷进调用者的缓冲并修正 ResultLength。
关机回写
关机回写的前提是,需要先将驱动文件本身复制一份到内核内存,文件路径从 DriverObject->DriverSection 指向的 LDR 节点里取。深拷贝成 NUL 结尾的独立缓冲是必要的,毕竟UNICODE_STRING 本身不保证NUL 结尾,而后面 ZwCreateFile 要用它。
写入过程中,用 InterlockedCompareExchange 确保同步——关机路径和电源回调可能同时触发,必须防止两个线程同时 FILE_OVERWRITE_IF 打开同一个文件。
至此,源码的原理分析基本结束,虽然分析看着简单,但实际上代码量达到了接近5000行,从个人项目来讲,已经算是个不小的项目了。就整个项目而言,采用的技术中规中矩,基本都是公开技术,但综合在一起,形成了一个全方位隐匿的高对抗性样本。
测试环境与监控工具
复现与监控需要一套完全隔离、可回滚的环境,以下是我的实践建议,读者可作参考(务必全程在虚拟机快照内进行)。
环境
- 虚拟化:VMware Workstation 或 VirtualBox,安装 Windows 10 22H2 / Windows 11(与 WDK 目标版本一致)
- 编译:Visual Studio 2022 + WDK(或 EWDK),配套同版本 SDK
- 调试模式:
bcdedit /set testsigning on与bcdedit /set debug on打开测试签名与内核调试。注意这会关闭 PatchGuard,后文”坑”里 PG 冲突的结论需与”关 PG 不蓝屏、开 PG 蓝屏”对照理解
监控工具(按用途分类)
| 用途 | 工具 | 说明 |
| — | — | — |
| ARK / 进程树 | PCHunter(XueTr)、System Informer(原 ProcessHacker) | 识别进程伪装、驱动对象异常 |
| Rootkit 专项 | GMER | 本文实测默认扫描无发现 |
| 内核对象 | WinObj (Sysinternals) | 查看 \Driver、\Device 异常对象 |
| 驱动枚举 | Autoruns、driverquery、sc query | 枚举已加载驱动/服务 |
| 注册表 | Process Monitor (ProcMon) | 抓注册表回调前后的可见差异 |
| 文件系统 | Process Monitor + WizTree | 抓 MiniFilter 前后的枚举差异 |
| 网络 | Wireshark + npcap、TCPView | 抓 TCP 表与真实连接的对照 |
| 驱动日志 | DebugView (DbgView) | 捕获 DbgPrint 输出 |
| 杀软对照 | 火绒剑 / 火绒等任意三款杀软 | 记录是否报毒 |
监控思路
核心是对照法:普通工具(ProcMon / TCPView)看到的视图,与 ARK / 内核工具看到的视图相减,差异处即隐藏点所在。例如本文中 System 进程多出一个、驱动对象服务名为空,就是伪装动作留下的特征残留。
如何检测
我在测试机中做了实验,尝试了国内3款杀毒软件,都没啥反应,于是尝试手工检测。
通过Gmer进行Rootkit检测(检测的默认行为),完全没有发现
但是比较明显的是,该样本会将目标进程伪装为系统进程(PID=4),所以通过ProcessHacker可以看到异常,系统中出现两个System进程
但从属性上无法区分真假
但通过XueTr(也就是PCHunter)可以看到恶意进程
对于内核的检测,由于其会固定将自身伪装为系统的NULL.sys,所以是可以通过PCHunter等ARK工具检测到异常的,很明显,伪装终究是伪装,不可能面面俱到,驱动对象和服务名是空的,对于系统服务来说,这不正常。
也可以给通过文件名排序,发现异常的内核驱动
提示词中的坑
提示词并非”一键出活”,生成结果落地时问题不少,这里列几类(均需在开启 PatchGuard 的干净快照下复验):
- PatchGuard 冲突(最致命):
_DRIVER_OBJECT克隆与 LDR 节点伪装属于典型 PG 敏感区,一旦 PatchGuard 开启就会触发蓝屏,这也是本次测试机蓝屏的直接原因。这意味着此类样本的”可用性”高度依赖关闭 PG /开启测试签名,严格环境下存活率存疑。 - 硬编码偏移跨版本易崩:EPROCESS 字段偏移按版本硬编码,兜底逻辑”统一当 Win7 处理”,说明生成代码对版本分支覆盖不足,换个内核小版本就可能写错内存导致蓝屏。
- 依赖未公开结构:NSI 的连接表结构、LDR 节点布局均为逆向得到的未公开结构,系统打补丁后即失效,需逐版本重新适配。
- 卸载不干净:Hook 恢复依赖保存旧指针,但完成例程注入、回调注册若拆解顺序不当,会残留不稳定状态甚至再次蓝屏。
综上,该提示词的价值在于快速生成一个”技术面立体、能跑通”的 PoC 骨架,但达不到”一键交付”的工程标准,落地仍需人工修正版本适配与对抗细节。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:轩公子谈技术 刃无锋
刃无锋《粉丝投稿: 对一款Windows木马开源提示词的测评》