本文授权翻译自 https://andrewmoore.ca/blog/post/anticheat-secure-boot-tpm/,原作者 Andrew Moore。
随着多人在线游戏中的舞弊行为越来越普遍,一些反作弊程序厂商将目光放在硬件与固件相关的安全功能上。最近,EA 宣布 将要求玩家同时启用安全启动和 TPM(至少需要 TPM 2.0 协议规范)才能游玩其最新作《战地风云 6》。Riot 的 Vanguard 反作弊系统也对 使用 Windows 11 操作系统的玩家有类似的要求 ;随着 Windows 10 逐渐停止支持,有人猜测 Riot 有可能会将这个要求扩展到所有玩家群体。一段时间以来,安全启动(Secure Boot)和 TPM(Trusted Platform Module,可信平台模块)2.0 一直是 Windows 11 升级与安装的软性要求之一,因此对于反作弊程序厂商而言,随着 Windows 10 进入生命周期尾声,现在这个时间点添加这些硬件安全特性的支持似乎就是水到渠成。 不过,这些突然的变更还是引起了玩家社群的讨论。一些阴谋论者尝试将其形容为通过迫使玩家升级到最新操作系统以避免让他们在没那么新的硬件上游玩的诡计;或是一个规模不断扩大的、收集并出售玩家个人信息的「天网」。
为了搞清楚为什么反作弊程序厂商现今越来越依赖这些硬件加密功能,我们必须先搞清楚:这些功能(在特定场景下)到底是如何抓外挂(本文中「外挂」一词指代在游戏中作弊的外挂程序——译者注)的,对于隐私的影响又有几何,以及如何利用这些功能抓到特定的外挂。
重要提醒: 切记,反作弊引擎的设计目标并非在作弊行为开始前阻止作弊行为。反作弊引擎的真正目的是为外挂设计者设置技术高墙以更难开发出可用的外挂、更轻松地检测有作弊行为的数据包,以及避免这些「有前科」的外挂玩家绕过封禁。 任何游戏,无论何种游戏类型、是否计算密集型,甚至是否带有联网要素,都会有各种作弊行为。 不过,配合合适的手段,反作弊服务可确保削弱玩家作弊的动机,以此减少作弊者的数量,并令正常玩家有更好的体验。
安全启动是电脑主板硬件用于检测 UEFI 启动镜像〔可能是操作系统引导程序、选项 ROM(Option ROM)或任何其他 EFI 应用程序〕不被恶意第三方篡改的简单机制。安全启动依赖一个需要多个密钥参与的层次结构,以确定谁有权更新一个授权签名数据库。这个数据库的作用是,最终确认启动镜像已经过验证、未被篡改。
这个结构的最顶层是 平台密钥(Platform Key,PK) 。在 x86-64 平台上,PK 通常是电脑主板制造商的公钥。举个例子,如果你有个技嘉的主板,通常情况下你有可能找到以下 PK。
主板制造商会随主板板载制造商 PK 的公钥,但你随时可以将其替换成你自己的公钥。替换操作需要将安全启动设为 设置模式(Setup Mode) ;不同主板上,这个设置的步骤会有所不同[1]。平台密钥的存在是为了建立固件和平台拥有方之间的信任,这里所指的通常是你和你的电脑。
平台密钥 可控制这个密钥结构中下一级别的密钥: 密钥交换密钥 。
密钥交换密钥(Key Exchange Key,KEK) 用来控制对不同的签名数据库进行更改。它用于在操作系统和固件之间建立信任关系。通常,你的主板应该板载微软的(一组)KEK;在某些情况下,也有可能板载主板制造商的 KEK。任何对 KEK 的更改都应由 PK 的私钥(PKpriv)进行签名,这个机制用于未经授权的用户或软件擅自更改 KEK 值。
不过,这也就意味着任何对 KEK 的修改都必须和硬件制造商进行沟通和协调。微软最近正在更换即将过期的 KEK,也就是说,他们正在和不同的厂商合作更新这些密钥。还好 KEK 并不会经常更新。
最后,整个结构里还有 授权签名库(authorised signatures database,DB) 和 禁用签名库(forbidden signatures database,DBX) 。在微软 Windows 的语境中,这些数据库由微软的 KEK 直接签名,并随 Windows Updates 自动更新流程完成分发。
在 UEFI 固件尝试启动一个 UEFI 镜像〔这个镜像有可能是操作系统的启动引导器(bootloader)、一个选项 ROM 或任何其他 EFI 应用程序〕之前,固件会利用 DB 对镜像进行验证。如果镜像没有被签名、签名与 DBX 内的条目匹配,或是签名无法与 DB 内的条目匹配,启动过程都会被终止。
Windows 的启动加载器还会利用 DB 来验证加载的所有内核级别驱动程序的签名。不过,它只会匹配通过微软验证的密钥签名[2]。也就是说,如果一个内核级别的驱动程序没有经过微软的签名,抑或是已经存在于 DBX 中,那么 Windows 也不会加载这个驱动。
微软会在某个驱动程序拥有令攻击者在内核空间执行未经验证的程序的漏洞时将其添加到 DBX 中,这样就能有效避免带有漏洞的驱动程序随系统加载启动。只要外挂作者不能从微软获得驱动程序签名,强制让玩家启用安全启动就是一个有效避免内核层级作弊的手段,无需依赖某些未知或未修复的系统漏洞。
话虽如此,反作弊引擎也不能完全信任操作系统回报的「安全启动已启用」的信号。某位作弊者或者可疑的攻击者可以在事实上禁用安全启动,并通过加载一个内核级别的驱动让操作系统误以为安全启动已经启用。此时立刻赶到战场的就是 TPM。
可信平台模块(Trusted Platform Module)
在反作弊的语境下,TPM 可以在两个方面完成任务:
一个独特的硬件标识符可以让反作弊服务高效封禁有过「前科」的作弊者。在某种程度上这件事情还挺重要,例如,如果被抓到作弊后只封禁其帐户,那么他们可以在另一个帐户上重新买一次授权(或者,对于免费游戏而言,重新注册个帐户并不难),然后继续我行我素地开挂。通过 IP 地址封禁玩家没什么用,因为宽带运营商(ISP)并不能默认保证分配给宽带用户的 IP 地址是固定的。又因为 IPv4 资源吃紧,许多运营商正开始部署 CGNAT(Carrier-grade NAT,运营商级别 NAT),从而让多位用户共享一个 IP 地址。(即俗称的「大内网」。——译者注)
禁用作弊者的硬件是一种避免带「前科」的玩家重新注册帐户的唯一有效手段。他们得重新购买别的硬件来绕过封禁,开挂的成本因此陡然飙升。TPM 可以为反作弊服务提供一种可复现验证的识别作弊者的硬件唯一标识符。
如果真的要用 TPM 来做硬件标识符验证,需要留心不同硬件会拥有不同的 TPM 类型。分离的 TPM 芯片(Discrete TPM,dTPM)是一个可独立于 CPU 和主板购买和安装的小型 TPM 模块。在这种情况下的硬件标识符并不完全保证能识别硬件。如果你也用 dTPM,我也非常怀疑一些反作弊平台会不管三七二十一,直接不让你玩游戏。
大概在 2017 年,AMD 和英特尔都将固件 TPM(firmware TPM,fTPM)作为其大多数 CPU 产品封装的一部分。从 2021 年起,这两家所有的桌面端和移动端平台硬件都提供 fTPM。
所有的 TPM 芯片的生产都会携带一个独特且无法被修改的 认可密钥(Endorsement Key,EK) 。它的私钥部分(EKpriv)无法从 TPM 侧被导出或获取,而公钥部分(EKpub)则可被软件读取。特别是 fTPM 还拥有一个证书(EKcert),它用于确保 EKpub 真正来自其 fTPM 制造商。别有用心的人(比如作弊者)是不可能自己伪造一个可被 AMD 和英特尔验证的 EKpub 的。
利用 EKpub 本身和 EKcert 对其的验证,反作弊服务可以确保 EKpub 来自原始硬件。前文提到,fTPM 已是 CPU 封装的一部分,封禁特定的 EKpub 就意味着作弊者必须通过购买另一块 CPU 来继续在把他们封禁的游戏里开挂。
在 Windows 上,你可以通过 Get-TpmEndorsementKeyInfo -HashAlgorithm SHA256 指令获取你的硬件 EKpub 和 EKcert。
在 Linux 上,在安装了 tpm2-tools[3] 小工具之后,你可以通过以下指令获取 EKpub 和 EKcert:
TPM 上可为反作弊引擎提供助力的另一重要安全组件叫做平台配置寄存器(Platform Configuration Registers,以下简称 PCR)。每一组 24 个 PCR 都包含 SHA1 或 SHA256 哈希过的测量事件,它们可能发生在启动或运行时。对于反作弊而言,我们主要关注启动时的事件。
当一个事件通过 TPM2_PCR_Extend 指令被记录时,这个事件的数据[4]将会与 PCR 中已注册的前一个哈希值连接,然后再进行哈希计算。这样做的目的是确保每个 PCR 值可在加密学意义上确保该 PCR 上所有事件日志的完整性。如果某条记录回放时发现计算出来的 PCR 值与记录的 PCR 值,那么这些记录十有八九记录就是被篡改过的。
每个 PCR 区块(bank)都被预留给了特定的目的。例如,PCR 7 包含安全启动信息的状态:
多个 EV_EFI_VARIABLE_DRIVER_CONFIG 事件会因为记录安全启动的当前状态而被写入。平台密钥、密钥交换密钥、授权签名库和禁用签名库都会被悉数记录来进行远程认证。最终,跟随 EV_SEPARATOR 事件之后,一个 EV_EFI_VARIABLE_AUTHORITY 事件会在每次 EFI 驱动或 EFI 引导程序验证之后被记录,如果可能,其中还会包含镜像的签名。
PCR 4 会在每次 EFI 引导程序被执行后记录 EV_EFI_BOOT_SERVICES_APPLICATION 事件。
注:此处日志为部分节选,可以前往 这个页面 查看完整日志。 这些日志中不同的 EV_EFI_BOOT_SERVICES_APPLICATION 事件,也可以揭示 Windows 是被一个不同的启动引导器以链式方式加载的。
反作弊引擎也可以通过 TPM 的帮助,检测Windows是否正在通过某个管理程序(hypervisor)执行。如果宿主机的 TPM 透传到了虚拟机内,要么会在 TPM 日志中有二次启动事件、要么就会缺失相关记录,EV_EFI_BOOT_SERVICES_APPLICATION 也将会指向一个不同的、未经微软 KEK 验证(通过 EV_EFI_VARIABLE_AUTHORITY 记录可以得知)的 EFI 应用。如果 TPM 类型是虚拟 TPM(virtualised TPM,vTPM),由于 AND 和 Intel 不会为 vTPM 内的 EK 证书签名,其 EKpub 和 EKcert 都无法通过验证。
最后,Windows 也有一些存储在操作系统特定的 PCR 区块上的专有信息。特别是 PCR 14,它包含带有用于验证内核级别驱动程序签名的启动授权公钥的记录。这可以让反作弊服务确保 CustomKernelSigners 未被启用。
以下是 Windows 操作系统中,每个 PCR 区块所记录的信息类型。PCR 0 到 7 分配给了固件;随操作系统或启动引导器的不同,8 到 15 的记录类型可能会有所差异;PCR 16 通常预留给调试;PCR 23 预留给应用程序支持[5]。
在 Windows 内,你可以在 %WINDIR%\Logs\MeasuredBoot\ 访问当前或历史 TPM 活动记录的二进制格式。
在 Linux 下,根据启动引导器的不同,PCR 区块 8 到 15 包含的信息可能有所差异。Linux 用户空间 API 组发布了一个 实用的 PCR 注册表 。你可以从 /sys/kernel/security/tpm0/binary_bios_measurements 这个路径查阅当前的 TPM 事件记录。 正确检查整个操作系统启动的可信环境的最后一步,就是在确保不被用户修改的情况下获取 PCR 区块值。想要完成这一步骤,可以在给定一个审计密钥(Attestation Key,AK)的情况下通过 TPM2_Quote 完成。
通过一个复杂的加密学骚操作(TCG 的 这个 指南有详尽介绍),反作弊服务可以验证其硬件上 TPM 记录的真实性,同时验证 EKpub 与真实的、记录所有这些事件的 fTPM 芯片相关联。如果反作弊服务在验证 TPM 记录时,确认你通过一个可信的环境中连接到受保护的游戏服务器,他们就可以向你发放一个一次性使用的凭证(token)让你连上游戏大厅(这个凭证在加密学上也和你的 EK 相关联)。 反作弊服务通常会验证 DB 和 DBX 已是最新版本,以及没有在 Windows 启动过程中配置或使用用于验证自签名内核级别驱动程序的额外的启动授权。
如果反作弊服务合理使用整套证明流程、及时响应 AMD 或英特尔尚未发现的大规模安全漏洞,对于作弊者来说整套流程几乎是不可绕过的。尽管整套流程并不能杜绝外挂(操作系统、反作弊引擎和游戏本身都可能会有漏洞),但可以从硬件和内核层面避免可被外挂利用的漏洞,也能避免作弊玩家绕过封禁。
一个不争的事实是,通过内核层面的组件来反作弊的操作只能用在 Windows 上。如果一个反作弊服务就是不想适配 Linux,那咱也没啥办法。这种事情以前就是这样,现在也依旧是这样。
唯一的影响是,如果从 GRUB2、systemd-boot 和任何其他的 Linux 启动引导器来链式启动 Windows,反作弊服务有可能会产生「过敏反应」,并阻止你启动游戏——即使 PCR 14 依然允许这些启动引导器验证只有经过微软签名的内核层级驱动被加载。这个问题可以在 systemd-boot 解决,方法是在 loader.conf 中添加 reboot-for-bitlocker yes 参数。但 GRUB2 用户就没那么幸运了,它并没有设置 BootNext UEFI 变量的指令来允许 GRUB2 直接重启至 Windows,而非依靠链式启动。
不过,你还是得配置你的 Linux 安装,来让其支持安全启动。尽管一些发行版预装 shim 软件包,但我个人不推荐使用,因为它添加了额外需要管理的密钥层级(设备所有者密钥,Machine Owner Keys,MOK),如果系统使用非自由的内核模块,这可能会导致其他问题[6]。
我个人的意见是,长期而言,将你自己的平台密钥(PK)通过 sbctl 登记并用钩子签名启动镜像会更容易管理。配置起来花费时间可能会比较长,但好处是一劳永逸:不需要在内核更新的时候重新注册一个新的 MOK,一次设置终生受益。Arch Linux wiki 内 有一个相关章节介绍如何设置 subctl ,如果你用其他发行版的话可能需要根据实际情况进行配置。 我们可能会在未来看到 Linux 平台上的反作弊引擎调用 EKpub 和 EKcert 进行反作弊验证。好消息是,所有的验证操作可在用户空间内完成——只要你的 Linux 帐户在 tss 用户组内。
要求安全启动和合理配置的 TPM 远程证明对于减少非 硬件级别的游戏舞弊 是相当有效的。它同时让被封禁的玩家更难以绕过封禁。TPM 证明也可以在完全用户层级完成,对于隐私的影响微乎其微。 对于在线环境中的玩家而言,更少的作弊者与更好的诚信机制绝对是一件好事。我个人就是因为游戏社区的外挂和毒性横行而彻底放弃了在线游戏。希望这可以帮助减少作弊者的数量。Riot 公布的数据在侧面也证明了这一点(虽然我对他家游戏半点兴趣都没有)。
经管理程序保护的代码完整性 ( Hypervisor-Protected Code Integrity,HVCI) :反作弊服务通常还要求玩家启用 HVCI。这个安全功能可针对 Windows 内核的恶意软件或外挂提供更强的防护措施。它也可以用于保护用户免受带有已知漏洞、恶意行为或绕过 Windows 安全机制的驱动程序的威胁。
不幸的是,尽管我相信真正的反作弊方法是在服务器端进行行为监测,但我们暂时还不能要求游戏开发商在不明显提高算力要求的前提下用它反作弊。而且现在这个阶段,它也做不到精准打击。
在线游戏的反作弊议题要求反作弊开发商通过一系列手段,共同携手降低外挂作者的成功概率。这个母题上,解决方案不会只有一种,但通过深入、合理的应对手段,可以最大程度减轻作弊对于游戏玩家的影响。
评论区
共 3 条评论热门最新