提到加固,很多人会直接想到防破解、反外挂、防反编译。这些当然都算,但加固真正面对的其实是客户端暴露出来的攻击面。
游戏客户端里储存了不少有价值的东西,比如:登录流程、接口地址、资源加载逻辑、反作弊检测点、支付状态判断等,甚至部分游戏的战斗和数值逻辑也放在客户端。
理论上,游戏的关键逻辑应该尽量放到服务端,但在真实项目里,出于性能、弱网体验、离线玩法等方面的考量,客户端不可能完全“空心化”。
客户端跑在玩家设备上,本身不可信,但又不得不承载部分业务逻辑——这就是加固存在的原因。
通常情况下,攻击者拿到游戏APK有两种处理方式,一是进行拆包、反编译,二是观察运行时行为。这里以 Android 游戏包为例,解压后可以关注几个重点区域:
- classes.dex:Java / Kotlin 层逻辑,反编译后可能看到类名、方法名、接口路径、业务判断;
- lib/xxx.so:Native 层逻辑,Unity IL2CPP、Cocos、UE 或自研引擎里大量核心逻辑都可能在这里;
- assets/:资源、配置、脚本、AssetBundle、Lua、JS、表格等内容经常会放在这里;
- AndroidManifest.xml:权限、组件、入口 Activity、SDK 信息、部分渠道配置;
- resources.arsc:资源索引和部分可读信息。

如果游戏客户端没有做加固,那么像接口地址、开关字段、活动参数、检测逻辑、资源路径等重要线索都可能会被直接搜索出来。通常情况下,攻击者会用以下几种手段展开攻势:
1. 静态分析
静态分析不需要把游戏跑起来,只要拿到包体,就可以导进IDA等工具里慢慢看。为了避免游戏被静态分析,可以采用代码混淆、字符串加密、控制流混淆、资源加密等手段来提高逆向分析门槛。
如字符串加密可以避免接口、字段、检测标记被直接搜索;控制流混淆可以让反编译后的逻辑没那么直观;资源加密可以避免 AssetBundle、配置表、脚本文件被直接拖出来分析等等。
2. 动态分析
游戏跑起来以后,攻击面会变多。攻击者可能不关心代码长什么样,只关心运行时能不能改结果。比如 Hook 一个函数返回值,通过调试器观察关键分支,用内存工具搜索金币、血量、冷却时间,或者替换资源文件后绕过校验。
以 Android 为例,常见的手段有 Java 层 Hook、Native 层 Hook、调试器附加、内存 dump、so 注入,Frida 和 Xposed 是这类攻击最常用的两个框架。

举个简单的例子。客户端里有一个环境检测函数,正常情况下检测到异常后应该返回失败,或者上报安全事件。但如果这个函数被 Hook,攻击者可以让它永远返回正常。这样检测逻辑虽然还在,但结果已经不可信了。
3. 重打包
攻击者可以修改 APK 后重新签名,把广告模块、破解逻辑、甚至恶意代码塞进去,再通过非官方渠道传播。如果客户端没有签名校验、完整性校验,就很难判断当前运行的还是不是原始版本。

完整性校验除了可以检查安装包有没有被改,还可以检查运行时加载的 so、dex、资源包和配置文件是否符合预期。如:发现签名异常、so hash 异常、资源版本异常时,可以进行记录上报,或限制登录、支付等敏感操作。客户端是否直接闪退,要结合误报成本和业务影响看。
客户端跑在玩家设备上这个前提,就决定了它没法变成可信环境。而加固说到底是个成本博弈——破解的成本比收益高,大多数人就不会动你。门槛永远堆不到顶,但够高就够用了。