
做内网渗透的朋友应该都有体会拿下一台主机权限只是开始难的是怎么让它一直稳住。计划任务和注册表Run键当然能用但在现在的EDR和杀软眼里这些已经是高危行为落盘痕迹太明显。今天聊的WMI权限维持属于那种用了很久但讨论得不多的一类手法——它不落盘文件、不开新端口、不引入第三方服务靠Windows系统自己的WMI事件订阅机制就能把命令挂到系统运行周期里。这篇内容适合刚接触内网攻防的人理解原理也适合蓝队的朋友拿来搭检测规则。提前说清楚所有涉及攻击视角的还原都只适合在你自己有授权的靶机环境里做别拿去碰真实生产系统。1. 先弄清WMI权限维持的基本运行机制WMI全称Windows Management Instrumentation微软自己的一套管理框架。平时大家用得比较多的可能是winmgmt服务、wmic命令行或者通过CIM/WMI查询硬件信息。它本质上是一个系统对象数据库里面装的不只是硬件数据还包括很多可操作的事件、方法、属性。权限维持用的核心是WMI的事件订阅功能。你可以把它理解成一个系统内置的触发-执行管道先定义一个触发条件叫EventFilter再定义一个满足条件时要执行的动作叫EventConsumer最后用一条绑定FilterToConsumerBinding把两者连起来。整个过程通过WMI对象存储在系统里路径在root\subscription命名空间下。攻击者要做的事很简单就是把这三类对象写进去。Windows自身的大量服务也依赖这套机制所以它不是后门专用的API反而因为行业通用躲过了不少严格的白名单检测。在定位上root\subscription默认只允许管理员权限写入所以攻击者通常已经在失陷主机上拿到了SYSTEM或管理员权限才会去创建订阅。这个前提决定了它更适合做权限维持而不是初始入侵。常见的事件消费者类型包括CommandLineEventConsumer、ActiveScriptEventConsumer、LogFileEventConsumer等。其中CommandLineEventConsumer是最常用的因为它可以直接执行命令行程序攻击者只要把自己的payload地址填进去就行不需要额外释放脚本文件到磁盘。ActiveScriptEventConsumer则允许执行VBScript/JScript脚本隐蔽性更强但相对容易把杀软惹毛。这里补充一点基础认知WMI事件订阅在注册表里的体现主要是HKLM\SOFTWARE\Microsoft\WBEM\CIMOM路径但具体订阅内容并不是简单存放在注册表字符串里而是以托管对象的方式存在WMI仓库普通查启动项的姿势根本看不到它。这也是它常被忽略的核心原因之一。2. 攻击者视角事件订阅是怎么被利用的到了实际操作层攻击者还原起来其实就三步写过滤器、写消费者、建立绑定。这跟写代码一样得有顺序因为绑定必须引用到已经存在的消费者和过滤器。EventFilter是触发器最常见的触发方式有几种。一种是系统启动相关比如利用Win32_PerfFormattedData_PerfOS_System这类性能计数器对象的变化来判断系统是否已完成启动。因为这类对象几乎每秒都会刷新攻击者可以用WITHIN 60这样的轮询间隔配合逻辑判断实现定时执行。另一种更直接的是用__IntervalTimerInstruction设置一个定时器然后让__TimerEvent作为触发源。还有一种是观测进程创建事件比如检测winlogon.exe启动攻击者可以在用户登录的瞬间触发payload。Consumer是执行体。攻击者构造CommandLineEventConsumer时不一定要写一个完整的命令行进去常见的做法是把真正的payload做成一个PowerShell命令或者写一段加密后的命令行。这里有个容易被忽视的点Consumer里的命令不是拿到SYSTEM权限执行的而是以WMI宿主进程wmiprvse.exe的身份启动的子进程权限取决于WMI服务的运行身份通常是SYSTEM所以它天然具有高权限。绑定就是把过滤器和消费者关联起来。写完这三个对象后即使杀掉当前会话退出只要系统不重装、不清理WMI仓库这个事件订阅就会一直存在重启后照样触发。我见过不少攻击者把订阅触发时间设在系统运行120秒之后再用一个无限轮询或周期触发这样每次开机后稍等一两分钟就会“复活”。需要特别指出的是攻击者在实战中经常把消费者命令写成PowerShell的-enc参数。原因很简单-enc接受Base64字符串命令行里没有明文的payload内容蓝队如果只看进程命令行而不做解码很容易忽略。这类行为在红队演练中非常常见所以蓝队需要重点盯着wmiprvse.exe的异常子进程启动。再提一个攻击者偏好他们一般不会只挂一个订阅而是会做冗余比如同一台机器上同时挂定时触发和启动触发这样即使其中一个被清除另一个还能把权限捞回来。清除的时候如果只删了绑定而没删过滤器和消费者或只删了其中一个系统会自动把其余对象保留这样攻击者理论上一旦还有写权限就能重新绑定恢复。3. 实战排查在主机上找出可疑的WMI订阅蓝队和应急响应的人更关心的是怎么发现。先说结论root\subscription里干干净净的机器正常是没有任何对象的那才是常态。如果你在一台非域控、非SCCM客户端的机器上看到CommandLineEventConsumer就要高度警惕了。排查第一步枚举订阅。推荐用PowerShell别再用wmic了新系统里wmic已经被官方弃用。三条命令分别看三类对象# 查看过滤器 Get-CimInstance -Namespace root/subscription -ClassName __EventFilter # 查看消费者 Get-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer # 查看绑定关系 Get-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding如果类名拿不准也可以直接列出整个命名空间下的对象Get-CimInstance -Namespace root/subscription -ClassName __Namespace这条命令的意义在于让你看清这个命名空间里到底有哪些类被实例化过。正常情况下没有额外的CommandLineEventConsumer实例也没有可疑的ActiveScriptEventConsumer实例。第二步分析触发器和消费者的内容。__EventFilter里最关键的是Query字段这是一个WQL查询语句。攻击者会让它匹配某种事件变化比如系统启动后过60秒、某进程启动时等。看到Query里有__InstanceModificationEvent、__TimerEvent、Win32_PerfFormattedData这些类的时候就要去判断是不是人为创建的。CommandLineEventConsumer里最致命的是CommandLine字段它直接写着系统要被执行的命令。注意即使这里显示的是短路径cmd.exe /c也可能因为原命令被脱敏了要跟进父进程wmiprvse.exe的子进程树看完整行为。第三步结合日志做时间线。Sysmon对WMI有专门的事件ID19号事件记录WMI事件过滤器被创建20号记录消费器被创建21号记录过滤器和消费器的绑定。只要Sysmon版本不低于12.1并且配置了WMI事件监控任何新增订阅都会留下记录。Windows安全审计日志对WMI这块相对薄弱但可以通过4688进程创建事件监控wmiprvse.exe启动子进程的行为再结合PowerShell 4104脚本块日志把whoami、net user、calc这类测试命令和真正的payload区分开。第四个排查点是注册表。虽然WMI订阅的对象主体在WMI仓库但相关效果会在注册表留下一些线索比如消费者命令写入后在HKLM\SOFTWARE\Microsoft\WBEM\CIMOM的Logging等键值可以看到异常。不过这个不总可靠我更推荐直接查WMI仓库和Sysmon日志注册表只能作为佐证。最后用一张表格整理一下排查时的重点位置检查项具体位置异常特征事件过滤器root/subscription/__EventFilterQuery含InstanceModificationEvent或TimerEvent事件消费者root/subscription/CommandLineEventConsumerCommandLine字段为PowerShell或cmd命令绑定关系root/subscription/__FilterToConsumerBinding指向可疑的消费者和过滤器进程链日志Sysmon 1/19/20/21wmiprvse.exe创建可疑子进程PowerShell日志4104脚本块含远程下载、加密执行等特征4. 清除与防御正确的应急响应动作发现恶意订阅之后清除的顺序不能乱。直接删消费者或过滤器都会导致绑定失效但残留对象还在攻击者只要能恢复写权限就能把关系重新绑回去。正确的顺序是先删绑定再删消费者最后删过滤器。删除绑定的命令可以这样写Get-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding | Where-Object { $_.Consumer -match CommandLineEventConsumer -and $_.Filter -match __EventFilter } | Remove-CimInstance删除消费者的命令Get-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer | Remove-CimInstance删除过滤器的命令Get-CimInstance -Namespace root/subscription -ClassName __EventFilter | Remove-CimInstance这三条命令放在应急脚本里通常不会出大问题但有个前提你必须先看清楚这台机器是不是域控或安装了System Center、SCCM Agent之类的管理组件。因为微软自家的管理工具也会创建WMI订阅直接盲删会把这些组件的功能搞坏。我踩过这个坑有次排查一台装过SCCM客户端的服务器跑完清除脚本后收件箱监控直接失效后来才发现那个订阅是管理代理自己建的。正确的做法是先备份这三类对象的完整输出到一个JSON或文本文件再逐项确认哪些是可疑的、哪些是系统创建的。加固层面第一条原则是限制WMI的远程调用通道。WMI默认允许管理员组通过135端口远程访问很多内网横向用的就是这条通道。如果你业务上没有远程WMI需求组策略里可以设置WinRM/WMI的访问控制或者在防火墙层面阻断135端口的风险来源IP。第二条是启用Sysmon的WMI事件监控并推送集中日志很多内网事件都是事后从日志里翻出来的没有集中日志就会变成瞎子。第三条是监控PowerShell日志特别是-enc参数的出现。即便攻击者换成普通字符串只要PowerShell执行策略和日志审计完整4104事件里总会留下原始命令关键是日志别被本地清理掉。对于已经确认被植入的WMI订阅还要检查是否存在其他持久化点。WMI订阅只是其中一种攻击者往往同时存在计划任务、服务、启动项、WMI订阅等冗余。清除WMI订阅只是“止血”真正要做的就是全盘排查把攻击者其他路径一起摘掉。如果有EDR最好不要只依赖EDR的自动隔离功能。EDR通常能发现root\subscription写入行为但遇到那些用可信进程替代写入手法的会有漏报。落地到应急流程上我的习惯是先隔离主机断网再备份WMI订阅对象接着清绑定、清消费者、清过滤器然后用Sysmon和PowerShell日志回溯时间线最后重扫一遍计划任务和自启动目录。5. 权限维持之外WMI相关的攻击面扩展很多人对WMI权限维持的印象还停留在“创建一个消费者执行命令”这个层面。但实际上WMI能做的事情远不止这些扩展了解对防守也有帮助。一是攻击者可以利用WMI的远程查询功能做内网侦察。比如通过Get-WmiObject -Class Win32_Process -ComputerName 10.0.0.8远程枚举目标主机进程、系统信息、网卡配置。这类行为如果不打算做权限维持通常不会被Sysmon的19/20/21号事件记录到只会出现在4688进程创建和网络连接日志里。所以防守方不能只盯WMI事件订阅也要盯wmiprvse.exe的远程连接行为。二是可以用WMI实现文件传输。部分攻击者会通过Win32_Process.Create方法在目标主机创建进程配合System.Net.WebClient在内存中下载payload整个过程不落盘。这里有个细节Win32_Process.Create返回的进程ID结构在远程调用和本地调用时有差异攻击者经常利用这个方法去启动一个隐藏进程但不接收输出从而规避命令行参数监控。三是WMI对象本身可以作为C2心跳的载体。有些比较细的攻击者会把C2地址或指令周期性地写到WMI类的属性里而防守方甚至不一定知道该查询哪个类。这类对抗已经超出权限维持范围而是把WMI当成隐蔽通信渠道。检测思路可以集中在类名和属性名的异常变化上比如说突然出现一个名字像随机字符串的类并且含有URL或IP字段就值得人工确认。四是WMI的命名空间不仅限于root/subscription。攻击者还可能使用root\cimv2下的Win32_Process方法做执行使用__Namespace创建自定义命名空间存放自己的对象这样常规检查脚本扫不到。排查的时候建议把整个root下的命名空间枚举一遍看看有没有奇怪的自定义命名空间。对常规读者而言这部分可能有点“偏门”。但我想说的是WMI这个内置框架太庞大了攻击者的利用思路往往是从官方文档里翻出来的功能点而不是什么0day。防守如果想要做扎实至少要把WMI相关的Sysmon事件、PowerShell日志和异常进程链这三样东西先接起来不然很容易出现“攻击者已经在你机器上安家了你还以为系统一切正常”的尴尬局面。6. 结合实战场景的一个排查示例拿一个我在授权演练中处理过的场景来讲靶机是一台Windows Server 2019已经拿到管理员权限攻击者的目标是让它每60秒尝试执行一次payload并且不落盘文件。排查时我先跑了Sysmon日志发现绑定创建事件发生在凌晨日志里能看到三个最关键的信息过滤器Query里写的是系统启动相关的事件消费者CommandLine字段是PowerShell的-enc参数绑定创建进程是System。这三个特征凑齐了基本可以判定是红队做的WMI订阅。接下来我用Get-CimInstance把三个对象的内容落盘备份然后逐项确认这台机器不是SCCM管理端、也没有其他管理代理在跑WMI订阅否则不敢轻易清除。确认后再按绑定、消费者、过滤器的顺序删除再用同一套命令重新枚举一次确定root/subscription下已经没有CommandLineEventConsumer实例。然后回到日志侧往前回溯一周看wmiprvse.exe的子进程执行了哪些命令、有没有内网横向的苗头。最终这台机器的结论是权限维持只用了WMI订阅这一个点没有叠加其他后门清理完成后即可恢复正常。整个过程大概用了四十分钟真正耗时间的反而是日志回溯而不是删除本身。这个场景给我的经验是WMI权限维持的清除不难难的是确认“是不是只有这一个点”。很多时候你清完WMI订阅顺手一拉计划任务又发现一个藏在注册表里的启动项。所以一旦确认攻击者落过地就按“持久化全链路排查”来做别只盯着眼前这一个手法定生死。7. 想对新手说的话如果你刚接触内网安全我建议你先把WMI事件订阅的这三个对象关系吃透然后在自己的虚拟机里反复练习查询和恢复。可以在实验环境里创建一个无害的订阅来观察变化比如让Consumer执行whoami并重定向到文件观察这个动作先后在Sysmon日志和PowerShell日志里如何呈现。注意我说的是实验环境而且命令本身是无害的千万别拿生产服务器试。练习的最终目标不只是“知道怎么清除”而是建立起对正常系统和异常系统的差别嗅觉。WMI权限维持在系统里不会留下常规启动项所以它的隐蔽性天然比计划任务强但只要蓝队知道该查root/subscription它其实并不难被识破。另一点是我个人体会比较深的权限维持类技术攻击者更喜欢用系统和业务本身就有的功能而不是往你机器里塞一个格格不入的工具。WMI就是典型。这提醒防守方把常规管理工具的功能吃透有时候比堆一堆检测脚本更管用。你不需要会写所有利用代码但至少要能在看见恶意WMI订阅时一眼认出它和系统正常行为的差别。以后再做内网排查不妨在常规检查清单里加一条枚举root/subscription。这个动作很便宜但可能救你一次大麻烦。