Sysmon 是什么
Sysmon 是一款可以全面记录系统行为日志的工具,全称为 System Monitor(系统监视),最初由美国 Winternals 软件有限公司的 Mark Russinovich 编写而成,作为 Sysinternals 实用工具套件的一部分,现在的所有者为微软。
截止至本文发布时间,Sysmon 已经更新至 15.0 版本,且已经支持了 Linux 系统,在大多数国产操作系统中也可以正常工作。
在第一部分中,我们只讨论 Sysmon 的 Windows 版本。
保持敬畏
很多从事红队或渗透测试工作的朋友,在进程列表中遭遇 Sysmon 的第一反应可能是:
- A:它没有任何自身保护功能,Kill 掉它就万事大吉了;
- B:它又不会阻拦我继续进行渗透测试,是无关紧要的;
- C:拜托,很弱的啦。
可事实并非如此,在绝大多数已经部署 Sysmon 的企业或机构网络中,Sysmon 往往不是独立存在的。
Sysmon 可以收集的系统行为日志如下:
- 进程创建
- 进程退出
- 文件的创建时间被修改
- 网络连接
- Sysmon 服务状态更改
- Sysmon 配置更改
- 驱动加载
- 模块加载
- DNS 查询
...
篇幅有限,详细的事件记录请查阅 官方文档。
将各类行为日志提取后,后续的安全日志分析工具就开始发挥作用了,例如全球最流行的开源 SIEM 项目 Wazuh 和全球最大的日志分析商业平台 Splunk,它们采集到 Sysmon 的行为日志后,会通过内置的安全策略对行为日志进行筛选,找出可能对安全存在威胁的系统行为。
这种 日志收集 ->日志筛选 ->安全响应 模式,在安全运维机制良好的网络环境中是长期存在的,入侵者在系统中产生的行为数量,在广泛的行为日志中如沧海一粟。
所以,红队从一开始就处于完全监视之下,对上述模式采取不管不顾甚至是轻视的做法,最终会招致渗透测试完全失败的恶果,这是必然事件。
我们认为,以下做法是完全错误且十分不专业的,且可能会迅速吸引蓝队的注意:
- 尝试破坏 Sysmon(这是最危险的行为)
- 无视 Sysmon
从红队角度看,对行为事件采集源头的 Sysmon 保持敬畏之心,是十分有必要的。
定位 Sysmon
在准备应对 Sysmon 之前,红队必须确定当前系统中是否存在它,我们提供了一些方案用于定位 Sysmon。
Sysmon 由以下部分组成:
- Sysmon 服务程序
- Sysmon 驱动程序
使用 -i 参数可以将 Sysmon 以默认配置部署至系统中,如下图所示:
我们可以在系统服务和进程列表中观察到 Sysmon64,如下图所示:
该服务进程程序的路径默认为:
- C:\Windows\Sysmon64.exe
驱动程序为:
- C:\Windows\SysmonDrv.sys
注册表项路径:
- 服务:HKLM\SYSTEM\ControlSet001\Services\Sysmon64
- 驱动:HKLM\SYSTEM\ControlSet001\Services\SysmonDrv
过滤器实例信息:
- 过滤器名:SysmonDrv
- 实例名:Sysmon Instance
- 过滤器高度:385201
想了解更多有关文件系统微型过滤器的知识,请参考微软 官方文档。
通过查找以上信息,红队可以发现默认配置下的 Sysmon 部署情况,然而,不知出于有意或无意,Sysmon 允许用户通过改变安装参数和信息,避开上述所有的默认特征。
例如,使用如下安装操作,改变服务与进程名:
效果如下:
更多操作可以参考文章:Sysmon hide and seek
红队怎样才能定位到被彻底隐藏的 Sysmon?Sysmon 行为日志收集功能的核心是它的驱动程序,通过向系统注册上面提到的过滤器实例,Sysmon 才得以正常工作,我们可以先尝试枚举出所有的过滤器,然后找到它们对应的驱动程序路径:
Function Select-Column {
[cmdletbinding(PositionalBinding = $False)]
param(
[Parameter(ValueFromPipeline, Mandatory)]
$InputObject,
[Parameter(Mandatory, Position = 0)]
[int[]] $Index,
[Parameter(Position = 1)]
[int] $RequiredCount,
[Parameter(Position = 2)]
[string] $OutFieldSeparator = "`t"
)
process {
if (($fields = -split $InputObject) -and ($RequiredCount -eq 0 -or $RequiredCount -eq $fields.Count)) {
$fields[$Index] -join $OutFieldSeparator
}
}
}
$filterList = & "fltMC.exe" filters
$serviceList = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\*'
$filterList | Select-Column -Index 0 -RequiredCount 4 | Select-Object -Skip 1 | ForEach-Object {
$__ = $_
$serviceList | ForEach-Object {if($_.ImagePath -like "*$__.sys") { $_.ImagePath }}
}
遍历得到的驱动程序,获取它们的附加信息,并检索其中是否包含 Sysmon 关键字,随后,我们成功找到被隐藏起来的 Sysmon 驱动程序,如下图所示:
使用以上过程确定原版 Sysmon 是否部署,是非常准确的,因为,如果蓝队尝试修改掉 Sysmon 驱动程序的附加信息,就会使驱动程序二进制签名校验失败;如果蓝队重新对驱动程序进行签名,那就是另一个痛苦的故事了 🙂
* 如果你一定想破坏掉 Sysmon,较安全的办法已经在前面提到了,请仔细阅读并理解所有内容。
规则提取
以上步骤只是确定 Sysmon 是否部署,我们不建议红队对 Sysmon 功能进行任何形式的更改。
Sysmon 提取的特定行为类型,全部由配置文件定义,配置文件可以在 Sysmon 部署时指定并导入,也可以后续导入或更新,以下内容是一个简单的 Sysmon 配置,它允许 Sysmon 记录 cmd.exe 进程创建事件:
<Sysmon schemaversion="4.1">
<HashAlgorithms>*</HashAlgorithms>
<CheckRevocation/>
<EventFiltering>
<ProcessCreate onmatch="include">
<Image condition="image">cmd.exe</Image>
</ProcessCreate>
</EventFiltering>
</Sysmon>
蓝队通常情况下,会在导入配置文件后,将配置文件删除,这不会影响 Sysmon 的正常工作。Sysmon 配置文件的内容以二进制形式保存在以下注册表值项中:
- HKLM\SYSTEM\CurrentControlSet\Services\sysmonDrv\Parameters\Rules
正常情况下,蓝队或者管理员通过 -c 参数运行 Sysmon,可以将该二进制形式的配置转换为可读格式并打印,如下图所示:
但从红队角度出发,这是一个不太安全的操作,因为蓝队很可能提前准备了针对该命令执行的检测方案。
红队可以尝试使用注册表相关的 WIN32 API 对配置值项二进制进行转储,例如 RegQueryValueExW,然后将转储后的值项写入红队本地的对应注册表值项中,并通过在本地运行 Sysmon 的 -c 参数得到可读配置内容。
在 2018 年的 Black Hat(黑帽大会)中,Matt Graeber 和 Lee Christensen 分享了针对 Sysmon 的议题,并开源了他们的工作成果,链接如下:
- us-18-Graeber-Subverting-Sysmon-Application-Of-A-Formalized-Security-Product-Evasion-Methodology-wp.pdf
- https://github.com/mattifestation/PSSysmonTools/
其中我们认为非常有意思的部分,是对 Sysmon 二进制配置内容进行逆向的工作,你可以在 PSSysmonTools 项目中找到它,但是它已经停止维护了,对新版本的 Sysmon 配置无效,感兴趣的朋友可以自行学习。
小结
在本文中,我们简单的介绍了 Sysmon,描述了它在实际场景中的应用和十分有效的防御策略,并从红队角度出发,描述了准确的在 Windows 系统中找到 Sysmon 并获取可读配置内容的方法。
在第二部分中,我们还将会介绍 Sysmon 在 Linux 系统中使用的先进技术和优秀表现,并提出在 Linux 下的可靠对抗技巧,敬请期待。