WMI系列--关于WMI

本系列预计有三节,分别记录关于WMI的一些基础知识,WMI的永久订阅事件,WMI常见的攻防对抗手段

WMI简介

WMI 的全称是 Windows Management Instrumentation,即 Windows 管理规范,在 Windows 操作系统中,随着 WMI 技术的引入并在之后随着时间的推移而过时,它作为一项功能强大的技术,从 Windows NT 4.0Windows 95 开始,始终保持其一致性。它出现在所有的 Windows 操作系统中,并由一组强大的工具集合组成,用于管理本地或远程的 Windows 系统。虽然WMI已经被大众熟知,并且从其创始以来,已经被系统管理员大量使用,但随着WMI技术的不断演变以及在恶意攻击中的使用,它逐渐成为恶意攻击者的利器.在攻击活动中的作用一般有系统侦察获取系统信息,反病毒和虚拟机的检测,横向移动,权限持久化以及数据窃取等作用.
随着越来越多的攻击者利用WMI进行攻击,他将会是安全维护人员,事件响应人员,取证分析师必须掌握的一项重要技能,并且要明白如何发挥它的优势。
WMI ( Windows Management Instrumentation ) 管理规范是微软实现的由分布式管理任务组(DMTF)发布的基于Web的企业管理(WBEM)和公共信息模型(CIM)标准,是内置在 Windows 2000、Windows XPWindows Server 2003 系列操作系统中核心的管理支持技术,是一种规范和基础结构,通过它可以访问、配置、管理和监视所有的几乎所有的 Windows 资源。在 WMI 之前,能够以编程方式访问 Windows 资源的惟一方法就是通过 Win32 API。这种情况使 Windows 系统管理员无法通过一种简便的方法利用常见的脚本语言来自动化常用的系统管理任务,因为大多数脚本语言都不能直接调用 Win32 APIWMI是架构在组件对象模型COM(Component Object Model COM)技术之上的,是微软的一套软件组件的二进制接口标准。这使得跨编程语言的进程间通信、动态对象创建成为可能。

WMI体系结构

上边已经提到过,WMI是微软实现的由分布式管理任务组(DMTF)发布的基于 Web 的企业管理(WBEM)和公共信息模型(CIM)标准。
WMI的基础结构,引用微软提供的结构图如下:
WMI系列--关于WMI_第1张图片
Fireeye公布白皮书中关于WMI的架构如下:
WMI系列--关于WMI_第2张图片

WMI providers and Managed object-托管对象和WMI提供程序

WMI 提供程序是一个COM对象,用于监视WMI的一个或多个托管对象.托管对象是逻辑或物理企业组件,例如硬盘驱动器、网络适配器、数据库系统、操作系统、进程或服务。
与驱动程序类似,提供程序为WMI提供托管对象中的数据,并将来自WMI的消息处理到托管对象。WMI 提供程序由DLL文件和 托管对象格式 (MOF) 文件组成,该文件定义提供程序返回数据的类并执行操作。 提供程序(如 WMI C++应用程序)使用 适用于WMICOM API.
WMI MOFDLL文件位于%WINDIR%\System32\Wbem中,包括WMI Command-Line工具,例如Winmgmt.exeMofcomp.exe。 提供程序类(如 Win32_LogicalDisk)在MOF文件中定义,然后在系统启动时编译到 WMI 存储库中。
总结来讲:WMI Providers是整个WMI体系的最底层,它对所有的”提供者(Provider)”提供了封装和抽象。从文件的角度来说,WMI提供者是由一个实现逻辑的DLL和承载着描述数据和操作的类的托管对象格式MOF(Managed Object Format)文件组成。这个两个文件连同WMI命令行工具都保存在%Windir%\System32\Wbem目录下。

WMI Infrastructure - WMI基础结构

WMI基础结构是Windows操作系统组件,称为WMI服务 (winmgmt)WMI基础结构有两个组件:WMI核心和 WMI 存储库。(关于这块有个小疑问,微软的资料里边没有明说WMI服务和WMI Core的关系是什么,但是其它资料里边直接将二者等价了,看到有这样的描述方式:

WMI基础结构是Windows系统的系统组件。它包含两个模块:WMI Core的WMI Service(WMI服务)(Winmgmt) -
CIM Object Manager;WMI Repository(WMI存储库) - WMI namespaces(WMI命名空间)
组成)

WMI存储库由WMI命名空间组织。 WMI服务在系统启动时创建一些命名空间,例如root\default、root\cimv2root\subscription,并预安装一组默认类定义,包括Win32类、WMI系统类等。 系统上找到的其余命名空间由操作系统或产品的其他部分的提供程序创建。
WMI服务充当提供程序、管理应用程序和WMI存储库之间的中介。只有有关对象的静态数据存储在存储库中,例如提供程序定义的类。当客户端请求数据时,WMI会从提供程序动态获取大部分数据。

WMI consumers - WMI使用者

WMI使用者是与WMI基础结构交互的管理应用程序或脚本。 管理应用程序可以通过调用适用于WMICOM APIWMI脚本API来查询、枚举数据、运行提供程序方法或订阅事件。 唯一可用于托管对象(例如磁盘驱动器或服务)的数据或操作是提供程序提供的数据或操作。

Winmgmt - WMI服务

WMI服务是操作系统组件,充当管理应用程序(management applications 或脚本)WMI数据提供程序(WMI data providers)之间的中介。 WMI存储库是WMI相关静态数据的存储区域。它是通过一个共享的服务进程SVCHOST来实施工作的。当第一个管理应用向WMI命名空间发起连接时,WMI服务将会启动。当管理应用不再调用WMI时,WMI服务将会关闭或者进入低内存状态。WMI服务和上层应用之间是通过COM接口来实现的。

MOF - 托管对象格式 Managed Object Format

托管对象格式Managed Object Format (MOF)WMI数据库中类和类实例的原始保存形式,是用于描述通用信息模型(CIM)类的语言(CIM 用于描述如何表示真实托管对象的模型)。MOF文件是一个文本文件,包含了指定的可被查询的事物的语句,如该事物的名称,复杂类的字段类型,对象组相关的权限。语言的结构类似于Java,相当于受限的Java 接口声明。WMI提供程序(Provider)实现新WMI类的推荐方法是在MOF文件中,该文件使用Mofcomp.exe编译到WMI存储库(WMI Repository)中。也可以使用WMICOM API创建和操作CIM类和实例。
WMI 提供程序(Provider)通常是由提供的MOF文件定义的,它定义了数据和事件类和提供数据的COM DLL文件。
WMI提供程序通常包括一个MOF文件和一个DLL文件,该文件定义了提供程序为其返回数据的数据和事件类,而DLL文件则包含提供数据的代码。WMI客户端脚本和应用程序(scripts and applications)可以查询提供程序MOF类(provider MOF classes)的实例或订阅以接收事件通知。Windows 管理规范 (WMI) 提供了以下三种方法编译到WMI存储库的托管对象格式(MOF)文件:

使用Mofcomp.exe
使用 IMofCompiler 接口和$CompileFile方法
拖放到%SystemRoot%\System32\Wbem\MOF文件夹的 MOF 文件

MOF 是一种面向对象的语言,它由以下部分组成:

命名空间
类
属性
方法
限定符
实例
引用
注释

MOF中的命名空间

要在MOF中声明一个CIM命名空间,可以使用 #pragma namespace (\\computername\path) 指令。这个指令通常处于文件最开始的位置,同时这个声明语句的作用域包含整个文件.MOF语言允许通过声明父命名空间并定义一个 __namespaceclass的新实例来创建新的命名空间。示例代码如下:

#pragma namespace('\\\\.\\ROOT\\default')
instance of _namespace
{	
	Name=NewNS
}

MOF 自动恢复

WMICIM储存库实现了MOF文件的事务缓存式的插入,以确保数据库不会被破坏。如果在插入的时候系统发生崩溃或停止,MOF文件可以被注册为后续自动恢复。若要启用此功能,可以在MOF文件顶部使用 #pragma autorecover语句。这时,WMI服务将会把MOF文件的完整路径添加到MOF文件自动恢复列表中,此列表存储在以下注册表项中:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\CIMOM\Autorecover MOFs

从另一个角度讲,一个WMI的管理组件可以是一个进程,一个注册表的键,一个安装的服务或一个文件信息,等等。WBEMCID标准用来沟通确定实现者应该使用什么方法来query(查询),populate(填充),structure(构造),transmit(传输),perform actions on(执行操作)和consume data(处理数据)。(下边这一段转自利用WMI构建一个持久化的异步的无文件后门)

Managed Components(管理组件)

管理组件即WMI的对象,是代表着高度结构化的操作系统数据的Class Instances(类实例)。Microsoft提供了非常多的WMI对象来提供有关系统的信息,比如Win32_Process,Win32_Service,AntiVirusProductWin32_StartupCommand等。

Consuming Data(数据处理)

Microsoft提供了一些用来处理WMI数据和执行WMI命令的方法。例如,PowerShell提供给了我们一个非常简单的与PowerShell交互的方式。

Querying Data(数据查询)

所有的WMI对象可以通过一个叫WQL的查询语言来查询,这种语言与SQL相似,能够让我们精细地控制返回给用户的WMI对象。

Populating Data(数据填充)

当用户请求一个WMI对象时,WMI服务(Winmgmt)需要知道请求对象的数据填充方式。这个功能是通过WMI Providers(WMI提供者)来完成的。一个WMI提供者就是一个在注册表中拥有相关GUID的注册表键。WMI提供者在数据填充时,做了大量的动作,比如查询所有进程,枚举注册表键等。
WMI服务填充一个WMI对象时,会有两种类实例:Dynamic Object(动态对象)和Persistent Object(永久化对象)。
动态对象是在进行查询时生成的,例如,Win32_Process就是一个动态对象。永久化对象是存储在CIM Repository(CIM库)中的,默认放在%SystemRoot%\System32\wbem\Repository\OBJECTS.DATA中。

Structuring Data(构造数据)

WMI对象大部分的结构是通过Managed Object Format (MOF)(管理对象格式)文件中描述的。MOF文件使用类似C++的语法来描述WMI对象。
WMI提供者生成原始数据时,MOF文件对提供了这些数据的构造结构。从防御者的角度看,值得注意的是,WMI对象的定义可以不通过MOF文件,攻击者可以通过在CIM库中插入.Net代码来定义。

Transmitting Data(数据传输)

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

Performing Actions(执行操作)

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

WMI namespaces 命名空间

WMI的命名空间创建了一个层次结构,有点类似于我们的目录文件结构。

  1. root-作为所有其他名字的占位符;
  2. root\default-与注册表操作有关的类;
  3. root\security-与系统安全有关的类;
  4. root\cimv2-从CIM派生的类,代表我们最常用的工作环境。
    微软使用ROOT\CIMV2作为默认的命名空间。在下面的注册表项中包含所有WMI设置,也包括已定义的默认命名空间:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM

WMI 查询

WMI提供了一种非常直观的语法用来查询WMI对象的实例,类和命名空间,即WQLWQL查询通常可以分为以下几类:
1.实例查询(Instance Queries) - 用于查询 WMI 类的实例
2.事件查询(Event Queries) - 用于一个 WMI 事件注册机制(event registration mechanism),例如 WMI 对象的创建、 删除或修改
3.元查询(Meta Queries) - 用于查询 WMI 类架构(WMI class schemas)
WQL就是WMI中的查询语言。有如下特点:

每个WQL语句必须以 SELECT 开始;
SELECT 后添加需要查询的属性名;
FROM关键字;
要查询的类的名字;
另外,如果你想精确查询结果还可以加上WHERE条件从句。比如某个类有Enable属性,你可以在查询的时候加上WHERE ENABLE=true。

语法

SELECT properties[,properties] FROM class [where clause]
    SELECT      必选项。代表WQL语句的开始,
    properties  必选项。代表想查询的属性名字。可以是多个属性名,也可查询所有属性值,用*代替。
    FROM        必选项。跟在properties的后面。
    Class       必选项。代表想要查询的类的名称。
    where clause 可选项。where 从句和相关条件语句,用来缩小查询范围。

Win + R -> wbemtest ( 系统自带的测试WMI语句的工具 )
root\cimv2 or ROOT\SecurityCenter 

    SELECT * FROM Win32_Product;
    SELECT * FROM Win32_Process;

Instance Queries-实例查询

以下查询语句将返回Win32_Process类的每个实例的所有属性的名称字段中包含字符串”Chrome”的结果

SELECT [Class property name|*] FROM [CLASS NAME] <WHERE [CONSTRAINT]>
SELECT * FROM Win32_Process WHERE Name LIKE "%chrome%"
    Win32_Process.Handle="5292"
    Win32_Process.Handle="5364"

Event Queries-事件查询

事件查询被用作一种消息机制来监听事件类的触发。通常用来在一个WMI对象实例创建/修改/删除的时候给用户发送一个消息。根据消息类型是intrinsic(系统自带的)还是extrinsic(第三方的),查询语句格式不同:

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

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

以下的查询语句将在用户登录的时候被执行:根据微软文档可知,交互式登录的LogonType值为 2。

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

元查询

元查询用来查询WMI命名空间和类结构的信息。最常见的用法是用来列举WMI命名空间的类结构。元查询是实例查询的一个子集,但是与对象查询不同的是,我们查询的是类的实例的定义。格式如下:

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

下面这个语句会查询所有以WIN32开头的WMI的类:

SELECT * FROM Meta_Class WHERE __CLASS LIKE "Win32%"

下面这个语句会查询某个命名空间下的所有命名空间:

SELECT Name FROM __NAMESPACE

注意,当不显示的指定命名空间时,默认的命名空间为ROOT\CIMV2

WMI的交互

微软和一些第三方软件开发者提供了许多能够与WMI交互的工具。下面是部分工具的一个不完全的列表:

powershell    PowerShell是一个非常强大的脚本语言,其中包含很多能够与WMI进行交互的功能
wmic.exe      wmic.exe是一款强大的可以与WMI交互的命令行工具.有很多且方便的WMI对象别名可使用,可以用来进行更			     加复杂的查询。wmic.exe还能够执行WMI方法
wbemtest.exe  wbemtest.ext是一款强大的图形化工具,是出于诊断工具来设计的。可以用来枚举对象实例,执行查询,注册事件,修改WMI对象和类,本地或远程执行
WMI Explorer  WMI Explorer是Sapien公司开发的一款商业工具,用来查找WMI类,并且可以分层浏览WMI库。它不可以连接远程WMI库并执行查询。
CIM Studio    CIM Studio微软提供的免费WMI交互工具,可以用它方便的浏览WMI库,查找WMI类
VBScript      微软提供的脚本语言,功能强大
JScript       微软提供的脚本语言,功能强大
.Net System.Management 类  System.Management 命名空间是 .NET 框架中的 WMI 命名空间
winrm.exe     winrm.exe可以在本地或远程开启WinRM服务的机器上枚举WMI对象实例,调用方法,创建和删除对象实例

远程WMI

WMI的强大体现在通过远程操作的时候。目前,WMI支持两种协议:DCOMWinRM,使用这两种协议可以做任何事情,包括查询对象,注册事件和执行WMI类的方法,等等。两种协议都对攻击者有利,因为防御者通常不会检查这两种协议的恶意流量。利用WMI所需的东西就是可用的有权限的用户凭证。在Linux平台上的wmis-pth工具中,只需要提供被攻击者的用户哈希即可。(之后可以看下这个工具)

DCOM (Distributed Component Object Model)

DCOM在引入WMI时,就被当做是默认处理协议。DCOM通过135端口建立TCP连接,后续的数据交换则通过随机选择的TCP端口传输。这个端口可以通过dcomcnfg.exe进行配置和修改,其最终是改动如下注册表项:

HKEY_LOCAL_MACHINE\Software\Microsoft\Rpc\Internet - Ports (REG_MULTI_SZ)

所有的PowerShell中内置的WMI命令都使用DCOM协议。

WinRM (Windows Remote Management)

WinRM目前已经被Windows当作建议使用的协议。WinRM基于Web Services-Management (WSMan)规范,是一个SOAP-based设备管理协议。另外,PowerShell Remoting也是基于WinRM规范的,这使得我们能够通过PowerShell在大规模Windows企业环境中实现强大的远程管理功能。WinRM同样支持WMI,或者说CIM的网络操作。
默认情况下,WinRM服务开启并监听5985/tcp端口,而且默认是加密的。还可以通过配置证书的方式在5986/tcp端口实现HTTPS支持。

参考链接

https://learn.microsoft.com/zh-cn/windows/win32/wmisdk/wmi-architecture
https://learn.microsoft.com/zh-cn/windows/win32/wmisdk/managed-object-format–mof-
https://m0nst3r.me/pentest/
http://1sparrow.com/2019/12/10/Windows%20WMI%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/

你可能感兴趣的:(windows,WMI)