【游戏逆向笔记】 是 lxraa 的技术分享系列,记录”我”习得老爹的黑客技艺后,在游戏逆向领域的探索笔记,基于真实游戏逆向分析过程的半虚构日记式写作。
(友情提示)读完之后,你可能一时半会儿都不太想单纯「打游戏」了。
在上篇中,我接受了老张的挑战,开始验证Roy*l M**的螺旋桨棋子是否真的是”AI”。
但静态分析只能告诉我”代码怎么写的”,不能证明”它真的这么运行”。
要完整验证这套权重系统,我需要从”逆向分析”切换到”动态测试”。
要测试,第一个问题就是:如何控制测试环境?
我需要修改关卡数据。
我在反编译的代码里找到了LevelDataManager.LoadLevel()方法:
public LevelData LoadLevel(int levelNumber)
{
string path = $"{levelNumber}";
TextAsset textAsset = Resources.Load<TextAsset>(path);
byte[] bytes = textAsset.bytes;
ByteBuffer buffer = new ByteBuffer(bytes);
FTiledLevel flatLevel = FTiledLevel.GetRootAsFTiledLevel(buffer);
return ConvertToLevelData(flatLevel);
}
FTiledLevel——FlatBuffers格式。
游戏开发者有.fbs协议文件,但我没有。
不过我可以反推。
FlatBuffers的编译器flatc会把.fbs协议文件编译成对应语言的类。关键点在于,这个编译过程是不丢信息的——每个字段的名称、类型、偏移量、默认值,都会1:1映射到生成的代码里。
最明显的证据是CreateFTiledLevel()方法。这个方法的参数列表,就是.fbs文件里所有字段的完整定义。参数的顺序、类型、命名,都和原始协议文件一致。
换句话说,只要我能找到这个Create方法,就能完整还原.fbs文件。
我又一次把任务交给AI。
让AI读取CreateFTiledLevel()方法的参数列表,结合所有访问FTiledLevel字段的代码,得到了一个228行的.fbs文件。
FlatBuffers关卡数据协议:
关键结构节选:
// 主要的关卡结构
table FTiledLevel {
name:string;
move:int; // 移动次数
goals:[FGoalData]; // 关卡目标
grid:FTiledGrid; // 棋盘布局
predefined:[FTiledPredefined]; // 预定义元素
sets:[FTiledSet]; // 棋子集合
colors:[int]; // 颜色配置
// ... 50+ 字段定义
}
root_type FTiledLevel;
有了协议文件,我就可以:
我需要一套完整的测试工具链。
第一步,获取关卡数据样本。我在Roy*l M**的包里翻出了所有关卡数据文件——几千个关卡,每个都是FlatBuffers二进制格式。这些真实关卡数据能帮我验证还原的.fbs协议是否正确。
第二步,实现序列化/反序列化。用flatc把.fbs编译成Python代码,然后写了两个脚本:一个读取游戏的关卡文件并解析成人类可读的JSON,一个把修改后的JSON重新序列化成FlatBuffers二进制。测试了几个真实关卡,序列化→反序列化→再序列化,字节级完全一致。协议还原成功。
第三步,运行时注入。用Frida写了个注入脚本,Hook游戏加载关卡的函数,在内存中替换掉原始关卡数据。这样我就不需要重新打包游戏,直接在运行时测试自定义关卡。
测试工具链搭建完成。

图:关卡编辑器可视化界面
现在,我可以设计任何我想要的棋盘布局,注入游戏,观察螺旋桨棋子的真实行为。
测试时刻:
双击启动器,选择修改过的64关,点击启动。
手机屏幕亮起,Roy*l M**启动,进入64关。
左上角的移动次数显示:3000。
我笑了,随便点了几下。消除,消除,消除。不到一分钟,三个目标全部完成。
屏幕中央弹出金色的”Level Complete”。
“这就是氪金玩家的视角吗?”我自言自语。

图:Frida脚本注入+关卡编辑器+修改后的游戏界面
至此,我已经完全证明了老张纯属扯淡。
我整理完最后一份文档,打开统计脚本,看着输出结果:
分析文件数: 6823
文件总行数: 1025528
总函数数: 64445
已还原函数数: 1392
还原进度: 2.16%
已还原函数有效代码行数: 34670
这1392个函数,足够回答老张的问题了。
验证流程回顾:
graph TD
A[IL2CPP逆向] --> B[ILSpy导出骨架]
B --> C[IDA Pro还原汇编]
C --> D[AI还原C#代码]
D --> E[业务逻辑梳理]
E --> F[FlatBuffers协议还原]
F --> G[测试工具开发]
G --> H[动态验证]
H --> I[结论:精密规则引擎]
style I fill:#fde68a,stroke:#d97706
我给老张发了条消息。
“验证完了。”
他秒回:”怎么样?”
“你说对了一半。”我打字,”螺旋桨棋子确实很聪明。但不是AI。”
“……”
我把一堆文档丢过去。
过了几分钟,他回复:”明白了。游戏设计。”
“对。”
停顿了几秒。
“你输了。”我打字,”请吃饭,海底捞。”
“条件是你得给我讲讲那套权重系统。”
“没问题,反正你请客。”
“……”
我关掉聊天窗口,靠在椅子上伸了个懒腰。
窗外天已经黑了。屏幕的光照在脸上,文件夹里一堆文档和代码。
我起身去倒了杯水,回来的时候老爹正好路过。
他扫了眼屏幕上的统计数据,停顿了两秒。
“做完了?”
“嗯。”
“用了多久?”
“一个月。”
他点点头,端着茶杯继续往前走,隐约还哼了两句不知道什么调。
任务名称:Roy*l M** 螺旋桨棋子算法验证
起因:老张的都市传说
目标:证明国王不是AI
预计耗时:一周
实际耗时:一个月
任务状态:✓ 已完成
任务奖励:老张请的火锅(顺便给他讲权重系统)
螺旋桨棋子智能决策系统架构
通过完整还原300+个C#类和81种棋子逻辑,发现螺旋桨棋子系统采用五层计算架构 + 三层重定向机制:
五层权重计算体系:
策略层:4种攻击模式
全局层:棋盘分数计算(ExplodeTargetFinder)
单元格层:单格权重计算(ExplodeTargetMediator)
道具层:81种棋子独立评分(GetExplodeScore虚函数)
影响因子层:16个Helper系统跨棋子影响
三层重定向机制:
策略级重定向:通关条件优先
道具级重定向:道具自身重定向逻辑
Helper级重定向:跨道具复杂重定向
技术复杂度评估
开发成本:
工具链记录
声明:本文内容仅供学习和研究使用,请勿用于商业用途或破坏游戏平衡。
代码会说真话。
本文为基于真实技术分析的虚构故事,文中截图、图片如有展示,均作技术示意,与具体厂商和项目无直接指向关系。
未经授权 禁止转载。
版权所有 © lxraa 2025