WMI粗略学习
目录
WMI,Windows Management Instrumentation,Windows管理工具。如今所有得windows都预装了这个强大的命令行管理工具,同时它强大的功能也为黑客提供了一个绝佳的攻击面。
WMI 架构
WMI的架构如下图所示
可以总结为以下部分
Managed Components(管理组件)
就是WMI对象,是结构化 的 操作系统数据 的 类实例。
微软提供了许多的WMI对象来提供系统相关信息,如Win32_Process
,Win32_Service
,AntiVirusProduct
,Win32_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数据的方法:DCOM
和Windows 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事件订阅,需满足以下条件。
- 一个事件过滤器
- 一个事件处理:代表一个事件触发时启动的动作
- 一个处理绑定的过滤器:代表将一个过滤器绑定到一个事件处理的注册机制
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:执行一条命令