mandiant/STrace
GitHub: mandiant/STrace
一款 Mandiant 开发的 Windows DTrace 重新实现,通过 DLL 插件机制实现高性能的系统调用追踪和 ETW 事件监控。
Stars: 374 | Forks: 52
# STrace
Steve 的 Tracer。这是一个基于 Windows 系统调用 Hook 的 DTrace 重新实现。可以把它看作是一个兼容 Patchguard 的 SSDT Hook,但不需要使用 Hack 手段。这不支持 SSSDT (win32k apis),因为 DTrace 系统调用 API 本身不支持这个额外的表。除了所有用户模式 SSDT 系统调用外,Zw* 内核 API 也可以被追踪。
如果你正在为 STrace 开发新插件,请务必阅读本自述文件的结尾部分!
# 功能
Windows 上的 DTrace 支持多种探针类型。这包括 syscall、fbt、etw、profile 以及可能更多类型。此重新实现**仅重新实现了 syscall 和 etw 探针类型**。所有其他探针类型被认为完全超出了本项目的范围,并且**永远不会被支持**。如果你希望添加额外的探针类型,请随意 Fork 本项目。由于其他探针类型的复杂性及其涉及的系统,范围被限制为仅包括 syscall 和 etw 探针。
此重新实现完全摒弃了 D 脚本语言(注意:不是更流行的现代语言 DLang)。像原始 DTrace 实现那样在内核中运行 VM 的复杂性不适合本项目。相反,此实现直接暴露了接入 DTrace Windows 内核接口所需的相关 C 回调。为了启用脚本的“热加载”,使用了一个基于 DLL 的插件系统来替代原始 dtrace 的 VM + 脚本环境。该插件系统接受一个“普通”的用户模式 DLL(未启用任何安全检查或其他外部依赖项),并将其手动映射到内核地址空间。`plugin dll` 具有在内核系统调用回调发生时被调用的导出函数。内核 API 通过 DLL 的正常导入表 (IAT) 进行解析,插件 DLL 链接到 `ntoskrnl.lib`,然后驱动程序将在加载时解析这些 API,从而允许在插件 DLL 中像往常一样调用任何系统 API。此插件系统的性能非常出色,因为在系统调用 ENTRY 和 RETURN 之间直接执行的是原生代码,而不是脚本解释器或 JIT。与 Microsoft 提供的 dtrace 实现相比,此设计提高了性能。
设置 Hook 非常简单,你会获得一个通过 API 名称注册/取消注册 Hook 的例程,带有系统调用前后的回调。回调中的参数和返回值作为只读值访问。返回值可以在返回探针中被伪造,参数可以在入口探针中被修改,但原始系统调用通常不能替换或“取消”系统调用——此 API 充当观察者。然而,存在一个类似于 ( 和 ) 中记录的疏忽,该疏忽允许在堆栈上替换系统调用指针。利用这个疏忽,可以将系统调用完全替换为指向你控制的例程的指针。当事件发生且你的 Hook 回调触发时,可以做任何你想做的事情。回调是同步的,这意味着如果你在入口回调中延迟执行(例如通过一个 while 循环),那么系统调用将被延迟相应的时间。系统调用的执行发生在从入口回调返回之后,以及在进入返回回调之前。该系统完全兼容 Patchguard,但是必须禁用 DSE,因为不幸的是 Microsoft 认为这种类型的内核扩展是 NT 内核的一部分,因此会验证根签名者是否为 Windows。这_不适用于_像启用自定义内核签名者这样的技巧,在内核启动期间 DSE 真的必须关闭。
```
ValidationFlags=IMGP_LATEST_MS_ROOT_REQUIRED | IMGP_WINDOWS_ROOT_REQUIRED | IMGP_MS_SIGNATURE_REQUIRED
Scenario=ImgSigningScenarioWindows
```
Rust 驱动程序摒弃了 C++ 驱动程序使用的基于 DLL 的插件系统,并尝试使用 Web Assembly 解释器在 Windows 内核中托管 wasm 脚本。这更像使用 VM 的原始 dtrace 实现,但使用了一种比 DLang 更好的语言。这提供了沙盒和其他不错的好处。POC 已完成且可以工作,但不幸的是由于使用 WASMI 解释 WASM 的性能问题而无法使用。需要一个与 NT 内核兼容的基于 JIT 的 wasm 引擎才能使这种替代设计可行。它作为一个有趣的新奇事物包含在内,可能通过一些工作可用于其他用途。
# 项目组织
该项目主要分为 C++ 和 Rust 组件。C 驱动程序功能完备,应优先使用。在高层级上,项目具有以下组件
* C++ 驱动程序 w/ 基于 DLL 的插件
* Rust 驱动程序 w/ 基于 wasm 脚本的插件
* 用于监控文件删除的 C++ DLL 插件
* 用于记录所有系统调用和参数的 C++ DLL 插件
* 用于测试 NT 内核中 wasm POC 的 Rust Wasm 脚本插件
* 用于在用户模式下模拟执行 wasm 插件的 Rust Wasm 脚本测试器
* 用于符号化 C++ 驱动程序堆栈跟踪的 Rust 日志符号化器。不使用 DIA SDK。
# 安装与设置
设置 Visual Studio w/ DDK
* 安装 VS2022 + Windows SDK + Windows DDK。按此顺序,且 SDK 和 WDK 内部版本号需匹配。参见
* 将 STrace 驱动程序项目的 Windows SDK 设置更改为已安装的 WDK 版本。STrace->Properties->General->Windows SDK Version(你的 WDK 内部版本号)。
构建驱动程序和 cli,将文件移动到与脚本相同的文件夹中,然后以管理员身份运行 install 文件夹中的 powershell 脚本:
```
./install_as_admin.ps1
```
重启,然后选择 STrace 启动条目,并在此屏幕上按 F8(不是回车!):
这将调出此屏幕,选择禁用 DSE 启动:
成功启动后,可以使用 CLI 加载和卸载插件 DLL 以开始追踪。提供了两个示例插件。如果遇到问题,请详细阅读下面的详细信息。第一次可能需要再次重启,并且可能需要使用诸如 process hacker 之类的工具手动将 `STrace` 服务设置为`启动时`自动启动。
## 安装详情
原始 DTrace 安装位于此处: 。原始 DTrace 需要 configured Secure Boot 和 Virtualized Based Security,STrace 情况并非如此,因为它不实现需要这些功能的探针类型 (FBT)。
此项目执行与安装程序相同的操作,但通过简单的 powershell 脚本而不是 MSI。过程很简单。首先将 apiset dll 复制到 system32,以便激活内核扩展。然后安装驱动程序条目,以便在系统启动时执行驱动程序主函数以进行用户模式通信。ApiSet dll 是数字签名的,因此使用了原始的 microsoft apiset,这是必需的。此文件仅以二进制形式提供,除了将扩展导入指向实现驱动程序外,不包含任何逻辑:ext-ms-win-ntos-trace-l1-1-0 -> dtrace.sys。有关此机制的详细信息,请参见 (ApiSetSchemaExtensions)。
STrace 在内核初始化期间非常早地加载,在启动配置数据库 (BCD) 中启用 Test Signing 是_不够的_。必须禁用驱动程序签名强制 (DSE) STrace 才能成功加载,并且每次启动都必须手动完成。为了便于这一点,安装脚本创建了一个易于使用的启动菜单条目供用户选择。没有 BCD 标志允许在重启后永久禁用 DSE,内核明确禁止这样做。
忘记在启动时禁用 DSE 将导致你在重启后进入自动修复菜单。你可以无害地重试,如果启动继续失败,则需要从 drivers 文件夹中手动删除 STrace 驱动程序。请注意,**启动失败可能会导致 Windows 禁用 STrace 服务的自动运行标志***,如果在任何时候发生启动失败,你可能需要将其重新设置为自动运行。
# 插件
要开发自己的插件,最好使用现有插件之一作为基础项目。Visual Studio 项目设置了许多非常具体的设置,以生成无依赖项的独立二进制文件。非默认设置太多,无法一一列出,因此只需复制其中一个项目,并修改代码以添加你自己的逻辑 ( )。**如果你创建了一个有用的插件,请提交 PR**!制作的插件越多,这个系统对每个人就越有用!
标签:AI工具, C/C++, Conpot, DLL注入, DTrace, ETW, PatchGuard兼容, SSDT Hook, Syscall追踪, Windows内核, Windows安全, 事务性I/O, 云资产清单, 内核驱动开发, 可视化界面, 子域名生成, 流量审计, 白帽子, 系统调用钩子, 行为监控, 进程行为分析, 逆向工程