真正理解SimpleSvmHook,要从它处理的任务开始:SimpleSvmHook 是用于 AMD 处理器上的 Windows 的研究目的虚拟机管理程序。从日常自动化的使用方式看,输入边界、依赖和失败处理如果不清楚就很难稳定复用是采用前必须回答的问题。我的评估方法是用一项范围明确的真实任务完成最小试跑,然后检查配置时间、输出质量、异常信息和维护痕迹是否与文档一致。对愿意先做小范围验证并复查原始文档的团队来说,这个仓库值得继续验证;只求即装即用的人则要先看维护成本。
SimpleSvmHook
简介
SimpleSvmHook 是用于 AMD 处理器上的 Windows 的研究目的虚拟机管理程序。 它挂钩内核模式函数并保护它们不被检测到 嵌套页表 (NPT),AMD 虚拟化 (AMD-V) 技术的一部分。
该项目旨在作为虚拟机的示例实现 对 AMD 处理器进行自省 (VMI),并突出显示与类似处理器的差异 Intel 处理器上的 VMI 实现。
如果您已经了解 DdiMon,这是 从功能角度来看,它是 AMD 的对应物,除了一些事情之外 如下所述。
Stealth Hook 实施概述 隐形钩是一种从外部看不到的钩。 监视器或检查器组件。在VMI的上下文中,安装了隐形钩子 并由虚拟机管理程序管理到来宾代码中以重定向指定的执行 地址同时不易被客人察觉。
在虚拟机管理程序中实现隐形钩子的常见方法之一是拆分 “查看”read/write 的内存并使用 Second 执行来宾的访问 级别地址转换(SLAT),即Intel上的扩展页表(EPT) 和 AMD 处理器的嵌套页表 (NPT)。
SLAT 又引入了一个地址转换步骤,即从 来宾物理地址(GPA)到系统物理地址(SPA)。这个 本质上允许虚拟机管理程序在 来宾和后备物理内存地址。下图说明了如何 可以配置 SLAT 并且将导致地址转换。
GPA SPA Memory Contents
-----------------------------------------
0x1000 –(SLAT)-> 0xa000 ...
0x2000 –(SLAT)-> 0xb000 48 89 54 24 10
...
SLAT还可以配置GPA对访客的权限;例如, GPA:0x2000可以配置为readable/writable,但不可执行。当 来宾尝试以处理器 SLAT 不允许的方式访问 GPA 触发 VM-exit 以便虚拟机管理程序可以采取必要的操作,例如 更新权限或将 #GP 注入来宾中。
Stealth hook 通常是通过利用这些功能来实现的。取DdiMon 例如,当虚拟机管理程序安装stealth hook时,它会创建一个副本 目标页面,将0xCC设置为要挂钩的地址,然后设置EPT以使 该页面仅执行(以下示例中为 0xb000)。
GPA SPA Memory Contents
--------------------------------------------
0x2000 –(EPT --X)-> 0xb000 CC 89 54 24 10
0xf000 48 89 54 24 10 (The copied page. Unused yet)
...
当来宾尝试执行该地址时,虚拟机管理程序:
当来宾尝试读取或写入该地址时,虚拟机管理程序:
GPA SPA Memory Contents
--------------------------------------------
0x2000 –(EPT RW-) 0xb000 CC 89 54 24 10
->0xf000 48 89 54 24 10(复制的页面)
...
GPA SPA Memory Contents
--------------------------------------------
0x2000 –(EPT --X)-> 0xb000 CC 89 54 24 10
0xf000 48 89 54 24 10 (The copied page)
...
这些操作允许虚拟机管理程序重定向来宾的执行,同时 让客人看不到挂钩。另请注意 EPT 配置 恢复到原来的状态,下次执行或者read/write访问 可以用同样的方法处理。
但是,这不能直接在 AMD 处理器上实现。
AMD 处理器上的实现和限制
前面描述的技术无法在 AMD 处理器上实现,因为 缺少仅执行权限。
NPT,SLAT 的 AMD 实现,不允许管理程序配置 权限为仅执行,因为没有位来指示是否 页面可读。为了使页面可执行,它还必须在以下位置可读: 同一时间。此限制需要对隐藏钩子的方式进行重大更改。
首先,虚拟机管理程序需要将未修改的readable/writable页面设置为 目标页面的默认关联(以下示例中的 0xb000)。
GPA SPA Memory Contents
--------------------------------------------
0x2000 –(NPT RW-)-> 0xb000 48 89 54 24 10
0xf000 CC 89 54 24 10 (The copied page. Unused yet)
...
由于更频繁的 VM-exit(回想一下),这会带来额外的性能成本 被挂钩的地址是代码,更有可能被访问 执行)。
其次,钩子在某些情况下必须保持可见。让我们看看为什么。
当来宾尝试执行该地址时,虚拟机管理程序:
GPA SPA Memory Contents
--------------------------------------------
0x2000 –(NPT RWX) 0xb000 48 89 54 24 10
->0xf000 CC 89 54 24 10(复制的页面)
...
请注意,执行钩子时,被钩住的页面仍然可以通过 0xCC 读取。
这是一个关键问题,但解决起来具有挑战性,因为:
此问题的部分解决方案是在访客尝试时将其困住 执行挂钩页面的外部,然后隐藏0xCC。这可以是 通过设置除挂钩页面之外的所有页面不可执行来实现,然后,当 guest跳到被hook的页面外面,hypervisor:
GPA SPA Memory Contents
--------------------------------------------
0x2000 –(NPT RW-)-> 0xb000 48 89 54 24 10
0xf000 CC 89 54 24 10 (The copied page)
...
这样,当来宾执行任何代码时,挂钩保持不可见 在挂钩页面之外。换句话说,客人仍然可以看到钩子 当它正在执行与挂钩页面相同的页面时。这可能是一个 如果钩子必须安装在可能执行的代码上,则存在重大限制 自我完整性检查,但如果安装了钩子,这不太可能是一个真正的问题 针对已知的内核代码,例如 NTOSKRNL 和 Win32k。
这种设计的另一个缺点是 NTP 操作的开销。 VM-退出,当 访客从被钩住的页面跳进跳出,有着不可忽视的影响 性能损失,因为管理程序必须更新多个 NPT 条目 更改所有页面的可执行权限。
通过 Windows 性能分析器测量的 Windows 启动时间延迟 HP EliteBook 725 G4 当前的实施率为 20% (AMD A12 PRO-8830B),而 上的 DdiMon 仅为 9% Dell Latitude E6410 (英特尔酷睿 i7-620M)。鉴于所测试的AMD处理器已经快7年了 比测试的英特尔处理器更新的型号,预计会有更多 AMD-V 的优化实现比旧 Intel 处理器上的 VT-x 的优化实现, 这个高数字 (20%) 可能是由于重量级 VM-exit 处理所致。
虽然这种开销在正常负载下似乎并不明显,但它可能是 真正的问题取决于负载,也可能取决于安装的挂钩数量。
结论
该项目演示了在 AMD 处理器上实现隐形钩子 是可能的,但需要注意的是,钩子必须从代码中保持可见 同一页面,并且所解释的设计引入的性能开销是 明显高于英特尔处理器上的类似实现。
在某些用例中可以忽略这些限制,例如仪器仪表 已知内核 API 用于研究,但可能会阻止研究人员开发 高度隐秘的 VMI 工具和适用于性能敏感环境的工具。
安装与卸载
要从源代码构建 SimpleSvmHook,请使用以下命令从 GitHub 克隆完整源代码 以下命令并在受支持的 Visual Studio 版本上编译它。
$ git clone https://github.com/tandasat/SimpleSvmHook.git
在安装驱动程序之前,您必须启用测试签名才能安装驱动程序。至 为此,请使用管理员权限打开命令提示符并运行 以下命令,然后重新启动系统以激活更改:
>bcdedit /设置测试签名
要安装和卸载 SimpleSvmHook 驱动程序,请使用 sc 命令。对于
安装并启动:
>sc 创建 SimpleSvmHook 类型 = 内核 binPath= C:UsersuserDesktopSimpleSvmHook.sys
>sc 启动 SimpleSvmHook
请注意,驱动程序可能会因反汇编代码失败而无法启动 挂钩。 SimpleSvmHook 只能处理已知的字节模式(指令)并且 不尝试分解未知的字节模式。您可以解决这样的问题 通过向“FindFirstInstruction”函数添加新模式而出现错误,并且 重新编译驱动程序。
对于卸载:
>SC停止 SimpleSvmHook
>sc 删除 SimpleSvmHook
>bcdedit /删除值测试签名
输出
所有调试输出都保存在 C:WindowsSimpleSvmHook.log 中。
此屏幕截图显示了已安装挂钩的示例输出以及那些 钩子对于系统(本地内核调试器)是不可见的。
支持的平台
请注意,VMware 中的 NTP 仿真速度明显慢。尝试一下
SimpleSvmHook 在VMware上,将SIMPLESVMHOOK_SINGLE_HOOK设置为1并重新编译
司机。
资源
SimpleSvm
DdiMon