对一款Windows木马开源提示词的测评

· 2026-09-24 08:54 · 2 阅读

原创 博大爷 2026-09-24 08:54 北京

这是一篇来自老友的投稿。

引言

约两周前,笔者在 V2EX 看到一篇讨论:《我去,发现个好玩的,现在病毒木马都开始开源提示词了?》。文章披露了一个值得警惕的趋势——攻击者不再直接开源恶意代码,而是开源生成恶意代码的提示词(Prompt)。

这一现象并非孤例。早在今年年初,"开源提示词"就已在部分灰产领域出现苗头;而随着大模型代码生成能力的持续增强,如今这种模式已开始向内核级木马蔓延,其潜在危害不容忽视。

出于安全研究目的,笔者对其中的 Windows 版 Rootkit 提示词进行了完整测评。本文即为该测评的详细分析报告,后续将另发文对 Linux 版 Rootkit 提示词进行同类研究。

该提示词工程化程度较高,笔者从投喂到产出可运行样本约耗时 3 小时(含环境搭建)。最终生成的内核 Rootkit 具备进程伪装、文件/服务/注册表/网络隐藏、驱动镜像回写、驱动对象克隆伪装等完整能力,功能齐全且对抗性较强。但同时存在明显缺陷——测试过程中触发了蓝屏(BSOD),并非"一键即用"。


一、样本源码分析

1.1 整体能力矩阵

Windows 版提示词文件为 azure-wdm-agent-prompt.md,原文为英文,笔者已翻译为中文以便分析。提示词未指定生成项目的具体名称,项目命名完全由 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 入口逻辑简洁清晰:

1.2 进程伪装

该样本并未采用传统的进程隐藏思路,而是通过篡改内核EPROCESS结构中的UniqueProcessId字段实现进程伪装——将目标进程 PID 统一改写为系统进程 PID(即 4)。

实现方式为硬编码各 Windows 版本下UniqueProcessId字段在EPROCESS结构中的偏移量,若无法识别当前系统版本,则统一按 Win7 处理。

从工程实践角度,这种硬编码 + 无差别兜底的写法极不严谨,蓝屏风险极高——但这恰恰是 AI 生成代码的典型特征之一:追求"能跑",忽视兼容性与稳定性。

修改 EPROCESS 完成伪装:

1.3 网络隐藏

这部分在我看来难度比较大。其思路是 Hook nsiproxy 驱动的 IRP_MJ_DEVICE_CONTROL 派发例程,而 NSI(Network Store Interface)相关结构均属于微软未公开的内部结构,需要通过逆向分析获得。

Hook 安装:通过 ObReferenceObjectByName + *IoDriverObjectType 按名字获取目标驱动对象,再原子替换 MajorFunction[IRP_MJ_DEVICE_CONTROL],保存旧指针以便卸载时恢复。此处使用 InterlockedExchangePointer 而非直接赋值,说明作者考虑到了其他 Hook 可能同时占用该槽位的场景。

部分关键代码如下::

表压缩是本模块的精妙之处。TCP 表、状态表、PID 表在内核中为三个平行数组,删除任意一行必须同时压缩三张表,否则 PID 会错位到其他连接上。样本采用 RtlMoveMemory 对后续行整体前移完成压缩。

此外,pidValid 的设计极为谨慎:PID 表缺失时ByPid规则一律不匹配——否则一张不存在的表会退化为"人人命中",直接清空整张连接表,导致明显异常。

1.4 文件/目录隐藏

采用标准的 MiniFilter 文件过滤驱动实现,方案成熟、无特别之处,不再赘述。

1.5 服务与注册表隐藏

通过注册表回调(Registry Callback)实现注册表隐藏。由于 Windows 系统服务的配置本身即存储于注册表,因此该机制同时实现了对系统服务的隐藏,一举两得。

配置层允许使用符合人类习惯的 HKLM\... 路径,而回调层实际接收的是 \Registry\Machine\... 形式。样本将路径映射关系设计为查表结构(而非 if/else 链),有效降低了后续扩展成本,转换函数还妥善处理了两处边界情况。

由于注册表回调 API未提供"跳过当前项"的便捷返回值,跳过隐藏子键必须重写枚举结果。样本的做法是:获取当前项的索引,从 Index + 1 起自行调用 ZwEnumerateKey(辅以重入保护避免递归),寻找第一个未被隐藏的项,将其拷贝至调用者缓冲区并修正 ResultLength。

1.6 关机回写机制

关机回写用于确保驱动持久化。其前提是驱动加载时将自身文件复制至内核内存,文件路径从 DriverObject->DriverSection 指向的 LDR 节点中提取。

此处必须进行深拷贝并显式添加 NUL 结尾——UNICODE_STRING 本身不保证 NUL 结尾,而后续 ZwCreateFile 调用依赖此约束。

写入过程使用 InterlockedCompareExchange 保证同步:关机路径与电源回调可能被并发触发,必须防止两个线程同时以 FILE_OVERWRITE_IF 标志打开同一文件。

笔者编的demo样本代码量接近5000 行,对于个人项目已属可观规模。所采用的技术均为公开可查的经典手法,但多种技术的有机整合最终构成了一个具备全方位隐匿能力、对抗性较强的完整样本——这正是 AI 辅助恶意代码开发最值得警惕之处:降低了攻击者整合复杂技术的门槛。


二、检测方法

笔者在测试机中依次尝试了国内 3 款主流杀毒软件,均无告警反应。随后转入手工检测环节。

Gmer(Rootkit 检测经典工具,采用默认检测策略)——未发现异常:

ProcessHacker——由于样本会将目标进程伪装为 PID=4 的系统进程,可以观察到系统中出现两个 System 进程,属于明显异常:

但两者的属性信息基本一致,唯一区别是签名验证的差异,真正的 System 进程签名是严格的 Microsoft Windows 目录签名。

XueTr / PCHunter(ARK 类工具)——可清晰识别出恶意进程:

对于内核层检测:由于样本会固定将自身伪装为系统的 Null.sys(驱动名可以更改,但Null.sys是最优解,只服务 \Device\Null 一个设备),可通过 PCHunter 等 ARK 工具发现异常。伪装终究是伪装,难以做到面面俱到——例如样本的驱动对象名与服务名均为空,而这对于合法系统服务而言是不正常的:

按文件名排序同样可发现可疑的内核驱动:


三、提示词的坑

提示词中隐藏的问题较多,感兴趣的读者可自行测试。笔者遇到的蓝屏问题,根源在于提示词描述的 LDR 节点伪装(驱动伪装)机制与 PatchGuard 存在直接冲突。

因此需要明确:该提示词并不能"一键生成"稳定可用的木马,仍需较强的内核开发功底进行二次调试和适配。

项目地址:https://codeberg.org/sinoboy/kernel-lab-specs

跳转微信打开