游戏破解总结
赵云与阿斗》XAPK 逆向魔改完整实战文档
https://img.cdn1.vip/i/6a41dfdea3716_1782702046.webp
一、项目目标
对单机文字塔防游戏《赵云与阿斗》逆向修改,实现无限体力、无限初始馒头、零对局体力消耗、体力无冷却恢复,剔除广告逻辑,最终输出修改版 mod.xapk 安装包。
二、第一步:layadcc2 资源格式逆向解密
1. 资源路径
加密资源目录:assets/cache/dcc2.0/objects/
目录包含 394 个无后缀文件,文件名全部为 SHA1 哈希字符串。
2. layadcc2 文件头部结构(总共 24 字节头部)
表格
| 偏移位置 | 占用长度 | 字段说明 | 样例数据 |
|---|---|---|---|
| 0x00 | 8 Byte | 文件魔数 | layadcc2 |
| 0x08 | 4 Byte | 版本号(小端序 LE) | 02 00 00 00 |
| 0x0C | 8 Byte | XOR 加密密钥 | e9 b6 86 5f 86 8d 03 2a |
| 0x14 | 4 Byte | 加密数据长度(小端序 LE) | - |
| 0x18 往后 | 剩余全部 | 加密数据流 | 逐字节异或加密内容 |
3. 加解密规则
- 固定 8 字节密钥:
2a038d865f86b6e9 - 解密公式:
明文字节 = 密文字节 ^ 密钥[字节下标 % 8] - 批量解密全部文件后,得到核心业务逻辑文件
js/bundle.js(大小 2.8MB,游戏主逻辑载体)
三、第二步:bundle.js 三层混淆逐层脱壳
第一层:\xNN 十六进制转义字符解码
混淆特征:所有字符串被转义为 \xXX 十六进制格式
javascript
运行
1 | // 解码代码 |
示例:this['\x63\x69'] 解码后等价 this['ci']
第二层:字符串数组下标混淆
混淆特征:全部字符串预先存入数组,通过数组下标取值调用
javascript
运行
1 | var _0x181c = ["\u0072\u0061..."]; |
处理方案:提取完整字符串映射表,全局批量替换下标调用为原始明文字符串。
第三层:_0x727 自定义栈虚拟机数值混淆
混淆运算规则
函数调用格式:
1
_0x727([32, A, 32, B, 38, 37])
等价原生运算:
1
A ^ B
(两数异或运算)
脱壳方案
全局匹配该函数调用,直接替换为原生
1
A ^ B
表达式,裸露真实运算数值,方便定点修改。
四、第三步:定位目标变量代码位置
1. 体力类 T(搜索关键词 _stamina)
javascript
运行
1 | T = class { |
2. 馒头货币类 d(Ki 变量,搜索 get Ki())
javascript
运行
1 | d = class { |
- 变量访问路径:
F['instance']()['Gn']['Ki'] - 关键特性:Ki 属于运行时临时变量,不存入本地存档 JSON,对局结束自动归零,仅修改构造函数初始值可以永久生效。
五、第四步:XOR 数值最小侵入式修改方案
1. 异或修改推导公式
原始运算:result = A ^ B
修改目标:将运算结果改为 NewVal
推导新右值:B_new = A ^ NewVal
修改原则:左操作数 A 保持不变,仅替换 B 值,不改动原有代码结构,重加密后兼容性最强,不易程序崩溃。
示例:
原式 327014 ^ 327026 = 20,需要结果改为 99999
plaintext
1 | newB = 327014 ^ 99999 = 359417 |
_0x727 封装异或函数同理,仅修改参与运算的对应参数即可。
2. 特殊变量处理(体力恢复间隔 an)
an 未做异或混淆,定义形式为匿名返回函数:
javascript
运行
1 | function(){return 300000;} |
该字面量全局出现两处,必须携带上下文 \x61\x6e']=function(){return 300000;} 精准唯一匹配替换,避免误修改其他冷却计时变量。
3. 修改收尾
JS 修改完成后,反向套用 XOR 加密算法,对文件重新加密,覆盖原哈希命名的资源文件。
六、第五步:XAPK 重打包踩坑与解决方案
问题 1:apktool 编译重复类报错
报错信息:Class Lcom/facebook/ads/...ColorInfo; has already been interned
成因:Facebook 广告 SDK 以 assets dex 形式重复存放,smali_assets/com/ 与 smali_assets/audience_network/classes2/ 存在大量重复类
解决方案:手动删除 com/ 重复目录,运行时定向加载 audience_network/classes2.dex
问题 2:Split APK 分包签名不一致
XAPK 由 base、V1、V2、V3 多个分包组成,安装校验要求全部分包使用同一个签名证书
解决方案:自建 keystore 签名密钥,对所有分包统一重签名。
问题 3:XAPK 打包后无法被安装器识别
APKPure 等主流 XAPK 安装器要求包内文件禁止压缩
解决方案:使用 Python zipfile 开启 ZIP_STORED 无压缩模式打包输出成品。
七、修改前后参数对照表
表格
| 修改项目 | 修改前 | 修改后 |
|---|---|---|
| 初始馒头 (Ki) | 20 | 99999 |
| 最大体力上限 | 30 | 99999 |
| 每局体力消耗 | 5 | 0 |
| 体力恢复间隔 | 300 秒 | 0ms |
输出成品:赵云与阿斗_1.0.4_mod.xapk(105MB)
八、实战总结 & 通用逆向经验
- layadcc2 防护强度极低,仅固定文件头 + 简单字节异或加密,逆向解密门槛很低,仅做基础防小白篡改。
- JS 三层混淆属于 “纸老虎防护”:转义字符、字符串数组、自定义异或虚拟机仅增加阅读难度,理清运算逻辑后可精准还原、定点改值,不会破坏原有程序逻辑。
- XOR 原位改值是最优修改方案:仅替换数字、不改动代码结构,程序崩溃概率最低,重加密兼容性最好。
- Split XAPK 打包最大难点是签名一致性,多分包必须统一签名,是打包阶段最高频踩坑点。
- 单机游戏本地加密、代码混淆都无法有效防篡改;真正防数值修改必须依赖后端数据校验,单机魔改效果仅本地生效。
- https://img.cdn1.vip/i/6a41e007372ae_1782702087.webp