什么是 “Flightsigning”
Flightsigning 描述了使用 flight 证书对文件进行数字签名的过程。Microsoft 用于签署 Windows 系统文件的证书有 4 种常见类型:
- PreProd – PCA 2010
- Prod – PCA 2011
- Flight – Development PCA 2014
- Test – 各种各样的东西,最常见的是 MSIT Test CodeSign CA
Flight 只是 Microsoft 使用的一个特定证书/证书系列,当使用 flight 证书签名时,该版本称为 flightsigned 版本。
为什么 “Flightsigned” 版本无法在当前日期启动
用于对早期 flightsigned 版本进行签名的证书明确指定了过期时间,并设计为在系统时间超过过期时间后立即失效。这意味着一旦这些 flight 证书过期,Windows 将把这些证书数字签名的系统文件视为无效文件。
这有点像你不能用打补丁的系统文件正常启动 Windows。不同之处在于,如果签名因二进制文件的修改而无效,则可以使用 NOINTEGRITYCHECKS
BCD 选项强制引导加载程序继续引导,但如果证书过期,引导加载程序将停止加载。
这意味着系统时间不得超过这些 flight 证书的到期时间,因此不能在当前日期启动 flightsigned 版本。
我为什么要写这个指南
在过去的 15 年里,我一直在玩基于 DOS 和基于“经典” NT 的 Windows 的 Beta。一周前,我突然决定玩“现代”版本的 Windows,因为我对它们一无所知。我相信从 Windows 10 测试版开始是一个很好的开始。
我选择了 Windows 10 的第一个正式预发布版本(build 9841)- 真是个错误!我认为这可能是最容易解除时间炸弹的版本,而我忽略了一个事实,即甚至没有人谈论解除它的时间炸弹。然后我读到只有 fbl_partner_eeap 版本的时间炸弹可以被删除,因为它们包含“非功能的时间炸弹,因此可以在当前日期安装”。好吧,我想挑战一下这个只有 fbl_partner_eeap 版本可以解除时间炸弹的事实,所以我选择继续尝试 9841(fbl_release flightsigned 版本)。
毫无疑问,我高估了自己的能力,意识到解除 flightsigned 版本的时间炸弹就像经历了 9 个地狱圈。嗯,你看既然我在说如何解除它的时间炸弹,很明显,我最终成功了。这是一场漫长而艰难的战斗,我花了将近一周的时间才完全击败 flightsigning。
最初,我修补了内核以启用 NOINTEGRITYCHECKS
,然后将所有系统文件的所有数字签名中的所有证书替换为来自 build 9838 的非 flight 证书。是的,它成功了,但目录文件也用 flight 证书进行了数字签名。然后我去把所有的目录都换成了 9838 版本的目录——它不起作用。那么,ci.dll
的补丁似乎是唯一的出路。
因此,最后我修补了 ci.dll
,然后 Windows Loader
(winload.exe
/winload.efi
)以加载修补后的 ci.dll
,最后 Boot Manager 以加载修补后的 Windows Loader。这听起来很容易,但实际上要难得多… 其实没那么难,只是很乏味。我修补了20个文件,只是为了安全地让 Windows 10 build 9841 的 x86 版本在当前日期启动,而替换 boot.wim
、install.wim
和 winre.wim
的所有索引中出现的所有文件花费了更多的时间。由于这个过程非常繁琐,我不打算修补每个 flightsigned 版本的每个架构,所以我只想发布一个指南,希望它能适用于所有架构中的所有 flightsigned 版本。
观众
本指南仅供有经验的读者阅读。要理解这些过程并亲自执行修补,您必须充分了解现代版本 Microsoft Windows 的引导过程。您还应该能够理解 C/C++ 和所需架构的汇编语言。
如果您自己没有能力执行修补,我可以为您修补它们,前提是您在下面的评论部分上传所需的文件(因为我是一个大好人)。目前我只能修补 UEFI Boot Manager 和 Windows Loader,因为旧版 BIOS 的修补非常耗时。您必须上传 ci.dll
、winload.efi
、winresume.efi
、bootmgr.efi
和 bootmgfw.efi
。不要忘记,补丁只负责禁用证书到期检查,您仍然需要按照这个指南来解除时间炸弹。
如果您希望自己修补这些文件,请继续阅读以下部分。
修补 Windows 以在当前日期启动
由于存在不同的架构,即使对于相同的架构,补丁也可能不同(不同的偏移量、不同的寄存器),因此我将主要使用 C/C++ 伪代码演示补丁。
ci.dll
要修补的第一个文件是 ci.dll
,它是负责签名验证的代码完整性库。我们不会完全删除签名验证,我们只是让它忽略过期的证书。
有一个名为 STATUS_IMAGE_CERT_EXPIRED
的状态,我们不希望 return 该状态。因此,我们需要修补可能 return STATUS_IMAGE_CERT_EXPIRED
的函数。由于不同的版本具有不同数量能够 return STATUS_IMAGE_CERT_EXPIRED
的函数,并且这些函数可能都不同,因此您应该在 ci.dll
中搜索 0x0C0000605
。当您发现类似 mov ???, 0C0000605h
的内容时,请检查是什么原因导致 0C0000605h
移动到 ???
寄存器,您会发现这样的 if
语句:
if ( condition )
{
// certificate expired
result = STATUS_IMAGE_CERT_EXPIRED;
}
// certificate not expired
我们需要删除 if
语句,最好是将条件跳转修补为无条件跳转,或者 NOP
掉条件跳转(取决于具体情况)。确保找到所有的 mov ???, 0C0000605h
并对其进行修补。
由于我们修改了系统文件,所以为了安全起见,还应该对 CipReportAndReprieveUMCIFailure
进行修补。在这里,我们需要让 (g_CiDeveloperMode & 1) != 0
的 if
语句中的代码执行,无论 g_CiDeveloperMode
的值如何。
if ( (g_CiDeveloperMode & 1) != 0 )
{
// code here
EventDescriptor = (const EVENT_DESCRIPTOR *)CiPolicyFailureIgnored;
*(BYTE *)a10 = 1;
// code here
}
您应该在 TEST
指令之后找到一个条件跳转。同样,根据具体情况,你需要要么将条件跳转修补为无条件跳转,或者直接 NOP
掉它。
没有符号的额外步骤
对于 g_CiDeveloperMode
的修补,您需要首先识别 CipReportAndReprieveUMCIFailure
函数。要识别该函数,请搜索 ASCII 字符串 “This break indicates this binary is not signed correctly
”,然后跳转到引用。向上滚动,直到找到对 PsGetProcessProtection
的调用,并在上面不远处看到一个 TEST
指令(test something, 10h
)。一旦你找到了,你应该看到另一个 TEST
指令(test something, 1
)在这条指令之上,而这个 TEST
指令就是 (g_CiDeveloperMode & 1) != 0
的 if
语句。现在,您可以像使用调试符号一样,在它的正下方修补条件跳转。
winload.efi/winload.exe, winresume.efi/winresume.exe
由于我们修补了 ci.dll
,因此必须修补 Windows Loader 以加载修补的 ci.dll
。有两个东西需要修补 – 签名有效性检查(导致蓝屏显示 Windows 无法加载 xxx 的原因)和引导选项检查(防止自动修复屏幕)。
对于签名有效性检查,我们需要删除对 ImgpValidateImageHash
函数 return 值的检查。您也可以将 ImgpValidateImageHash
本身修补为 return 零,但我建议您修补 return 值检查(将复杂函数修补为仅 return 0 可能会导致不希望的效果)。首先找到 ImgpValidateImageHash
函数,跳转到引用,您应该看到 return 值被移动到另一个寄存器,然后是一个 TEST
指令。您应该修补 TEST
指令下的条件跳转,如果其跳转到 if
语句之外,则修改为无条件跳转,以避免 if
语句内的代码被执行。如果它跳转到 if
语句之内,那么您应该 NOP
掉条件跳转。代码可能是这样子的:
result = ImgpValidateImageHash(something);
if ( result < 0 )
{
result = ImgpFilterValidationFailure(something);
if ( result < 0 )
{
if ( (something & 0x20) != 0 )
goto Label;
result = 0;
}
}
然后,您应该修补 BlImgQueryCodeIntegrityBootOptions
,告诉 Windows Loader 忽略“已损坏”的文件,以避免每次启动 Windows 时出现“准备自动修复”屏幕。您只需要将第二个参数(IntegrityChecksDisabled
,一个 PBOOLEAN
)设置为 TRUE
。
没有符号的额外步骤
要找到 ImgpValidateImageHash
函数,请搜索 ASCII 字符串 “1.3.6.1.4.1.311.61.4.1
”,然后跳转到引用。要找到 BlImgQueryCodeIntegrityBootOptions
函数,请搜索 0x16000048
直到在其下方不远处看到 0x16000049
,然后继续搜索 0x16000048
直到再次在其下方看到 0x16000049
。
bootmgr/bootmgr.efi, memtest.exe/memtest.efi, cdboot.efi
Boot Manager 也必须进行修补,才能加载修补的 Windows Loader。该修补过程与 Windows Loader 修补过程相同,只是不需要修补 BlImgQueryCodeIntegrityBootOptions
。最困难的部分是修改压缩的 bootmgr
文件以用于传统 BIOS 引导。如果您使用的是 UEFI,那么在修补完这些 Boot Manager .EFI
文件后,您就完成了所有操作。
要修补压缩的 bootmgr
文件,首先需要了解其结构。它可以分为 4 个部分 —— 一个原始的 16 位 stub 加载器,一个包含压缩部分信息的自定义结构,一个 stub PE 文件,最后是压缩的 Boot Manager。
第一步是解压缩它或找到一个未压缩的副本。您应该能够在 boot.wim
(WinPE)中找到一个名为 bootmgr.exe
的文件,该文件与 bootmgr
中的 Boot Manager 文件相同,只是没有被压缩。然后,您需要按照上面的 Boot Manager 修补方法进行修补。最后,您必须压缩经过修补的可执行文件并将其添加回 bootmgr
。对于压缩,您可以使用 joakim 的 BOOTMGR 重新编译程序 v2。它输出一个带有硬编码 16 位 stub 的组合 bootmgr
,因此我强烈建议您从输出文件中提取压缩部分,并用它替换原始 bootmgr
文件的压缩部分。当然,您还必须修改 16 位 stub 下面的自定义结构和 PE stub 的 PE 校验和。jaokim 记录了自定义结构,因此请参见 BOOTMGR 重新编译程序 v2 项目页面。PE 校验和更正有点困难,所以我反编译了一些 bootmgr
签名检查函数并将其组合成了一个程序。只需运行它来显示正确的校验和,然后将 PE stub 的 PE 校验和更改为正确的校验和。
解除时间炸弹
令人惊讶的是…也许不是,上面的长篇大论甚至与解除时间炸弹无关。如果您正确地修补了所有文件,您现在应该能够在当前日期启动 Windows,但定时炸弹仍然存在。与 Windows 10 的其他预发布版本一样,flightsigned 版本也可以按照这个 BetaArchive 的指南进行拆解。那个指南有点混乱,所以当我有时间的时候,我会为 BetaWorld 写一个更好的指南。
一些解除时间炸弹的版本和修补后的文件
- 9841 x86 (UEFI & BIOS)
- 9926 x64 (UEFI)
- 14357.1000 (UEFI)
- 9879 x64 (UEFI)
- (Betajyst4094 或 Mintel)解除时间炸弹的 ISO: https://drive.google.com/file/d/1C0Abnp6iah77Yh_5YbAbclDzepufgXBB/view?usp=sharing
- 9841 x64 (UEFI)
- (Betajyst4094 或 Mintel)解除时间炸弹的 ISO: https://drive.google.com/file/d/17P2zHsRHKCXTehmrTi5CLHBalecCQIOL/view?usp=sharing
- 9860 x64 (UEFI)
- (Betajyst4094 或 Mintel)解除时间炸弹的 ISO: https://drive.google.com/file/d/1d9hM94oSQwMC7obvnVW-6gl9YNztjsfr/view?usp=sharing
- 9888 x64 (UEFI & BIOS)
- (Betajyst4094 或 Mintel)解除时间炸弹的 ISO: https://mega.nz/file/fUwUxQiR#0qjyARvo-3k73x2Irh2Wn2f4gbeollxYtmVOEUWgCqc
感谢我同事的翻译,他友好而礼貌的留言:”thank you so much lucas for giving me this f___ing piece of s__t to translate, after translating this s__t I know more about f___ing win 10 than anyone on the f___ing net m_____f___er“
编辑:感谢 Zammis Clark 提出文中错误,现已修正。同时他还指出,“最好”的方法可能是fork EfiGuard 项目并用于修改 ci.dll
中的签名检查部分,这样就不需要使用拐弯抹角的方法处理文件。
下页是英文原文 :