WMI(Windows Management Instrumentation)自Windows 2000以来不停是Windows操纵体系中的一个功效,该功效对体系管理员来说是异常重要的,它可以或许得到计算机外部状况的信息,可以或许对磁盘、进程、和其余 Windows 体系对象停止建模,从而实现“唆使”功效。恰是因为WMI的这类灵活性,在它晚期被引入Windows操纵体系时,收集入侵攻击者常常应用WMI来对计算机实行入侵攻击。WMI是微软Windows操纵体系中的一个异常重要的技巧,但从网安的角度斟酌,今朝尚未一种卓有成效的办法去记载某用户操纵WMI功效的行动运动。对付“防守者”而言,他们平日应用第三方对象或本身编写的解决方案往来来往记载操纵WMI的行动运动,但这在一定程度上并不可以或许阻拦“入侵攻击者”操纵WMI来履行各类收集入侵攻击的行动。在本文中,咱们将看看微软是若何改良记载WMI操纵行动功效的。
WMI Activity Provider
在2012年以前,Windows体系中的WMI Activity变乱日记法式重要用于在WMI启历时记载其跟踪和调试信息,但在Windows新刊行版本中扩大了该法式的功效,应用Operational选项可以或许对WMI的操纵行动停止记载。上面咱们将应用PowerShell对该新功效停止阐发,并应用Get-WinEvent cmdlet来得到信息。
咱们起首得到Provider法式的对象:
PS C:\> $WmiProv = Get-WinEvent-ListProvider "Microsoft-Windows-WMI-Activity"
PS C:\> $WmiProv
Name : Microsoft-Windows-WMI-Activity
LogLinks : {Microsoft-Windows-WMI-Activity/Trace, Microsoft-Windows-WMI-Activity/Operational, Microsoft-Windows-WMI-Activity/Debug}
Opcodes : {}
Tasks : {}
PowerShell对该对象的输入停止了格局化处置,是以咱们必要应用Format-List参数来检查一切属性和属性的值。
PS C:\> $WmiProv | Format-List -Property *
ProviderName : Microsoft-Windows-WMI-Activity
Name : Microsoft-Windows-WMI-Activity
Id : 1418ef04-b0b4-4623-bf7e-d74ab47bbdaa
MessageFilePath : C:\WINDOWS\system32\wbem\WinMgmtR.dll
ResourceFilePath : C:\WINDOWS\system32\wbem\WinMgmtR.dll
ParameterFilePath :
HelpLink :https://go.microsoft.com/fwlink/events.asp?CoName=MicrosoftCorporation&ProdName=Microsoft@Windows@Operating
System&ProdVer=10.0.15063.0&FileName=WinMgmtR.dll&FileVer=10.0.15063.0
DisplayName : Microsoft-Windows-WMI-Activity
LogLinks : {Microsoft-Windows-WMI-Activity/Trace, Microsoft-Windows-WMI-Activity/Operational, Microsoft-Windows-WMI-Activity/Debug}
Levels : {win:Error, win:Informational}
Opcodes : {}
Keywords : {}
Tasks : {}
Events : {1, 2, 3, 11...}
上面让咱们看看LogLinks或许Provider法式将变乱日记保留在哪里。
PS C:\> $WmiProv.LogLinks
LogName IsImported DisplayName
------- ---------- -----------
Microsoft-Windows-WMI-Activity/Trace False
Microsoft-Windows-WMI-Activity/Operational False
Microsoft-Windows-WMI-Activity/Debug False
上述Powershell的输入中,咱们比拟感兴趣的是Microsoft-Windows-WMI-Activity/Operational。如今咱们曾经肯定了哪一个EventLog会保留咱们感兴趣变乱的日记,上面咱们可以或许看看Provider法式天生的变乱日记。平日情况下,Provider可以或许从几个变乱中天生跨越100个变乱日记。是以,咱们应用Measure-Object cmdlet来检查Provider天生的变乱数目。
PS C:\> $WmiProv.Events | Measure-Object
Count : 22
Average :
Sum :
Maximum :
Minimum :
Property :
经由进程上述输入咱们看到Provider天生了22个变乱,上面咱们应用Get-Member cmdlet来看看若何组合每一个对象。
PS C:\> $WmiProv.Events | Get-Member
TypeName: System.Diagnostics.Eventing.Reader.EventMetadata
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Description Property string Description {get;}
Id Property long Id {get;}
Keywords Property System.Collections.Generic.IEnumerable[System.Diagnostics.Eventing.Reader.EventKeyword] Keywords {get;}
Level Property System.Diagnostics.Eventing.Reader.EventLevel Level {get;}
LogLink Property System.Diagnostics.Eventing.Reader.EventLogLink LogLink {get;}
Opcode Property System.Diagnostics.Eventing.Reader.EventOpcode Opcode {get;}
Task Property System.Diagnostics.Eventing.Reader.EventTask Task {get;}
Template Property string Template {get;}
Version Property byte Version {get;}
经由进程上面的输入咱们发明每一个变乱都有一个LogLink属性,且属性值为System.Diagnostics.Eventing.Reader.EventLogLink ,上面咱们来看看这些对象的值是若何构成的。
PS C:\> $WmiProv.Events[0].LogLink
LogName IsImported DisplayName
------- ---------- -----------
Microsoft-Windows-WMI-Activity/Trace False
PS C:\> $WmiProv.Events[0].LogLink | gm
TypeName: System.Diagnostics.Eventing.Reader.EventLogLink
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
DisplayName Property string DisplayName {get;}
IsImported Property bool IsImported {get;}
LogName Property string LogName {get;}
履行上面这个敕令可以或许筛选出咱们想要检查的变乱。
PS C:\> $WmiProv.Events | Where-Object {$_.LogLink.LogName -eq "Microsoft-Windows-WMI-Activity/Operational"}
Id : 5857
Version : 0
LogLink : System.Diagnostics.Eventing.Reader.EventLogLink
Level : System.Diagnostics.Eventing.Reader.EventLevel
Opcode : System.Diagnostics.Eventing.Reader.EventOpcode
Task : System.Diagnostics.Eventing.Reader.EventTask
Keywords : {}
Template : "http://schemas.microsoft.com/win/2004/08/events">
"ProviderName" inType="win:UnicodeString" outType="xs:string"/>
"Code" inType="win:HexInt32" outType="win:HexInt32"/>
"HostProcess" inType="win:UnicodeString" outType="xs:string"/>
"ProcessID" inType="win:UInt32" outType="xs:unsignedInt"/>
"ProviderPath" inType="win:UnicodeString" outType="xs:string"/>
Description : %1 provider started with result code %2. HostProcess = %3; ProcessID = %4; ProviderPath = %5
Id : 5858
Version : 0
LogLink : System.Diagnostics.Eventing.Reader.EventLogLink
Level : System.Diagnostics.Eventing.Reader.EventLevel
Opcode : System.Diagnostics.Eventing.Reader.EventOpcode
Task : System.Diagnostics.Eventing.Reader.EventTask
Keywords : {}
Template : "http://schemas.microsoft.com/win/2004/08/events">
"Id" inType="win:UnicodeString" outType="xs:string"/>
"ClientMachine" inType="win:UnicodeString" outType="xs:string"/>
"User" inType="win:UnicodeString" outType="xs:string"/>
"ClientProcessId" inType="win:UInt32" outType="xs:unsignedInt"/>
"Component" inType="win:UnicodeString" outType="xs:string"/>
"Operation" inType="win:UnicodeString" outType="xs:string"/>
"ResultCode" inType="win:HexInt32" outType="win:HexInt32"/>
"PossibleCause" inType="win:UnicodeString" outType="xs:string"/>
Description : Id = %1; ClientMachine = %2; User = %3; ClientProcessId = %4; Component = %5; Operation = %6; ResultCode = %7; PossibleCause = %8
Id : 5859
Version : 0
LogLink : System.Diagnostics.Eventing.Reader.EventLogLink
Level : System.Diagnostics.Eventing.Reader.EventLevel
Opcode : System.Diagnostics.Eventing.Reader.EventOpcode
Task : System.Diagnostics.Eventing.Reader.EventTask
Keywords : {}
Template : "http://schemas.microsoft.com/win/2004/08/events">
"NamespaceName" inType="win:UnicodeString" outType="xs:string"/>
"Query" inType="win:UnicodeString" outType="xs:string"/>
"User" inType="win:UnicodeString" outType="xs:string"/>
"processid" inType="win:UInt32" outType="xs:unsignedInt"/>
"providerName" inType="win:UnicodeString" outType="xs:string"/>
"queryid" inType="win:UInt32" outType="xs:unsignedInt"/>
"PossibleCause" inType="win:UnicodeString" outType="xs:string"/>
Description : Namespace = %1; NotificationQuery = %2; OwnerName = %3; HostProcessID = %4; Provider= %5, queryID = %6; PossibleCause = %7
Id : 5860
Version : 0
LogLink : System.Diagnostics.Eventing.Reader.EventLogLink
Level : System.Diagnostics.Eventing.Reader.EventLevel
Opcode : System.Diagnostics.Eventing.Reader.EventOpcode
Task : System.Diagnostics.Eventing.Reader.EventTask
Keywords : {}
Template : "http://schemas.microsoft.com/win/2004/08/events">
"NamespaceName" inType="win:UnicodeString" outType="xs:string"/>
"Query" inType="win:UnicodeString" outType="xs:string"/>
"User" inType="win:UnicodeString" outType="xs:string"/>
"processid" inType="win:UInt32" outType="xs:unsignedInt"/>
"MachineName" inType="win:UnicodeString" outType="xs:string"/>
"PossibleCause" inType="win:UnicodeString" outType="xs:string"/>
Description : Namespace = %1; NotificationQuery = %2; UserName = %3; ClientProcessID = %4, ClientMachine = %5; PossibleCause = %6
Id : 5861
Version : 0
LogLink : System.Diagnostics.Eventing.Reader.EventLogLink
Level : System.Diagnostics.Eventing.Reader.EventLevel
Opcode : System.Diagnostics.Eventing.Reader.EventOpcode
Task : System.Diagnostics.Eventing.Reader.EventTask
Keywords : {}
Template : "http://schemas.microsoft.com/win/2004/08/events">
"Namespace" inType="win:UnicodeString" outType="xs:string"/>
"ESS" inType="win:UnicodeString" outType="xs:string"/>
"CONSUMER" inType="win:UnicodeString" outType="xs:string"/>
"PossibleCause" inType="win:UnicodeString" outType="xs:string"/>
Description : Namespace = %1; Eventfilter = %2 (refer to its activate eventid:5859); Consumer = %3; PossibleCause = %4
此时,咱们可以或许看到与变乱日记相干联的特定变乱,而且咱们还可以或许得到到每一个变乱的细节信息,其中包含新闻的XML模板,该信息在咱们编写XPath过滤器时是非常有用的。咱们可以或许将它们保留到一个变量中,并从中得到变乱的ID,详细操纵如下所示:
PS C:\> $WmiEvents = $WmiProv.Events | Where-Object {$_.LogLink.LogName -eq "Microsoft-Windows-WMI-Activity/Operational"}
PS C:\> $WmiEvents | Select-Object -Property Id
Id
--
5857
5858
5859
5860
5861
Provider加载进程
每当WMI被初始化时,它将加载用于构建类的Provider法式,并向外界供给用来拜访操纵体系和体系组件的功效。这些功效都是在以后用户的SYSTEM上下文情况中履行的,也就是说,它们在Windows中将以异常高的特权履行。 是以,入侵攻击者们平日会把歹意的Provider法式用作后门,以便可以或许连续的、高权限的对Windows操纵体系停止拜访。上面是一些歹意的Provider法式示例:
https://gist.github.com/subTee/c6bd1401504f9d4d52a0 SubTee Shellcode Execution WMI Class
https://github.com/jaredcatkinson/EvilNetConnectionWMIProvider Jared Atkinson Evil WMI Provider Example
在变乱ID列表中,咱们注意到一个ID为5857的变乱,该变乱的布局中有一些异常有价值的信息,详细概况如下所示:
从上图布局信息中咱们可以或许发明加载Provider法式的ProcessID和Thread信息,而且咱们还可以或许看到主机进程的称号和加载的DLL门路。假如咱们应用Windows变乱收集器,咱们可以或许依据已知Provider创立一个XML过滤器,应用该过滤器可以或许对上述的输入成果履行过滤操纵以得到未知的Provider法式,上面咱们应用PowerShell天生一个简略的privider文件列表,详细输入如下所示:
PS C:\> Get-WinEvent -FilterHashtable @{logname='Microsoft-Windows-WMI-Activity/Operational';Id=5857} | % {$_.properties[4].value} | select -unique
%SystemRoot%\system32\wbem\wbemcons.dll
%systemroot%\system32\wbem\wmipiprt.dll
%systemroot%\system32\wbem\wmiprov.dll
C:\Windows\System32\wbem\krnlprov.dll
%systemroot%\system32\wbem\wmipcima.dll
C:\Windows\System32\wbem\WmiPerfClass.dll
%SystemRoot%\system32\tscfgwmi.dll
%systemroot%\system32\wbem\cimwin32.dll
%systemroot%\system32\wbem\vdswmi.dll
%SystemRoot%\System32\sppwmi.dll
%systemroot%\system32\wbem\WMIPICMP.dll
%SystemRoot%\System32\Win32_DeviceGuard.dll
%SYSTEMROOT%\system32\PowerWmiProvider.dll
%SystemRoot%\System32\storagewmi.dll
%systemroot%\system32\wbem\stdprov.dll
%systemroot%\system32\profprov.dll
C:\Windows\System32\wbem\WmiPerfInst.dll
%systemroot%\system32\wbem\DMWmiBridgeProv.dll
C:\Windows\SysWOW64\wbem\WmiPerfClass.dll
咱们可以或许将其转换为XML过滤器,并应用Get-WinEvent或WEC停止变乱日记的收集,详细操纵如下所示:
"0" Path="Microsoft-Windows-WMI-Activity/Operational">
"Microsoft-Windows-WMI-Activity/Operational">*[System[(EventID=5857)]]
"Microsoft-Windows-WMI-Activity/Operational">
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\wmiprov.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\wmipcima.dll']) or
(*[UserData/*/ProviderPath='%SystemRoot%\System32\sppwmi.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\vdswmi.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\DMWmiBridgeProv.dll']) or
(*[UserData/*/ProviderPath='C:\Windows\System32\wbem\WmiPerfClass.dll']) or
(*[UserData/*/ProviderPath='C:\Windows\System32\wbem\krnlprov.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\wmipiprt.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\stdprov.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\profprov.dll']) or
(*[UserData/*/ProviderPath='%SystemRoot%\System32\Win32_DeviceGuard.dll']) or
(*[UserData/*/ProviderPath='%SystemRoot%\System32\smbwmiv2.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\cimwin32.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\wmiprvsd.dll']) or
(*[UserData/*/ProviderPath='%SystemRoot%\system32\wbem\scrcons.exe']) or
(*[UserData/*/ProviderPath='%SystemRoot%\system32\wbem\wbemcons.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\vsswmi.dll']) or
(*[UserData/*/ProviderPath='%SystemRoot%\system32\tscfgwmi.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\ServerManager.DeploymentProvider.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\mgmtprovider.dll']) or
(*[UserData/*/ProviderPath='%systemroot%\system32\wbem\ntevt.dll']) or
(*[UserData/*/ProviderPath='%SYSTEMROOT%\System32\wbem\DnsServerPsProvider.dll'])
"Microsoft-Windows-WMI-Activity/Operational">
(*[UserData/*/ProviderPath='%windir%\system32\wbem\servercompprov.dll']) or
(*[UserData/*/ProviderPath='C:\Windows\System32\wbem\WmiPerfInst.dll'])
WMI查问差错
Id为5858的EventLog记载了WMI中一切的查问差错信息,这些信息包含差错代码(ResultCode标签)和惹起差错的缘故原由(Operation标签),还包含进程Pid,该字段信息位于ClientProcessId标签中,详细信息如下图所示:
从上图可以或许看出差错代码是十六进制格局的,不外微软在MSDN中列出了WMI一切的差错常量,咱们可以或许用它来肯定详细的差错信息。 咱们可以或许应用XPathFilter轻松查问特定的成果代码。在如下这个示例中,咱们经由进程搜刮ResultCode 0x80041010来查找失败的查问哀求 ,该操纵可以或许用来肯定入侵攻击者能否正在探求体系上存在的特定类,详细如下所示:
PS C:\> Get-WinEvent -FilterXPath "*[UserData/*/ResultCode='0x80041010']" -LogName "Microsoft-Windows-WMI-Activity/Operational"
咱们还可以或许搜刮因为权限不敷而失败的查问,详细搜刮如下所示:
PS C:\> Get-WinEvent -FilterXPath“* [UserData / * / ResultCode ='0x80041003']”-LogName“Microsoft-Windows-WMI-Activity / Operational”
WMI变乱
WMI变乱界说是当创立特定变乱类实例或直接在WMI模子界说的一类变乱,可以或许经由进程监督Windows中CIM数据库天生的特定变乱来实现变乱的操纵。 大多数变乱会创立一个查问哀求,该哀求中界说了咱们必要履行的操纵,一旦变乱产生就会履行咱们界说的操纵,今朝WMI支撑两种范例的变乱:
暂时变乱:只需创立变乱的进程处于运动状况,暂时变乱就会被激活。 (他们在进程的特权下运转)
耐久变乱:变乱存储在CIM数据库中,而且会不停处于运动状况,直到从数据库中将它移除。 (它们老是作为SYSTEM运转)
暂时变乱
因为某些对象在实现上每每应用暂时变乱,是以一些人觉得耐久性WMI变乱更容易被检测,这些对象平日情况下应用C ++,.Net,WSH或许PowerShell编写,它们容许应用WMI变乱过滤器来触发应当由应用法式本身履行的操纵。 咱们可以或许应用Id 为5860的变乱来跟踪这些操纵。一旦应用法式注册变乱消费者,变乱日记就会被创立。
上面是一个暂时变乱消费者的一个示例,在示例中它简略地写入曾经启动的进程称号。
# Query for new process events
$queryCreate = "SELECT * FROM __InstanceCreationEvent WITHIN 5" +
"WHERE TargetInstance ISA 'Win32_Process'"
# Create an Action
$CrateAction = {
$name = $event.SourceEventArgs.NewEvent.TargetInstance.name
write-host "Process $($name) was created."
}
# Register WMI event
Register-WMIEvent -Query $queryCreate -Action $CrateAction
当变乱消费者注册到Register-WmiEvent时,咱们会在体系上记载以下变乱。
咱们可以或许看到用于监督变乱的查问哀求被记载在UserData下的Query元素中,而在PlaussibleCause元素中,咱们看到它被标志为Temporary。
耐久变乱
当在WMI CIM数据库中创立一个耐久变乱时,体系同时还会创立Id为5861的变乱日记条款,该变乱也会在任何组件类实例被改动时被创立,该变乱将包含一切与耐久性相干的信息,如下图中的“PossibleCause ”子元素所示:
当改动组成耐久变乱的__EventFilter或Consumer时,体系会天生雷同的一个变乱,但数据中并无字段用来表现此变乱能否被改动。也可以或许经由进程Id 为5859的变乱来检查组成耐久变乱的__EventFilter类,然则在我一切测试中,我尚未看到应用此Id创立的变乱。
论断
正如咱们本文中所论述的,在最新版本的Windows中,经由进程参加一些日记功效,微软曾经改良了WMI的一些网安性。然则,这些功效尚未被参加到Windows 7和Windows 2008/2008 R2操纵体系中去。 是以,针对这些体系,咱们必要去可以或许跟踪如下信息:
差错的查问哀求;
暂时变乱的创立;
耐久变乱的创立与改动;
Provider的加载。
从“入侵攻击者”的视角来看,这让咱们晓得咱们的行动可以或许被跟踪,当咱们在实行某些歹意的行动操纵时,咱们应当看看这些变乱能否会被收集。从“防守者”的角度来看,咱们应当在体系情况中收集和阐发上述这些变乱的信息以用于阐发哪些是能够的歹意行动变乱。