r0ak 是一款 Windows 命令行实用程序,它使您能够轻松地从命令行读取、写入和执行内核模式代码(存在一些限制),除了管理员权限外无需其他任何条件。
r0ak v1.0.0 -- Ring 0 Army Knife
http://www.github.com/ionescu007/r0ak
Copyright (c) 2018 Alex Ionescu [@aionescu]
http://www.windows-internals.com
USAGE: r0ak.exe
[--execute <Address | module.ext!function> <Argument>]
[--write <Address | module.ext!function> <Value>]
[--read <Address | module.ext!function> <Size>]

Windows 内核是一个丰富的环境,典型系统上会有数百个驱动程序执行,且存在数千个包含全局状态的变量。对于高级故障排除,IT 专家通常会使用 Windows 调试器 (WinDbg)、SysInternals 工具或自己编写工具。不幸的是,这些工具的使用变得越来越困难,并且它们自身也受限于其对 Windows API 和公开功能的访问权限。
当今面临的一些挑战包括:
在这样的环境下,一款能够作为应急补丁/热修复使用,并可快速排查内核/系统级别问题(这些问题可能通过分析内核状态得以显现)的简单工具,对于社区而言可能很有价值。

r0ak 通过重定向窗口管理器在尝试加载新字体时的可信字体验证检查的执行流程来工作:它将可信字体表的比较例程替换为一个备用函数,该函数会调度一个存储在输入节点中的执行工作项 (WORK_QUEUE_ITEM)。然后,可信字体表的右子节点(作为根节点)被覆盖为一个命名管道的写缓冲区 (NP_DATA_ENTRY),其中存储了一个自定义工作项。该工作项的基础工作函数及其参数最终将在一个专用的 ExpWorkerThread 中于 PASSIVE_LEVEL 下执行——当尝试加载字体且比较例程执行时,该工作项会收到命名管道备份的父节点作为输入。一个实时的 Windows 事件跟踪 (ETW) 跟踪事件用于接收工作项已完成执行的异步通知,这使得安全地拆除结构、释放内核模式缓冲区以及恢复正常操作成为可能。
使用 --execute 选项时,函数和参数由用户提供。
使用 --write 时,使用一个自定义 gadget 来修改内核内存中任意位置的 32 位值。
使用 --read 时,写 gadget 用于修改系统的 HSTI 缓冲区指针和大小(注意:对于任何将请求 HSTI 数据的其他应用程序而言,这是破坏性行为。由于这是可选的 Windows 行为,且本工具用于紧急调试/实验,因此这种数据丢失被认为是可以接受的)。然后,使用 HSTI 查询 API 将数据复制回工具的用户模式地址空间,并显示十六进制转储。
由于仅使用了内置的、经 Microsoft 签名的 Windows 功能,且所有调用的函数都是 KCFG 位图的一部分,因此没有违反任何安全检查,也不需要调试标志或使用第三方编写不佳的驱动程序。
不是。由于本工具及其底层技术需要 SYSTEM 级别的特权令牌,而该令牌只能由在管理员帐户下运行的用户获得,因此没有绕过任何安全边界来实现效果。该工具的行为和实用性仅因 Windows 上管理员帐户的提权/特权安全上下文而成为可能,这被认为是设计使然。
当然!即使似乎没有违反特权边界,向 Microsoft 报告安全问题也总是很重要的——他们的研究人员和开发人员团队可能会发现新的攻击向量和外部研究人员未曾想到的到达某些代码路径的方式。
因此,在 2014 年 11 月,我们向 Microsoft 安全研究中心 (MSRC) 提交了一份安全案例,其回复如下: “……这不属于我们通过传统安全公告工具解决的安全问题范围。它……预先假定具有管理员权限——在架构上,我们目前不将此处定义为可防御的安全边界。因此,我们不会着手修复此问题。”
此外,在 2015 年 4 月的 Infiltrate 会议上,一场题为《Insection : AWEsomely Exploiting Shared Memory Objects》的演讲详细介绍了这一问题,包括向在场的 Microsoft 开发人员展示,他们同意这目前超出了 Windows 架构安全边界范围。这是因为管理员至少有几十种(如果不是更多)其他方式来读取/写入/执行 Ring 0 内存。本工具只是使其中一种向量易于使用,用于调试和排查系统问题。
将此代码打包成库需要仔细移除所有交互式命令行解析和标准输出,此时,如果没有重大重写,该“工具包”将:
_NT_SYMBOL_PATH 环境变量,并且大约 15MB 的符号数据已作为 PDB 文件下载并缓存到磁盘的某个位置有意使用此特定方法(相比之下存在众多其他更兼容、无需 SYSTEM 权限的技术)的攻击者,很可能早在 3 年多前的 2015 年 4 月,就已经基于概念验证代码改编了自己的代码。
由于使用了 Windows 符号引擎,您必须安装 Windows 软件开发工具包 (SDK) 或 Windows 驱动程序工具包 (WDK),并包含 Windows 调试工具。该工具会自动查找您的安装路径,并利用该目录中的 DbgHelp.dll 和 SymSrv.dll。由于这些文件不可再分发,因此不能包含在本工具的发行版中。
或者,如果您自行获取了这些库,也可以修改源代码以使用它们。
使用符号需要 Internet 连接,除非您已本地预缓存了符号。此外,您应该设置 _NT_SYMBOL_PATH 变量,指向适当的符号服务器和缓存位置。
假设 IT 专家或其他故障排除人员,显然有读取/写入/执行内核内存的需要(并且了解要访问的合适内核变量),已经非常熟悉上述设置要求。请不要提交问题询问 SDK 是什么或如何设置环境变量。
某个驱动程序泄漏了内核池?为什么不调用 ntoskrnl.exe!ExFreePool 并传入正在泄漏的内核地址?对象引用泄漏了?调用 ntoskrnl.exe!ObfDereferenceObject 来清理。
想转储内核 DbgPrint 日志?为什么不转储内部循环缓冲区 ntoskrnl.exe!KdPrintCircularBuffer?
想知道机器上内核栈的大小?尝试查看 ntoskrnl.exe!KeKernelStackSize。
想转储系统调用表查找钩子?打印出 ntoskrnl.exe!KiServiceTable。
这些只是几个例子——所有 Ring 0 地址都被接受,可以使用 module!symbol 语法,或者如果知道内核指针,直接传入。使用 Windows 符号引擎进行查找。
该工具需要某些仅存在于现代 Windows 10 版本中的内核变量和函数,并且仅设计用于 64 位系统。这些限制是因为在较旧的系统(或 x86 系统)上,这些更严格的安全要求不存在,因此可以使用更传统的方法。这是一个我公开的个人工具,我没有对旧系统的需求,在那些系统上我可以改用简单的驱动程序。话虽如此,如果有人感兴趣移植它,本仓库接受拉取请求。
其次,出于使用场景和我的自身需求,存在以下限制:
显然,这些限制可以通过编程选择不同的方法来解决,但它们适合命令行工具的需求和我的使用场景。同样,如果其他人希望贡献自己的添加,接受拉取请求。
请注意,所有执行(包括 --read 和 --write 命令的执行)都发生在系统工作线程的 PASSIVE_LEVEL 上下文中。因此,用户模式地址不应作为参数传递。
欢迎拉取请求。对于重大更改,请先提交一个问题来讨论您想要更改的内容。
Copyright 2018 Alex Ionescu. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY ALEX IONESCU ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALEX IONESCU
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the authors and
should not be interpreted as representing official policies, either expressed or implied, of Alex Ionescu.