PatchGuard 是 Windows 内核中的防御机制,用于检查内核中关键的数据结构和代码是否被恶意软件或驱动程序篡改。如果发现异常,PatchGuard 会直接以错误码CRITICAL_STRUCTURE_CORRUPTION或者KERNEL_SECURITY_CHECK_FAILURE触发蓝屏。在对 Windows 内核进行安全研究时,如果需要对内核中的关键函数进行挂钩,就必须先关闭 PatchGuard,否则测试过程会受到影响。
目前,最为成熟的关闭 PatchGuard 的方法是使用EfiGuard。EfiGuard 是一个 EFI 固件,可以在系统启动时提前劫持 Windows Boot Manager,进而实现对 Windows 内核的动态修补,阻止 PatchGuard 初始化的相关代码执行。EfiGuard 有多种使用方法,以下进行详细说明。
接下来,需要确保当前机器的 BIOS 中设置为通过 UEFI 启动,并且识别到了 Windows Boot Manager 启动项。通常情况下,全新安装的 Windows 系统都满足这一要求。然而,笔者在实验中也发现,一些笔记本预装的 Windows 系统的启动项中并不包含 Windows Boot Manager,而是只有 NVMe0 这样的磁盘。Windows 系统虽然可以启动,但是这时直接加载 EfiGuard 可能会导致启动失败。
不存在 Windows Boot Manager
这时,需要手动修复启动项。比较简单的解决方案是使用 Dism++ 等工具修复引导。打开 Dism++,点击「恢复功能」中的「引导修复」,即可重新添加 Windows Boot Manager 启动项。完成后,可以重新启动,判断 BIOS 是否识别到了 Windows Boot Manager。
部署 EfiGuard
通过普通 U 盘启动
最简单的方法就是参考 EfiGuard 的文档,在 U 盘上创建/EFI/Boot/目录,然后将bootx64.efi和EfiGuardDxe.efi两个文件复制到该目录中。完成后,将 U 盘插入待测试的电脑,然后选择通过 U 盘启动即可。如果一切正常,EfiGuard 会在启动时自动加载,并输出大量的日志(特征为绿色文字)。
将结果列出,如上表所示。Rejewski 发现,表中的字母存在一些 “链”,例如,上一行的字母 A 对应下一行的字母 E,上一行的字母 E 对应下一行的字母 N,以此类推,最后又回到字母 A。这样就产生了字母链 AENHI。同时,也可以找到其它的字母链:BLSJP,C,DOFWVG,K,MZURTY,Q,X。如果机器的初始状态相同,那么得到的字母链自然也是相同的。更重要的是,Rejewski 发现,插线板的存在只会改变字母链中的字母,但不会影响各个字母链的长度。 例如,在上面的场景中,额外将 A 和 C 之间加入一条接线,那么,原先的 AENHI 链会变为 CENHI,C 链会变为 A 链;但两条链的长度是不变的。因此,字母链的长度特征是插线板作用下的不变量,它只和转子的初始位置有关,由此可以将插线板的作用和转子的初始位置解耦合。波兰的破译团队用了一年的时间进行预计算,得到了所有转子初始位置与字母链的长度的对应关系。此后,在收到新的密文后,破译者可以查表,将字母链的长度与预计算的结果进行比较,得到可能的转子的初始位置。在成功恢复出转子初始位置后,破译者可以对密文进行解密,之后进一步地分析插线板的状态。具体的算法原理如下。