【应急响应】WMI事件消费者

    应急响应 lz520520 5年前 (2019-10-09) 1435次浏览

    0x00 前言

    最近听说powershell挖矿又变种了,其实我觉得这个病毒的手法还是蛮高明的,wmi消费事件启动,powershell无文件落地的方式,可以绕过一些杀软的监测,让一些安全小白也无从下手去处理。回想起第一次应急就遇到这个病毒的时候,当时还是小白,对powershell和wmi一脸懵逼,客户说内网老是蓝屏,老是有powershell程序运行,用杀软也杀不出病毒,也不知道怎么处理,当时找了半天文章才发现有类似的分析文章,最后尝试使用里面提供的几句powerhell代码,意想不到的病毒不再发作了。回头仔细看了那篇分析文章,发现关键点在于一个wmi的操作,上网也查了wmi和powershell那几句命令的相关资料,最后才明白该病毒是使用wmi消费事件自启动,并在运行的时候读取保存在wmi类里的变量,解码后在内存中释放运行各个模块,所以下面我会讲解下该自启动操作是怎么实现的,并且怎么通过脚本去清除,因为这次变种和原来的自启动操作差不多,所以理解了启动原理,针对新的变种也就好改脚本去清除了呀。

     

     

    0x01 wmi事件消费者

    WMI是Windows的一个核心组件,通常用于日常管理任务,比如部署自动化脚本、在指定时间点运行进程或程序、获取已安装的应用或硬件信息、监控目录修改动作、监控硬盘空间等。

    WMI的“事件永久消费者”可实现不依赖编写进程来接收事件,即只要WMI服务运行,即可监控事件。当监控到指定事件发生时,就会执行消费者预先设定好的功能。

    可能比较抽象,我直接从病毒样本中拉出事件消费者设置的代码。

    如下所示

    #过滤器设置

    $Query = "SELECT * FROM __InstanceModificationEvent WITHIN 5600 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"

    $filterName = 'Windows Events Filter'

    $FilterParams = @{

    Namespace = 'root\subscription'

    Class = '__EventFilter'

    Arguments =@{Name=$filterName;EventNameSpace='root\cimv2';QueryLanguage='WQL';Query=$Query}

    ErrorAction = 'SilentlyContinue'

    }

     

    $WMIEventFilter = Set-WMIInstance @FilterParams

     

    #消费事件设置

    $consumerName = 'Windows Events Consumer'

    $Script = 'ping -t http://www.qq.com'

    $Scriptbytes = [System.Text.Encoding]::Unicode.GetBytes($Script)

    $EncodedScript=[System.Convert]::ToBase64String($Scriptbytes)

    $ConsumerParams = @{

    Namespace = 'root\subscription'

    Class = 'CommandLineEventConsumer'

    Arguments =@{ Name = $consumerName; CommandLineTemplate='powershell.exe -NoP -NonI -W Hidden -E '+"$EncodedScript"}

    ErrorAction = 'SilentlyContinue'

    }

     

    $WMIEventConsumer = Set-WMIInstance @ConsumerParams

     

    #将过滤器和事件消费者绑定在一起

    Set-WmiInstance -Class __FilterToConsumerBinding -Namespace 'root\subscription' -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer} | Out-Null

     

    其中涉及到三个类

    __EventFilter

    CommandLineEventConsumer

    __FilterToConsumerBinding

     

    __EventFilter类用来设置一个事件过滤器,CommandLineEventConsumer是可以用来执行二进制程序的消费者,而__FilterToConsumerBinding是用来将指定过滤器和事件消费者绑定起来。实现的效果就是当某个事件被配置的过滤器捕捉到,会触发与过滤器绑定的消费者,消费者会指定预先设置好的功能。

     

     

    结合上述代码,事件过滤器为命名空间root\subscription下的__EventFilter类的实例,实例名称为“Windows Events Filter”,而WQL查询语句内容如下

    SELECT * FROM __InstanceModificationEvent WITHIN 5600 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'

    #过滤器设置

    $Query = "SELECT * FROM __InstanceModificationEvent WITHIN 5600 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"

    $filterName = 'Windows Events Filter'

    $FilterParams = @{

    Namespace = 'root\subscription'

    Class = '__EventFilter'

    Arguments =@{Name=$filterName;EventNameSpace='root\cimv2';QueryLanguage='WQL';Query=$Query}

    ErrorAction = 'SilentlyContinue'

    }

     

    $WMIEventFilter = Set-WMIInstance @FilterParams

     

    查阅微软文档,__InstanceModificationEvent类会报告实例修改事件,事件是在命名空间中实例更改时生成的一种内部事件。其中有一个属性是TargetInstance,表示实例修改事件中所对应的实例对象。

     

    【应急响应】WMI事件消费者

     

    而 'Win32_PerfFormattedData_PerfOS_System'格式的数据类从性能计数器提供预先计算的数据,这些计数器监视计算机上多个组件处理器的实例。

     

    【应急响应】WMI事件消费者

     

    所以WQL语句意思为每5600秒查询实例修改事件类中的所有实例,这些实例有从Win32_PerfFormattedData_PerfOS_System类派生的任何类的成员。

    而Win32_PerfFormattedData_PerfOS_System类提供的数据为性能计数器产生,性能计数器基本上时时刻刻都在变化,所以对应的实例肯定在实例修改事件中,进而通过WQL语句肯定能查询成功。

    所以每隔5600秒必定会触发过滤器所绑定的消费事件。

     

    我们再看来下消费事件,消费事件为命名空间root\subscription下的CommandLineEventConsumer类的实例,实例名称为Windows Events Consumer,执行的命令为powershell.exe -NoP -NonI -W Hidden -E $EncodedScript。其中$EncodedScript为编码后的命令。

    #消费事件设置

    $consumerName = 'Windows Events Consumer'

    $Script = 'ping -t http://www.qq.com'

    $Scriptbytes = [System.Text.Encoding]::Unicode.GetBytes($Script)

    $EncodedScript=[System.Convert]::ToBase64String($Scriptbytes)

    $ConsumerParams = @{

    Namespace = 'root\subscription'

    Class = 'CommandLineEventConsumer'

    Arguments =@{ Name = $consumerName; CommandLineTemplate='powershell.exe -NoP -NonI -W Hidden -E '+"$EncodedScript"}

    ErrorAction = 'SilentlyContinue'

    }

     

    $WMIEventConsumer = Set-WMIInstance @ConsumerParams

     

    最后通过__FilterToConsumerBinding类的实例,将事件过滤器实例与事件消费者实例绑定起来。

    #将过滤器和事件消费者绑定在一起

    Set-WmiInstance -Class __FilterToConsumerBinding -Namespace 'root\subscription' -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer} | Out-Null

     

    这样讲上述代码运行,即可产生一个永久事件消费者,以此即可启动设定好的恶意程序。

     

     

    0x02 wmi分析

    当已感染这种病毒,我们该怎么去查看启动项,下面会讲解两种方式。

    首先第一种最简单的,使用autoruns工具,可以直接读取到wmi里的启动项。如下图所示

    【应急响应】WMI事件消费者

    可以看到事件消费者名称,WQL查询语句,以及执行的命令。

    要处理就右键删除即可。

     

    第二种是使用wmi测试器,一个微软提供的用于与WMI基础结构交互的通用、图形化工具。

    使用命令wbemtest.exe可以打开测试器。

    【应急响应】WMI事件消费者

     

    点击连接,输入之前powerhsell代码设置的命令空间,如下,再点新窗口里的连接。

    【应急响应】WMI事件消费者

     

     

    然后枚举所有类

    【应急响应】WMI事件消费者

     

     

    找到__FilterToConsumerBinding类,点开

    【应急响应】WMI事件消费者

     

     

    然后点击实例

    【应急响应】WMI事件消费者

     

    就可以在里面找到我们创建的实例了。

    【应急响应】WMI事件消费者

     

    点开这个实例,可以找到他的属性__PATH,属性值表明绑定的事件消费者和事件过滤器。

    【应急响应】WMI事件消费者

     

     

    我们用相同的方法查看__EventFilter,CommandLineEventConsumer的实例

    【应急响应】WMI事件消费者

     

    【应急响应】WMI事件消费者

     

    可以看到上面查找到的实例属性和脚本里的一一对应上,也可以通过这里手动删除。

     

    最后一处需要提醒的就是,上面说的是病毒自启动操作,病毒还会从WMI管理的类中读取各个模块运行。

    存放在命名空间root\default下,类名为System_Anti_Virus_Core,可以看到该类属性有很多异常数据。

    【应急响应】WMI事件消费者

     

     

    单独提取一个funs属性,看上去很像base64编码,尝试解码发现为powershell代码,其他属性还有PE文件编码。

    【应急响应】WMI事件消费者

     

     

    0x03 脚本编写清除

    根据上面分析,病毒创建了三个实例,和一个病毒类。所以反向清除即可。

    清除脚本如下

    Get-WmiObject -Namespace root\Subscription -Class __EventFilter -filter "Name= 'Windows Events Filter'" | Remove-WmiObject -Verbose

    Get-WmiObject -Namespace root\Subscription -Class CommandLineEventConsumer -Filter "Name='Windows Events Consumer'" | Remove-WmiObject -Verbose

    Get-WmiObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "__Path LIKE '%Windows Events Consumer%'" |Remove-WmiObject -Verbose

    ([WmiClass]'root\default:System_Anti_Virus_Core') | Remove-WmiObject -Verbose

    Get-Process -Name "powershell" | Stop-Process

     

    通过Get-WmiObject获取指定命令空间指定类的指定实例,然后传递给Remove-WmiObject,即可移除病毒实例和类。

    其中-filter为过滤器,过滤指定属性如Name或__Path,匹配方式有“=”、“LIKE”,一个是精确匹配,一个是模糊匹配,%表示任意个字符,可匹配任意类型和长度的字符。由于__FilterToConsumerBinding 的__Path属性包含属性字符串,所以匹配某一段即可。

    最后一行是清除名称为powershell的进程,通过启动项及进程,将病毒清除干净。

    以后如果遇到类似方式的病毒,就不需要手动一个个去处理了,理解了病毒运行的原理,编写特定的脚本清除,会更高效。

     

    下面就是我将分析后的结果合入到我专杀工具里变成通用模块,通过配置文件设置需要清除的实例或类路径即可,这个专杀工具可以参考我的另一篇文章。

    【应急响应】WMI事件消费者

     

     

    0x04 结语

    关于WMI的内容其实有蛮多的,经常会调用里面的类来监控系统,发现真香,本次主要是结合一种新型病毒的持久化方式来分析,,我也期待能发现更多有趣的骚操作。之前其实已经分析过这类病毒了,这回算是将经验总结一下,也觉得对他的原理更清晰了,不过大家学习看看就好,不要拿这种方式来搞事情。如果看完有什么疑问的,欢迎给我留言。

     

    0x05 参考

    https://docs.microsoft.com/zh-cn/windows/desktop/WmiSdk/--instancemodificationevent#properties

    https://docs.microsoft.com/en-us/previous-versions//aa394272(v=vs.85)

    https://docs.microsoft.com/zh-cn/windows/desktop/WmiSdk/wql-sql-for-wmi

    https://docs.microsoft.com/zh-cn/windows/desktop/WmiSdk/isa-operator-for-schema-queries

    https://blog.csdn.net/breaksoftware/article/details/50644665


    Security , 版权所有丨如未注明 , 均为原创丨
    转载请注明原文链接:【应急响应】WMI事件消费者
    喜欢 (10)