大型多人联机游戏的安装最佳做法

本文介绍如何为大型多人联机游戏 (MMOG) 客户端安装和自定义游戏更新系统创建信任链设计,这些系统与 Windows 以及 Windows Vista 和 Windows 7 的安全模型配合良好。 该方法的目的是在支持标准用户帐户的同时,为 MMOG 游戏打补丁,而标准用户帐户限制了对硬盘驱动器和系统注册表的访问。

为什么 MMOG 客户对传统零售购买游戏有不同的要求

MMOG 不断连接和不断发展的性质使得定期更新客户端代码和内容以修复安全漏洞和扩展游戏体验成为一项基本要求。 由于几乎每天都有更新的可能性,MMOG 方案需要仔细管理,以确保用户友好的体验。 这与传统的零售购买模式不同,在传统零售购买模式中,可能会在产品零售发货日期附近提供少量补丁。 操作系统提供的 Windows Installer 有限用户修补技术旨在处理少量的应用程序修补程序,而不是 MMOG 所需的大量和高频率修补程序。 因此,通常需要开发自定义修补系统来满足 MMOG 的需求,包括针对正在开发的特定 MMOG 的任何特殊要求。

由于有如此多的计算机连接到 Internet,Windows Vista 和 Windows 7 对用户有更严格的安全限制和保护措施,这限制了应用程序对硬盘驱动器各个区域的访问。 与 Windows XP 不同,这些限制是为用户帐户的默认模式启用的。 在设计游戏布局、可执行文件和数据及其相关修补系统时,必须考虑这些限制。 有关操作系统提供的安全措施的详细信息,请参阅用于游戏开发人员的用户帐户控制

信任链方法概述

本白皮书中提出的自定义更新方法基于在受保护的 Program Files 文件夹中安装值得信赖的加载程序应用程序,同时将游戏可执行文件和数据保存在共享的所有用户可访问区域中。 信任链始于加载程序,它在启动之前对游戏二进制文件和数据执行有效性检查。

信任链始于一个值得信赖的加载程序

值得信赖的加载程序需要有足够的逻辑,能够在启动游戏之前验证游戏的可执行文件和其他二进制文件没有被篡改。 加载程序还可以根据需要经常验证游戏数据;然而,游戏数据的大小通常太大,无法在单次传递中每次都进行检查。 另一种方法是使用采样模式,确保在较长的时间内对整个数据集进行验证。 加载程序应用程序可能包含游戏修补引擎,该引擎通过将更新与已安装的游戏集成来提供值得信任的方法。

服务器上验证了所有内容,如果我的客户端被黑客攻击,我为什么要担心呢?

无法信任客户端未被入侵;因此,MMOG 服务器通常会验证从客户端接收的所有数据。 虽然此处理可以识别游戏世界中遭到入侵或欺骗的游戏客户端,但服务器无法轻松识别游戏客户端可能面临的所有问题。 请务必加强对黑客的防护,防止黑客将你的客户端用作攻击你的服务、其他用户的平台,甚至只是作为攻击客户端机器本身的载体。 代码签名和数据验证技术的应用可以帮助在被执行之前检测到被感染的客户端。 由于修补机制需要公开不受程序文件的标准只读权限保护的可执行文件和 DLL 二进制文件,因此在启动这些文件之前对其进行验证对于整体系统安全非常重要。

此模型不尝试处理恶意管理员用户方案,因为加载程序本身可能会遭到入侵,而是侧重于保护标准用户不意外地运行被篡改的代码。 对于恶意的客户端系统管理员来说,传统的服务器-客户端验证技术实际上是唯一可能的缓解方法。

构建 Trust-Worthy Loader 应用程序

后台读取

读者应熟悉以下文档,其中提供了确保基于软件的信任的最佳做法的基础技术的详细信息。

代码签名

针对游戏开发人员的验证码签名

SignTool

MSDN 上的 SignTool

以下部分详细介绍了应用于构造加载程序应用程序的 API,该应用程序支持用于安装和验证信任检查的光盘布局。

安装受信任的加载程序和修补程序

与传统安装一样,应将受信任的加载程序和修补程序实用工具的基本版本安装在 HDD 上受保护的 Program Files 文件夹下。 加载程序应用程序的安装和修补需要管理员权限,因此尽量减少加载程序的更新频率以确保最终用户不需要经常升级非常重要,尽管可以使用 Windows Installer 有限的用户修补来避免加载程序修补程序的升级。

请参阅 Windows XP、Windows Vista 和 Windows 7 中修补游戏软件一文。

安装游戏可执行文件、DLL 和数据

为了方便标准用户在没有管理权限的情况下更新游戏,游戏可执行文件、DLL 和数据必须安装到所有用户都可以写访问的硬盘区域。 操作系统提供了一个“所有用户应用程序数据”区域,可用作默认安装位置。 SHGetFolderPath 应与 CSIDL_COMMON_APPDATA 键一起使用,以确定此区域的文件路径。 重要的是,不要假设此密钥返回的路径,因为它可能是用户可配置的。

安装需要更改或管理文件夹权限,才能实现更新游戏所需的所有用户共享写入访问权限。 使用正确的权限,加载程序程序的游戏更新程序功能可以轻松修补游戏,而不需要任何用户帐户的特权,包括由标准用户启动的时间。

访问控制列表修改代码

对于 Windows XP,需要执行代码来手动更改访问控制列表 (ACL),以下是一个示例函数,演示了如何执行此操作:

HRESULT ChangeACLtoAllowUserRW( WCHAR* strDir )
{
    EXPLICIT_ACCESS explicitaccess;
    PACL NewAcl = NULL;
    DWORD dwError;

    BuildExplicitAccessWithName( &explicitaccess, L"BUILTIN\\Users",
                                 GENERIC_ALL, GRANT_ACCESS,
                                 SUB_CONTAINERS_AND_OBJECTS_INHERIT );
                                 
    dwError = SetEntriesInAcl( 1, &explicitaccess, NULL, &NewAcl );
    if( dwError == ERROR_SUCCESS) 
    {
        dwError = SetNamedSecurityInfo( strDir, SE_FILE_OBJECT,
                                        DACL_SECURITY_INFORMATION,
                                        NULL, NULL, NewAcl, NULL );
        if( dwError == ERROR_SUCCESS)
        {
            if( NewAcl != NULL ) AccFree( NewAcl );
            return S_OK;
        }
    }

    if( NewAcl != NULL ) AccFree( NewAcl );
    return E_FAIL;
}

此代码示例也适用于 Windows Vista 和 Windows 7;但是,它们还提供命令行实用工具 icacls 来编辑编辑文件 ACLS,你可以选择使用它。

该工具在执行时提供了详细的帮助,但该工具的一个示例用法是:

icacls "C:\Users\All Users\Game" /grant Rex:(D,WDAC)

此用法将授予用户 Rex Delete 和 Write DAC 权限,以访问存储在硬盘“所有用户”区域中的游戏文件夹。

高级用户安装

对于高级用户安装方案,用户可能需要手动指定游戏安装路径。 目录选择应限制在程序文件之外,以确保文件夹位于硬盘驱动器的真正可共享区域。 用户选择的路径应仅用于游戏执行程序和数据,因为游戏加载程序和补丁程序执行程序应始终安装在安全的 Program Files 文件夹下,以提高安全性。

加载程序的信任验证

Windows 提供了用于检查签名代码有效性的 WinVerifyTrust 函数,该函数基于操作系统中的加密服务。 该函数在 MSDN 上有完整的文档记录:WinVerifyTrust 函数。

有关使用函数确定程序可执行文件是否使用有效证书签名的更多详细信息,请参阅示例 C 程序:验证 PE 文件的签名

为了验证已签名的游戏可执行文件是否值得从加载程序内执行,通用验证操作就足够了:

WINTRUST_ACTION_GENERIC_VERIFY_V2

含义

使用 Authenticode 策略提供程序验证文件或对象。

该函数接受一个输入结构参数,该参数包含信任提供程序处理指定操作所需的信息。 通常,与前面的示例情况一样,该结构包括标识信任提供程序必须评估的对象的信息。

结构的格式特定于操作标识符。 有关 WinTrust 提供程序的示例结构的更多详细信息,请参阅 WINTRUST_DATA 结构。

如果信任提供程序验证该使用者对于指定操作是受信任的,则返回值为零。 除了零之外,其他任何值都不应被视为成功返回。

数据验证

代码签名机制仅支持对几种特定类型的文件进行签名,包括可执行文件、DLL、Windows Installer 包(.msi 文件)和cabinet (.cab) 文件。 不应使用 WinVerifyTrust API 来验证大型数据文件(例如,.cab 文件)是否未被篡改,因为在验证非常大的文件时存在一些性能和稳定性问题。 程序可执行文件往往足够小,以便使用 WinTrust 提供程序进行完全信任检查,但游戏数据文件的大小通常为数 GB。 加载程序用于验证游戏数据的方法应该是在游戏运行期间测试数据集的一小部分样本。 此方法将验证测试的成本分散在游戏游戏体验的整个生命周期内,可以提供无缝的用户体验,而无需长时间等待。 为了实现这一点,可能需要仔细组织数据。 一些 MMOG 采用数据库方法来帮助管理、维护和验证游戏资产随时间推移的正确性。

从安全的角度来看,客户端代码的设计应该是不信任数据文件,即使对受信任的加载程序使用某种基本的数据验证。 应使用标头检查、哈希和其他传统完整性检查。 还应使用模糊测试等技术以及利用 Visual Studio 2005 和 Visual Studio 2008 中的 /analyze 开关等自动静态代码分析工具(在 Visual Studio Team System 和 Windows SDK 附带的免费编译器中可用)来强化客户端的 I/O 代码。

有关软件安全性的详细信息,请参阅游戏开发中的最佳安全做法