WMI粗略学习

目录

WMI,Windows Management Instrumentation,Windows管理工具。如今所有得windows都预装了这个强大的命令行管理工具,同时它强大的功能也为黑客提供了一个绝佳的攻击面。

WMI 架构

WMI的架构如下图所示

image-20210801130642908

可以总结为以下部分

Managed Components(管理组件)

就是WMI对象,是结构化 的 操作系统数据 的 类实例。 微软提供了许多的WMI对象来提供系统相关信息,如Win32_ProcessWin32_ServiceAntiVirusProductWin32_StartupCommand等。

Consuming Data(数据处理)

用于处理WMI数据和执行WMI命令。如powershell下的WMI的交互模式。

Querying Data(数据查询)

通过一个叫做WQL的语言进行查询,它和SQL的语法十分相似。

Populating Data(数据填充)

当我们请求一个WMI对象时,WMI在背后会通过各种手段(比如查询所有进程,枚举注册表键)去填充这个WMI对象以使其能够呈现在我们面前。

WMI在填充一个WMI对象时,会有两种类实例。Dynamic Object动态对象和Persistent Object 永久化对象。 动态对象是进行查询的时候生成的,例如Win32_Process就是一个动态对象。 永久化对象是存储在CIM库中的,默认存放在%SystemRoot%\System32\wbem\Repository\OBJECTS.DATA

Structuring Data(构造数据)

WMI对象大部分结构是通过MOF文件描述的,MOF文件使用类似C++的语法来描述WMI对象。 同时WMI也可以通过在CIM库中插入.net代码定义。

Transmitting Data(数据传输)

Microsoft提供了两种用于远程传输WMI数据的方法:DCOMWindows Remote Management (WinRM)

Performing Actions(执行操作)

一些WMI对象包含一些可执行的方法/函数。例如,Win32_Process类的静态函数Create就经常被黑客用来做内网中的横向移动。 WMI还提供了一个Eventing System(事件系统),用户可以注册在WMI对象生成,修改或删除时执行的事件处理程序。

WMI类和命名空间

一个WMI对象就是一个WMI类的实现。 WMI类被分类分层放在命名空间中,所有命名空间都放在ROOT命令空间下,当不指定命名空间进行查询时,会默认使用root\cimv2作为命名空间。

所有的WMI设置,包括默认命名空间在下面的注册表键中:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM

WQL

wmi提供了一种非常直观的语法来查询WMI对象实例,类和命名空间,即WQL。它很像SQL,但它只能用于查询。

WQL查询大致分为如下类:

Instance Queries(实例查询)

查询WMI对象实例。

SELECT [Class property name | *] FROM [CLASS NAME] <WHERE [CONSTRAINT]>

Event Queries(事件查询)

等同于在WMI对象创建/修改/删除的时候注册一个消息。常用于监听某事件触发,根据监听的消息类型是intrinsic(系统自带的)还是extrinsic(第三方的),查询语句格式也不同。WITHIN的意思是查询间隔,它会根据设定的时间间隔去查看事件是否处于被触发状态。

SELECT [Class property name | *] FROM [INTRINSIC CLASS NAME] WITHIN [POLLING INTERVAL] <WHERE [CONSTRAINT]>

SELECT [Class property name | *] FROM [EXTRINSIC CLASS NAME] <WHERE [CONSTRAINT]>

下面的查询将在用户登录的时候被执行:
SELECT * FROM __InstanceCreationEvent WITHIN 15 WHERE TargetInstanceISA 'Win32_LogonSession' AND TargetInstance.LogonType=2

下面的查询将在用户插入可移除设备时被执行:
SELECT * FROM Win32_VolumeChangeEvent Where EventType=2

Meta Queries(元查询)

元查询用来获取WMI命名空间和类结构的元信息。最常见的用法是用来列举WMI命名空间的类结构,元查询是实例查询的一个子集

SELECT [Class property name | *] FROM [Meta_Class | SYSTEM CLASS NAME] <WHERE [CONSTRAINT]>

查询某默认命名空间root\cimv2下的所有命名空间
SELECT Name FROM __NAMESPACE

远程WMI

WMI还有一个十分强大的体现,远程操作。 WMI远程操作时支持两种协议DCOM和WINRM。

DCOM

DCOM是WMI的默认协议,通过135端口建立TCP链接,随后数据交换则是随机选择TCP端口传输。 所有powershell中内置的WMI命令都是用的DCOM协议

WINRM

WINRM在功能性上已经超过了DCOM,被微软作为建议使用的协议。

默认情况下,WinRM服务开启并监听5985/tcp端口,而且默认是加密的。还可以通过配置证书的方式在5986/tcp端口实现HTTPS支持。

WMI事件

WMI事件可以用来响应基本所有的操作系统事件。 WMI事件分为两类,本地单个进程事件和永久性WMI事件订阅。 本地事件的生命周期为宿主进程的周期,永久性WMI事件存储在WMI库中以SYSTEM权限运行,并且重启后依旧存在。

如果要安装一个永久性WMI事件订阅,需满足以下条件。

  1. 一个事件过滤器
  2. 一个事件处理:代表一个事件触发时启动的动作
  3. 一个处理绑定的过滤器:代表将一个过滤器绑定到一个事件处理的注册机制

Event FIlters 事件过滤器

一个事件过滤器接收一个WMI事件查询参数,并保存到ROOT\subscription:__EventFilter对象的一个实例中。

事件过滤器一般有两类:Intrinsic Events和Extrinsic Events

Intrinsic Events

__NamespaceOperationEvent
__NamespaceModificationEvent
__NamespaceDeletionEvent
__NamespaceCreationEvent
__ClassOperationEvent
__ClassDeletionEvent
__ClassModificationEvent
__ClassCreationEvent
__InstanceOperationEvent
__InstanceCreationEvent
__MethodIvocationEvent
__InstanceModificationEvent
__InstanceDeletionEvent
__TimerEvent

大概有如上事件,很全面。

SELECT * FROM __InstanceCreationEvent WITHIN 15 WHERE TargetInstance ISA 'Win32_LogonSession' AND TargetInstance.LogonType=2

上面的查询的意思是,在一个登陆类型为2(交互式登陆)的Win32_LogonSession类的实例创建时,触发一个事件。

它有一个时间间隔,用WITHIN设定,他会根据设定的时间,每隔一段这个时间去检查一下事件的触发情况。 所以Intrinsic events有时候并不能捕捉到事件:当事件在设定的时间间隔里发生又消失。

Extrinsic Events

Extrinsic Events 解决了时间响应问题,当事件发生时便会立刻触发。 但它的事件类不多

ROOT\CIMV2:Win32_ComputerShutdownEvent
ROOT\CIMV2:Win32_ProcessStartTrace
ROOT\CIMV2:Win32_ModuleLoadTrace
ROOT\CIMV2:Win32_ThreadStartTrace
ROOT\CIMV2:Win32_VolumnChangeEvent
ROOT\DEFAULT:Msft_WmiProvider*
ROOT\DEFAULT:RegistryKeyChangeEvent
ROOT\DEFAULT:RegistryValueChangeEvent

Event Consumer 事件处理

一个Event Consumer代表当一个事件触发时进行的操作。

有如下标准类,所有的事件处理类都在从__EventConsumer类继承而来的

LogFileEventConsumer: 将事件数据写入到指定的日志文件
ActiveScriptEventConsumer: 用来执行VBScript/JScript程序
NTEventLogEventConsumer:创建一个包含事件数据的日志入口点
SMTPEventConsumer:将事件数据用邮件发送
CommandLineEventConsumer:执行一条命令

reference:https://m0nst3r.me/pentest/%E5%88%A9%E7%94%A8WMI%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%8C%81%E4%B9%85%E5%8C%96%E7%9A%84%E5%BC%82%E6%AD%A5%E7%9A%84%E6%97%A0%E6%96%87%E4%BB%B6%E5%90%8E%E9%97%A8.html