最近从 Windows 10 迁移到了 Windows Server 2022,不过我在设置指纹解锁时发现添加按钮是灰色的,并且系统显示了错误提示 “Windows Hello 在 Windows Server 上不可用”。
在 Google 上找了一圈并没有找到一个可行的方案,这篇 Windows Server 2019 的博客 给出的工具在 2022 中可以加上 PIN,但加上 PIN 后添加指纹的按钮依然是提示不可用的。看来得自己研究一下了。
初步分析
根据前面提到那篇博客给出的思路,我大致翻了一下 SettingsHandlers_User.dll,但是并没有找到和指纹解锁 / Windows Hello 有关的东西,猜测 Microsoft 对这块设置进行了重构。
我并不想去研究整个 UWP APP 的逻辑,于是打开火绒剑观察进程模块。很快就发现进入 登录选项 这个标签时会加载 SettingsHandlers_Authentication.dll,相关逻辑应该就藏在这里了。
放进 IDA 一看,这个 DLL 中确实有不少和 Windows Hello 相关的逻辑,然而点进函数我却发现这个 DLL 除了包含大量遥测、日志代码,还用了 eXtended Flow Guard,这直接让部分逻辑的静态分析变得几乎不可能。
碰到 _guard_xfg_dispatch_icall_fptr()
的时候,如果是调用 GUID 还可以去注册表翻一翻 CLSID,但碰到参数是几个寄存器的时候就只能傻眼了。
没办法直接从 UI 逻辑下手,我试图从导入表中找到 WBF 相关内容然后反向追回去,但是却发现这个 DLL 没有 WBF 相关的导入。猜测微软的设计模式和之前那篇分析 2019 的博客中提到的相同,还是把相关的注册组件拆成了一个独立组件。
除此之外,根据这个 DLL 的逻辑粗略分析,按钮的 SetupOrAddFingerprintSetting::get_IsApplicable()
只是简单的从一个变量里读取了这些信息然后直接返回,而 SetupOrAddFingerprintSetting::get_IsEnabled()
等函数是通过 XFG 动态计算的值。猜测 Windows Server 的相关检测也放到了前文提到的独立组件中,或者在进入设置页面的时候就已经全部计算好了。无论如何,我决定先放弃这个文件,看看能不能找到那个 “独立组件”。
凭据注册管理器
花了一点时间把 System32 下带 Enrollment 字样的 DLL/EXE 文件全部翻了一遍,最后我定位到了 CredentialEnrollmentManager.exe 这个文件上。
这个 EXE 的标题为 凭据注册管理器,关联到服务 CredentialEnrollmentManagerUserSvc,并且它在我们进入 登录选项 标签时会被自动启动。加之导入表中有 WinBio
相关的一系列函数以及之前那篇分析 2019 的博客提到的 EnrollPin
函数,我猜测实际的注册逻辑和判断逻辑都在这里。
PIN 注册判断
从之前在普通 Windows 10 中配置指纹的经验来看,还是必须有 PIN 才能设置指纹,所以这里先研究 PIN 的注册判断逻辑 (事实证明这个决定非常正确)。
根据函数名一个一个看,排除掉 PinEnrollment::v_IsSupported()
后很快我们就看到了 PinEnrollment::v_CanEnroll()
这个很明显是某种判断的函数。调试一下,很容易发现前面两个对自身变量的判断是通过了的,而在 PinEnrollment::CanAddPin()
这里返回了 false
导致我们不能添加 PIN“:
追进 PinEnrollment::CanAddPin()
,很容易发现第一个判断 this->byteE8
就没有通过:
再花一点时间找寻找写这个内存的地方,最后找到了 PinEnrollment::RefreshPolicy()
这个函数。仔细一看,上面大多是一些读取用户配置、组策略配置之类的内容,而往下翻我们很快就看到了一个重要的判断 !IsOS(0x1Du)
:
这个 IsOS
是什么东西呢?让我们看看 Win32 API 文档:
IsOS function (shlwapi.h)
Checks for specified operating systems and operating system features.
dwOS: A value that specifies which operating system or operating system feature to check for. One of the following values (you cannot combine values).
Return value: Returns a nonzero value if the specified operating system or operating system feature is detected, otherwise FALSE.
再结合这里传入的 0x1D
分析,很明显这就是我们要找的判断了。
打补丁
用 IDA 打一个简单的补丁 (如果你喜欢,这里换成 jnz 也行):
然后我们覆盖一下文件并杀掉之前的进程,重新进入 登录选项 标签,添加 PIN 的按钮就可以正常使用了。除此之外,添加指纹的组件也可以正常工作,看起来这个 Policy 判断是针对 Windows Hello 而不是单纯针对 PIN 的。
注意事项:文件权限
覆盖文件的过程中可能会碰到权限问题,你可以通过 NSudo 拉起一个 TrustedInstaller 权限的命令提示符完成覆盖操作。
为了确保操作系统的安全性不受破坏,你应该使用 icacls /save
命令来备份 CredentialEnrollmentManager.exe 的 ACL 并在替换完成后使用 icacls /restore
进行还原。
当然,你也可以选择手动设置 ACL,条条大路通罗马。
修改好的文件
如果你手上没有 IDA 或者不想自己动手,也可以直接使用我修改好的 CredentialEnrollmentManager.exe:
点击下载 (2022-12-06)我不能保证这个文件一定能工作,也不能保证它不会损坏你的计算机,你将需要自行承担可能存在的风险。如果你同意承担此风险,我会告诉你解压密码是小写的 xwtf
。
注意事项:管理员账户
Windows Server 的内建 Administrator 账户并不支持配置指纹解锁。如果你尝试进行配置,就会碰到这样的错误:
日常使用 Administrator 账户也不是一个好习惯,建立一个独立的 User + Administrators 组账户就可以使用指纹解锁了。