威胁者可以利用本机 Windows API 调用来安装恶意服务,而无需在事件日志中生成相关条目。使用本机 API 而不是标准 API 调用来安装服务允许威胁者绕过安全控制和事件日志记录。这种技术被用于臭名昭著的 Stuxnet 恶意软件样本,据称该样本由美国和以色列政府创建,旨在针对伊朗核计划。它也恰好是我最喜欢的恶意软件样本之一 <3。我不会介绍什么是本机 API 调用 - 有关更多信息,请阅读我之前的一条推文。
这种技术并不新鲜(因为 Stuxnet 曾使用过),然而,业内许多分析师将事件日志视为单一事实来源,却没有意识到有时情况并非总是如此。因此,响应者/猎人/检测工程师始终明智的做法是将每个人工制品的各种证据流关联起来,而不是依赖单一证据来源。@HarlanCarvey 将此称为“人工制品星座”,我认为这是一个非常精彩的短语,完美地描述了这种情况。
在这篇博文中,我将重点介绍如何通过本机 API 调用安装服务以逃避检测,然后重点介绍通过内存取证的检测机制。如果不介绍一些流程内部信息,就很难谈论这个话题,因此本博文的结构涵盖了以下内容:
-
该技术的工作原理以及如何绕过事件日志记录
-
为什么波动性插件“svcscan”无法检测到通过此方法安装的服务
-
检测方法
第一部分:该技术的工作原理
如果不使用“规避”技术,服务通常是通过标准 Windows API 调用“CreateServiceA”或“CreateService”创建的——您可以在此处阅读此 API 的完整文档。每当您使用本机 Windows 可执行文件“sc.exe”在计算机上注册服务时,也会调用此 API。随后,对此 API 的调用会在事件日志中生成条目,这些条目对应于响应者将习惯于查看的服务创建事件 ID。
威胁行为者可以通过直接与 Windows 本机 API 调用交互来创建服务,而无需依赖于典型的“CreateServiceA”API 调用。例如,“StartService”API 将调用本机 API“NdrClientCall2”并在事件日志中注册服务启动事件。但是,通过直接调用“NdrClientCall2”来启动已手动创建注册表项的服务 - 服务已启动并运行,但未创建相关事件日志 - 从而逃避检测。这将导致恶意服务运行,但未创建相关事件日志条目。更进一步说,威胁行为者可以删除注册表中的证据以及“services.exe”内存中加载的任何相关证据。这样一来,您就几乎没有注册表痕迹,也没有事件日志信息可供分析。
Stuxnet 利用此技术注册了两个恶意服务,通过调用本机 API“NtLoadDriver”来运行恶意内核驱动程序。但是,恶意软件并未删除注册表中隐藏的工件(因为调用 NtLoadDriver 需要这些注册表值)。此 API 记录在NTAPI 未记录函数网站中,例如。要调用 API,只需传递一个值 - 驱动程序名称,并确保注册表已设置恶意驱动程序的路径。
通常,当获得内存样本时,分析师会运行 Volatility 中的“svcscan”插件来寻找服务。当面对 Stuxnet 时,您会注意到这不会返回显示恶意服务的结果。Stuxnet 中存在的两个恶意服务称为“mrxnet”和“mrxcls”。运行“svcscan”模块您也看不到这些服务存在的证据。
但是,参考 NtLoadDriver 文档,其中需要设置注册表值。遍历内存样本中的注册表项显示这些服务确实存在。那么为什么会这样呢?为什么 svcscan 插件没有检测到这个服务?
这是一个需要反思的重要地方,因为分析师必须了解他们使用的工具如何“工作”。依赖运行插件而不了解其工作原理可能会限制分析师找出替代搜索方法的能力。
第 2 部分:为什么“SVCSCAN”无法检测到这一点?
这两种方法无法检测到恶意的 Stuxnet 服务,因为通过直接调用本机 API 而不是标准 API,服务控制管理器 (SCM) 被绕过,这意味着内存中没有创建服务记录。让我们逐一介绍这两种方法以及它们失败的原因……
方法 1:遍历 VAD 树,查找“services.exe”中可能显示恶意正在运行的服务的内存部分。
插件“svcscan”会遍历 VAD 树。VAD 是虚拟地址描述符,用于以分层树结构存储进程使用的内存范围。由于 Stuxnet 直接与 NTLoadDriver 交互,services.exe 的进程内存中没有相关的“数据”,因此遍历 VAD 树不会返回有关这两个恶意服务的任何信息。
有关 Windows 内部结构、取消链接、PEB、EPROCESS 和其他结构的更多背景信息,请查看我之前发的这条推文。
方法二:在内存样本中查找带有“sErv”和“serH”标签的服务记录
此技术遍历整个内存样本,寻找任何带有可能已从服务控制管理器 (SCM) 双向链接列表中断开链接的标签的服务记录。此方法失败,因为在调用 NtLoadDriver 时没有创建相关的服务记录 _SERVICE_RECORD 结构。
这就是为什么查找“sErv”和“serH”标签无法检测到服务的原因,因为从未创建过记录。服务控制管理器 (SCM) 将有关安装在机器上的服务的信息存储在链接列表或双向链接列表中。下面的屏幕截图显示了此结构在双向链接列表(旧版本的 Windows)中的组织,即 0x0 处的“ServiceList”。
第 3 部分:检测方法
在寻找恶意服务创建时,我会从头到尾遵循这个逻辑。始终寻找相关证据来强化发现,而不是仅根据一个工件的结果来解决问题。
对于大多数恶意软件/不太复杂的威胁行为者来说,IR 的一般工作流程如下。在 Stuxnet 的例子中,这些检测技术可能没有提供任何发现,也没有足够的信息来确定恶意驱动程序和服务。
1. 查看 7045、7035、7034、7036、7040、4697 服务创建的事件日志
2. 检查服务的注册表项:
-
HKLMSYSTEMCurrentControlSetServices
-
HKLMSYSTEMControlSet001Services
-
HKLMSYSTEMControlSet002Services
3. 检查命令行日志,查找使用“sc.exe”、“at.exe”创建的服务的迹象
4. 审查执行的工件,例如 Shimcache、Prefetch、Amcach
5. 检查 $MFT/$I30 是否存在恶意文件创建的迹象(即删除的 .DLL、.EXE 等)
6. 使用 Volatility“svcscan”来获取未链接服务的迹象并查找正在运行的服务
在 Stuxnet 实例中……由于 NTLoadDriver 被 Stuxnet 调用来注册恶意驱动程序服务,因此还需要采取以下操作来形成更完整的检测。
7. 检测磁盘上的恶意驱动程序(也可以通过关联磁盘上的创建时间戳来完成,而无需内存取证)
8. 将恶意驱动程序文件与已加载的内核模块关联起来,以证明该服务正在系统上运行。这意味着这些驱动程序正在运行。
9. 检测对 NTLoadDriver 和 NdrClientCall2 的本机 API 调用以及对允许直接写入注册表项的函数的其他 API 调用。通常,EDR 工具会监视并警告对 StartService 和 CreateServiceA 的调用 - 但正如本文所演示的那样……这种方法会绕过该检测。
对于检测工程师,我会考虑寻找对 NTLoadDriver 和 NdrClientCall2 的调用以及对 StartService、RegCreateKey、RegSetValue 的其他 API 调用以及写入上面列出的注册表项的相关证据。
最后,如果你有兴趣阅读有关分析 Stuxnet 的完整文章,我强烈推荐 MNIN 的这篇文章。这个样本中蕴含了许多微妙的技术。
参考
-
https://docs.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-createservicea
-
https://undocumented.ntinternals.net/
-
http://mnin.blogspot.com/2011/06/examining-stuxnets-footprint-in-memory.html
原文始发于微信公众号(Ots安全):通过本机 API 逃避 Windows 事件日志
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论