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

admin 2026-10-16 10:16:44 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

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

刃无锋
刃无锋

利刃信安

2026年9月23日 10:00
北京

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

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

事情的起因是在大概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进行分析,代码很少,逻辑清晰

image-20260922154218225

进程伪装

该样本并不是对进程进行隐藏,而是通过修改内核EPROCESS的UniquePorcessId字段,实现进程伪装,在本次测试中,伪装的PID始终为系统进程(PID=4)。
首先是通过硬编码各个Windows版本的UniquePorcessId字段在EPROCESS下的偏移,如果不确定是哪个系统,统一当Win7处理。老实说,就这逻辑,也就AI干得出来,是个人都不敢这么写,否则早被公司开了。

image-20260922161422549

修改EPROCESS实现伪装

image-20260922161627150

网络隐藏

这部分在我看来,是难度较大的,Hook nsiproxy 的 IRP_MJ_DEVICE_CONTROL,但是NSI 的这些结构是未公开的。
安装HOOK:用 ObReferenceObjectByName + *IoDriverObjectType 按名字拿到驱动对象,然后原子替换MajorFunction[IRP_MJ_DEVICE_CONTROL]。保存旧指针以便卸载时恢复;用InterlockedExchangePointer 而不是直接赋值,说明作者考虑过「可能有其他 hook 也在改这个槽位」。

image-20260922163950340

之后注入完成例程,完成例程部分关键代码如下:

image-20260922164806791

之后进行表压缩,TCP 表、状态表、PID 表是三个平行数组,删除一行必须三张表同时压缩,否则 PID 会错位到别的连接上。NhRemoveRow 用 RtlMoveMemory 把后续行整体前移。pidValid 的设计也很谨慎:PID 表缺失时 ByPid 规则一律不匹配,否则一张不存在的表会退化成人人命中,把整张连接表清空。

文件/目录隐藏

没什么好说的,就是通过Minifilter进行过滤

服务/注册表隐藏

通过注册注册表回调来实现注册表的隐藏,由于系统服务也存在于注册表中,所以同时可以实现对服务的隐藏。

配置里允许写人类习惯的 HKLM\\...,回调里看到的却是 \\Registry\\Machine\\...。把映射关系做成一张表(而不是 if/else 链)使扩展成本很低。转换函数还处理了两个边界。

image-20260922170218074

因为注册表回调 API 没有提供「跳过这一项」的便利返回,跳过隐藏子键只能重写枚举结果。做法是:拿到当前项的索引,从 Index + 1 开始自己调 ZwEnumerateKey(用重入保护避免递归),找到第一个不隐藏的项,把它拷进调用者的缓冲并修正 ResultLength。

image-20260922170443125

关机回写

关机回写的前提是,需要先将驱动文件本身复制一份到内核内存,文件路径从 DriverObject->DriverSection 指向的 LDR 节点里取。深拷贝成 NUL 结尾的独立缓冲是必要的,毕竟UNICODE_STRING 本身不保证NUL 结尾,而后面 ZwCreateFile 要用它。

image-20260922170931036

写入过程中,用 InterlockedCompareExchange 确保同步——关机路径和电源回调可能同时触发,必须防止两个线程同时 FILE_OVERWRITE_IF 打开同一个文件。

image-20260922171201998

至此,源码的原理分析基本结束,虽然分析看着简单,但实际上代码量达到了接近5000行,从个人项目来讲,已经算是个不小的项目了。就整个项目而言,采用的技术中规中矩,基本都是公开技术,但综合在一起,形成了一个全方位隐匿的高对抗性样本。

如何检测

我在测试机中做了实验,尝试了国内3款杀毒软件,都没啥反应,于是尝试手工检测。

通过Gmer进行Rootkit检测(检测的默认行为),完全没有发现

image-20260922173203717

但是比较明显的是,该样本会将目标进程伪装为系统进程(PID=4),所以通过ProcessHacker可以看到异常,系统中出现两个System进程

image-20260922173304604

但从属性上无法区分真假

image-20260922173330048

但通过XueTr(也就是PCHunter)可以看到恶意进程

image-20260922173423432

对于内核的检测,由于其会固定将自身伪装为系统的NULL.sys,所以是可以通过PCHunter等ARK工具检测到异常的,很明显,伪装终究是伪装,不可能面面俱到,驱动对象和服务名是空的,对于系统服务来说,这不正常。

image-20260922173528548

也可以给通过文件名排序,发现异常的内核驱动

image-20260922173657542

提示词中的坑

其实挺多的,可以自行测试。我这边蓝屏是因为文档中LDR 节点伪装(驱动伪装)与 PatchGuard 直接冲突导致,所以不要指望该提示词可以一键完成你要的东西。


对一款Windows木马开源提示词的测评" 网络安全文章

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

本文测评了一款通过AI提示词生成的Windows内核级Rootkit,详细分析了其进程伪装、网络隐藏、文件隐藏、注册表隐藏及驱动伪装等核心功能模块的实现原理。测试发现该样本功能齐全但存在蓝屏风险,常规杀软难以检测,但可通过PCHunter等ARK工具发现异常。文章提供了检测思路并指出提示词中的坑点,对安全研究人员具有参考价值。
国家网络安全宣传周系列活动丨我院组织开展“网络安全筑童心,数字护航伴成长”网络安全宣传进校园活动" 网络安全文章

国家网络安全宣传周系列活动丨我院组织开展“网络安全筑童心,数字护航伴成长”网络安全宣传进校园活动"

成都信息工程大学网络空间安全学院志愿者走进双流区实验小学开展网络安全宣传进校园活动,通过摆点宣传、有奖问答和主题讲座等形式,向小学生普及网络谣言辨识、电信诈骗防范、账号隐私保护等知识,推动网络安全理念进校园进课堂进童心,实现高校学科优势与基础教育场景有效对接。
内核的退与守:微软WESP如何重划终端安全边界" 网络安全文章

内核的退与守:微软WESP如何重划终端安全边界"

微软在Windows11预览版中发布wesp终端安全平台,将内核采集与执行能力收归操作系统,安全厂商检测逻辑留在用户态。wesp.sys提供46类事件采集、规则匹配及响应处置能力,通过espclient.dll供厂商下发规则。该架构降低内核稳定性风险,但存在扩展受限、复杂阻断能力不足、缺乏事后处置等问题,安全厂商需规划能力迁移。
评论:0   参与:  0