天天看点

wmi基础Windows管理规范基础

文章目录

  • Windows管理规范基础
    • wmi简介
    • wmi体系结构
    • 类与命名空间
    • WQL语句查询
      • 实例查询
      • 事件查询
      • 元查询
    • WMI交互
      • PowerShell
      • wmic.exe
      • wbemtest.exe
      • WMI Explorer
      • Windows脚本宿主(WSH)语言
      • C/C++调用IWbem* COM API
      • .NET System.Management类
      • winrm.exe
    • 远程使用
    • WMI事件
      • 事件筛选器
      • 事件消费者

Windows管理规范基础

wmi简介

  wmi就是Windows Managerment Instrumentation(Windows管理规范),是Windows中的一个核心管理技术。wmi为访问大量的Windows管理数据和方法提供了一个统一的机制。wmi通过脚本、C++程序接口、.Net类(系统管理)和命令行工具(WMIC)提供了对这个信息的访问。wmi的功能还包括事件、远程、查询、查看、计划和实施用户扩展及更多内容。可以理解为Windows提供了一个api来操作Windows系统。

  wmi的具体实现就是wmic.exe,位于windows目录下面(C:\Windows\System32\wbem),是一个命令行程序。

  对于wmi的使用者,比如一个脚本或者其他用到wmi接口的应用程序,由使用者访问CIM对象管理器WinMgmt(即wmi服务),再由后者访问CIM(公共信息模型Common Information Model)存储库,静态或动态的信息(对象属性)就保存在CIM库中,同时保存对象的方法。WMI能够响应用户的访问,就是因为这个服务的运行。一旦关闭WinMgmt,所有对wmi的操作都将失效。WMI是事件驱动的,无论是操作系统、服务、应用程序或者设备驱动程序都可以作为事件源,通过COM接口生成事件通知,这时候WinMgmt就会捕捉到事件、然后刷新CIM库中的动态信息。就像注册表有根键一样,CIM库也有分类,用面向对象的术语描述来说就是命名空间(NameSpace)。

  wmi常用两种模式,wmic执行和powershell执行。两种模式都可以达到一个效果:

//查询当前系统中的安全补丁

//wmic实现:
wmic qfe

//powershell实现:
Get-WmiObject Win32_QuickEngineering
           

  除此之外还有其他调用方法,下文会介绍。

  wmi可以执行一些攻击技术,其作用有执行系统侦察,反病毒和虚拟机检测,代码执行,横向运动,权限持久化以及数据窃取。

wmi体系结构

  • 托管组件:托管组件表示为WMI对象,即操作系统类实例。例如Win32_Process(表示操作系统上的一个进程)、Win32_Service(运行Windows的计算机系统上的服务)、AntiVirusProduct、Win32_StartupCommand(当用户登录到计算机系统时自动运行的命令)等等
  • WMI数据的使用:微软提供了几种方式使用WMI数据或执行WMI方法,下文会分别介绍
  • WMI数据查询:WMI查询语言WQL能够很好且细微的控制返回给用户的WMI对象
  • 填充WMI数据:用户请求特定的WMI对象的时候,WMI服务需要知道如何填充被请求的WMI对象。这个过程由WMI提供程序实现。WMI提供程序是一个基于COM的DLL文件,包含一个在注册表中已经注册的相关联的GUID。WMI提供程序能够提供诸如查询正在运行的进程、枚举注册表项等很多操作。当WMI服务填充WMI对象时,有两种类型的类实例:动态对象和持久性对象。动态对象是在特定查询时在运行过程中生成的,例如Win32_Process对象。而持久性对象存储在%SystemRoot%\System32\wbem\Repository\目录下的CIM存储库中,存储着WMI类的实例、类的定义和命名空间的定义。
  • 结构化WMI数据:绝大多数的 WMI 对象的架构是在托管对象格式 (MOF) 文件中描述的。MOF 文件使用类似于 C++ 的语法并为一个 WMI 对象提供架构。因此,尽管 WMI 提供程序产生了原始数据,但是 MOF 文件为其产生的数据提供了被格式化的模式。WMI对象定义可以在没有MOF文件的情况下被直接创建出来。
  • 远程传输WMI数据:两个协议,分布式组件对象模型(DCOM)和Windows远程管理(WinRM)
  • 执行WMI操作:部分WMI对象有可执行的方法,如Win32_Process类中的静态Create方法可以创建一个进程。此外WMI还有一个事件系统,用户可以使用注册事件处理函数进行创建、修改或删除任何WMI对象实例。

类与命名空间

  WMI 类的命名空间的层次结构非常类似于传统的,面向对象的编程语言的命名空间。所有的命名空间都派生自根命名空间ROOT, ROOT\CIMV2 为默认的命名空间。WMI所有的设置存储在如下注册表中:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM

WQL语句查询

  WQL是wmi中的查询语言,全称是wmi query language。WQL语法格式和sql一样,不过要注意这些语句并不能直接在命令行执行。

  当执行任何 WMI 查询时,除非显式提供命名空间,否则将隐式使用默认的命名空间 ROOT\CIMV2。

  一共有三种类别的查询:

实例查询

  实例查询是最常见的用于获取 WMI 对象实例的 WQL 查询。

//查询正在运行的进程的可执行文件中包含Chrome的结果
SELECT * FROM Win32_Process WHERE Name LIKE "%chrome%"
           

事件查询

  事件查询提供了报警机制,触发事件的类。用于一个wmi事件注册机制,如wmi对象的创建,修改或删除。事件分为内部时间和外部事件。

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

SELECT [Class property name|*] FROM [EXTRINSIC CLASS NAME] <WHERE [CONSTRAINT]>
           
//可移动没提插入时的事件查询触发器
SELECT * FROM Win32_VolumeChangeEvent WHERE EventType = 2

//交互式用户登录的事件查询触发器
SELECT * FROM __InstanceCreationEvent WITHIN 15 WHERE TargetInstance ISA 'Win32_LogonSession' AND TargetInstance.LogonType = 2
           

元查询

  元查询提供一个 WMI 类架构发现和检查机制.

//查询所有以Win32开头的WMI类
SELECT * FROM Meta_Class WHERE __Class LIKE "Win32%"
           

WMI交互

PowerShell

  作为功能强大的脚本语言,PowerShell包含了丰富的与WMI进行交互的功能,常用的命令如下:

PowerShell操作WMI命令文档

  • Get-WmiObject:获取WMI类的实例或有关可用类的信息。
  • Get-CimAssociatedInstance:检索通过关联连接到特定CIM实例的CIM实例。
  • Get-CimClass:获取特定名称空间中的CIM类列表。
  • Get-CimInstance:从CIM服务器获取类的CIM实例。
  • Get-CimSession:从当前会话获取CIM会话对象。
  • Set-WmiInstance:创建或更新现有WMI类的实例。
  • Set-CimInstance:通过调用CIM类的ModifyInstance方法,修改CIM服务器上的CIM实例
  • Invoke-WmiMethod:调用WMI方法。
  • Invoke-CimMethod:调用CIM类的方法。
  • New-CimInstance:创建一个CIM实例。
  • New-CimSession:创建CIM会话。
  • New-CimSessionOption:为New-CimSession 命令t指定高级选项。
  • Register-CimIndicationEvent:订阅使用筛选器表达式或查询表达式的指示。
  • Register-WmiEvent:订阅WMI事件。
  • Remove-CimInstance:从计算机中删除CIM实例。
  • Remove-WmiObject:删除一个存在的WMI类实例
  • Remove-CimSession:删除一个或多个CIM会话

  WMI 和 CIM 的 cmdlet 也提供了类似的功能。然而,CIM cmdlet 引入了 PowerShell V3,并通过 WMI cmdlets 提供了一些额外的灵活性。使用 CIM cmdlet 的最大优点是它们工作在 WinRM 和 DCOM 协议之上。WMI cmdlet 只工作在 DCOM 协议之上。但是并不是所有的系统都将安装 PowerShell v3+。PowerShell v2 是默认安装在 Windows 7 上的。因此,它被攻击者视为最小公共程序。

wmic.exe

  wmic.exe 是一个与 WMI 进行交互的强大的命令行实用工具。它拥有大量的 WMI 对象的方便记忆的默认别名,我们还可以执行更为复杂的查询。wmic.exe 还可以执行 WMI 方法,攻击者经常用来通过调用 Win32_Process 的 Create 方法来进行横向运动。Wmic.exe 的局限性之一是不能接受调用嵌入的 WMI 对象的方法。在 PowerShell 不可用的情况下,使用 wmic.exe 足够用于执行系统侦察和基本方法的调用。

wbemtest.exe

  wbemtest.exe 是一个功能强大的带有图形界面的 WMI 诊断工具。它能够枚举对象实例、执行查询、注册事件、修改 WMI 对象和类,并且可以在本地或远程去调用方法。它的接口对大多数用户来说不是特别友好,但从攻击者的角度来看,在其他工具不可用时,它完全可以作为替代选项 —— 例如,如果应用程序白名单机制阻止了 wmic.exe 和 powershell.exe,那么 wbemtest.exe 将是一个带有一个不太理想的 UI但是功能却很强大的实用工具。

WMI Explorer

  WMI Explorer 是一个很好的 WMI 类发现工具。它提供了一个优雅的 GUI ,可以使用分层次的方式探索 WMI 存储库。它也能够连接到远程的 WMI 存储库,并执行查询。

Windows脚本宿主(WSH)语言

  Microsoft 提供了两个 WSH 脚本语言,VBScript 和 JScript。尽管它们比较过时,也算不上高雅的编程语言,但是说到与 WMI 进行交互时,它们的确都是功能强大的脚本语言。此外,它们是唯一支持 ActiveScriptEventConsumer 事件消费者组件的语言,该组件对于攻击者和防御者来说都是一个非常有价值的 WMI 组件。最后,从攻击的角度来看, VBScript 和 JScript 是在未安装 PowerShell 的老版本的 Windows 系统上的最小公共程序。

wmi基础Windows管理规范基础

C/C++调用IWbem* COM API

C/C++提供的COM接口

.NET System.Management类

  .NET 类库在 System.Management 命名空间中提供了几个与 WMI 相关的类,可以相对简单的使用如 C#、VB.Net 和 F# 语言编写与 WMI 交互的程序。

winrm.exe

  winrm.exe 可以在运行 WinRM 服务的本地和远程计算机上进行枚举 WMI 对象实例、调用方法,并创建和删除对象实例。也可以用 winrm.exe 来配置 WinRM 设置。

远程使用

  虽然可以与本地的 WMI 进行交互,但是通过网络才能显示出 WMI 的真实能量。目前,由于 DCOM 和 WinRM 这两个协议的存在,将使得远程对象的查询,事件注册, WMI 类方法的执行,以及类的创建都能够被支持。

  • 分布式组件对象模型(DCOM):从 DCOM 出现以来它一直是 WMI 所使用的默认协议,通过 TCP 的 135 端口建立初始连接。后续的数据交换则使用随机选定的 TCP 端口。在 PowerShell 中内置的所有 WMI cmdlets 都是使用 DCOM 进行通信的。
  • Windows远程管理(WinRM):最近, WinRM 取代了 DCOM 并成为 Windows 推荐的远程管理协议。WinRM 的构建基于 Web 服务管理 (WSMan) 规范 —— 一种基于 SOAP 的设备管理协议。此外,PowerShell 的远程传输协议也是基于 WinRM 规范的,同时 PowerShell 提供了极其强大的 Windows 企业级的远程管理。WinRM 也支持 WMI,以及通过网络执行 CIM 操作。

WMI事件

  从攻击者或防御者的角度来看, WMI 最强大的功能之一就是对 WMI 事件的异步响应的能力。除了少数例外,WMI 事件几乎可以用于对操作系统的任何事件作出响应。例如,WMI 事件可能用于触发一个进程创建的事件。这种机制可随后被用作在任何 Windows 操作系统上执行命令行审计。

  有两类 WMI 事件,内部事件和外部事件 , 它们都运行在本地的单个进程和 WMI 永久事件订阅的上下文中。本地事件可以维持宿主进程的生存期,尽管 WMI 永久事件订阅存储在 WMI 存储库中,但是作为 SYSTEM 权限运行后依旧可以在重新启动之后继续持续运行。

  如果想要拥有一个永久事件订阅,必须要做三件事:

  1. 事件筛选器(filter):系统每时每刻都有大量事件,通过自定义的筛选器,我们可以捕获感兴趣的事件进行处理
  2. 事件消费者(consumer):要在事件被触发时执行的操作,它是由可执行程序、动态链接库或脚本组成
  3. 消费者绑定筛选器(binding):通过将筛选器和消费者绑定,明确什么事件由什么消费者处理

事件筛选器

  事件筛选器描述了感兴趣的事件并且执行了 WQL 事件查询。一旦系统管理员配置了筛选器,他们就可以使用它在创建新的事件时接收到通知。

  事件筛选器都被存储为一个 ROOT\subscription:__EventFilter 对象的实例。事件筛选器查询支持以下类型的事件:

  • 内部事件

      内部事件表示的是创建、修改和删除任何 WMI 类,对象或命名空间的事件。它们也可被用于计时器或 WMI 方法执行的警报。以下内部事件采用了系统类 (以两个下划线开头的那些) 的形式,并存在于每一个 WMI 命名空间,这些事件的作用非常强大,因为它们可以被用于在操作系统中几乎任何可以想见的事件的触发器:

    1. __NamespaceOperationEvent:所有与命名空间相关的内部事件的基类。
    2. __NamespaceModificationEvent:报告一个命名空间修改事件,这是一种内部事件,在命名空间被修改时产生。
    3. __NamespaceDeletionEvent:报告一个命名空间删除事件,这是一种内在事件,当子命名空间从当前命名空间中删除时产生。
    4. __NamespaceCreationEvent:报告一个命名空间创建事件,这是一种内部事件,当一个新的命名空间被添加到当前命名空间时产生。
    5. __ClassOperationEvent:所有与类相关的内部事件的基类。
    6. __ClassDeletionEvent:表示一个类删除事件,它是当一个类从命名空间中删除时产生的一种内部事件。
    7. __ClassModificationEvent:表示一个类修改事件,这是类在命名空间中发生更改时产生的一种内部事件。
    8. __ClassCreationEvent:表示一个类创建事件,这是一种当一个新类被添加到命名空间时产生的内部事件类型。
    9. __InstanceOperationEvent:所有与实例相关的内部事件的基类。
    10. __InstanceCreationEvent:报告一个实例创建事件,这是一种内部事件,当一个新实例被添加到命名空间时产生。
    11. __InstanceModificationEvent:报告一个实例修改事件,这是一种内部事件,当一个实例在命名空间中发生变化时产生。
    12. __InstanceDeletionEvent:报告一个实例删除事件,这是一种内部事件,当一个实例在命名空间中被删除时产生。

  由于触发的内部事件有一定的频率,所以必须在 WQL 查询语句的 WITHIN 子句中指定事件轮询间隔。这就是说,它有时可能错过事件。

  • 外部事件

      外部事件解决了和内部事件有关的潜在的轮询问题,因为它们在事件发生时立刻被触发。然而美中不足的是在 WMI 中并没有太多的外部事件,不过,所有已经存在的外部事件的作用很强大,性能也很高。

    1. ROOT\CIMV2:Win32_ComputerShutdownEvent:此事件类表示计算机开始关闭过程时发生的事件。
    2. ROOT\CIMV2:Win32_IP4RouteTableEvent:表示由于计算机系统上的IP路由添加、删除或修改而导致的IP路由更改事件。
    3. ROOT\CIMV2:Win32_ProcessStartTrace:表示一个新进程已经启动。
    4. ROOT\CIMV2:Win32_ModuleLoadTrace:指示进程已经加载了一个新模块。
    5. ROOT\CIMV2:Win32_ThreadStartTrace:表示一个新线程已经启动。
    6. ROOT\CIMV2:Win32_VolumeChangeEvent:表示在计算机系统(例如CDROM)上添加驱动器号或挂载驱动器而产生的本地驱动器事件(不持支网络驱动器)
    7. ROOT\DEFAULT:RegistryKeyChangeEvent:表示对特定键的更改。所做的更改仅适用于键,而不适用于其子键
    8. ROOT\DEFAULT:RegistryValueChangeEvent:表示对特定键的单个值的更改

事件消费者

  事件消费是一个派生自 __EventConsumer 系统类的类,它表示了在事件触发时的动作。系统提供了以下有用的标准事件消费类,他们都隶属于Root\CIMV2和Root\DEFAULT:

  • LogFileEventConsumer - 将事件数据写入到指定的日志文件
  • ActiveScriptEventConsumer - 执行嵌入的 VBScript 或 JScript 脚本 payload
  • NTEventLogEventConsumer - 创建一个包含事件数据的事件日志条目
  • SMTPEventConsumer - 发送一封包含事件数据的电子邮件
  • CommandLineEventConsumer - 执行一个命令行程序

  攻击者在响应他们的事件时,大量使用 ActiveScriptEventConsumer 和 CommandLineEventConsumer 类。这两个事件消费者为攻击者提供了极大的灵活性去执行他们想要执行的任何 payload 并且无需写入一个恶意的可执行文件或脚本到磁盘。

继续阅读