安卓游戏资源解密
· 1 分钟阅读 · @admin

一位同学在群里分享了一个游戏,需要对游戏资源进行解密分析。首先反编译查看源码,没有发现明显的加密逻辑。使用 Android Killer 查看资源文件,发现在 res/raw 目录下有一个较大的文件 t0.zip,解压后得到 t0.pak 文件,大小约 3MB。根据文件扩展名和格式特征判断,这是一个 PAK 格式的打包文件。

网上搜索了一些打开 PAK 文件的软件,都无法成功解析。最近阅读了《揭秘数据解密的关键技术》一书,从下图可以看到框框内的数据很像文件名,由此可以判断这是一种自定义的文件打包格式,但具体结构尚不清楚。
使用 010 Editor 分析 PAK 文件结构
解析文件推荐使用 010 Editor,它可以方便地编写文件解析模板来分析二进制格式。
通过分析可以发现,第一个文件名从偏移 0xA 开始。对比每个文件名的结构,发现名字前面的一字节数据表示该文件名字符串的长度,前面 8 个字符的含义未知,每两个字符串之间相差 8 个字节的数据。我们可以利用 010 Editor 的模板功能编写解析模板。
前 8 字节的数据暂时定义成以下结构:
typedef struct unknown
{
char unk[8];
}
包含文件名的数据结构定义如下:
typedef struct {
BYTE nameLen; // 文件名长度
char name[nameLen]; // 文件名
char unknown[8]; // 未知数据
} FILE_LIST;
定位到最后一个文件名字符串的位置:
确定文件数量和结构
通过不断调整模板文件中 i 的值来统计文件名总数,最终计算出共有 292 个文件名。此时发现文件开头的四字节数据恰好为 292,因此可以判断该字段存储的是文件总数。据此重新编写模板代码:
typedef struct {
int fileNum; // 文件数量
int unknown; // 未知数据
} PAK;
typedef struct {
BYTE nameLen; // 文件名长度
char name[nameLen]; // 文件名
CHAR unk[8]; // 未知字段
} FILE_LIST;
/////////////////////////////
LittleEndian();
PAK pak;
FSeek(0x8);
local int i;
for (i = 0; i < pak.fileNum; i++) {
FILE_LIST fileList;
}
分析文件偏移和大小信息
继续分析最后一个文件名后面的数据。数据的起始地址为 0x2D80。
观察发现,第一个 FILE_LIST 结构(模板文件中定义的结构)的 unk 字段的前 4 个字节为 0x2D80,可以判断 unk 的前四个字节存储的是偏移地址。通过比较多个 FILE_LIST 结构,发现相邻两个 FILE_LIST 结构的 unk 字段前 4 字节之差,恰好等于相邻两个文件的数据大小。
根据以上分析,将模板文件修改为:
typedef struct {
int fileNum; // 文件数量
int unknown2; // 未知数据
} PAK;
typedef struct {
BYTE nameLen; // 文件名长度
char name[nameLen]; // 文件名
int fileOff<format=hex>; // 文件偏移地址
int fileSize<format=hex>; // 文件大小
} FILE_LIST;
/////////////////////////////
LittleEndian();
PAK pak;
FSeek(0x8);
local int i;
for (i = 0; i < pak.fileNum; i++) {
FILE_LIST fileList;
}
验证文件数据
随机选择一个文件名进行验证:
可以看到后缀为 .sprite 的文件头部为 SPRX,说明该数据确实是这个文件的内容,并且没有加密。
解析图片资源
资源中最重要的是图片文件,其中占比最多的是 PNG 图片。但查看数据时发现文件头并不是标准的 PNG 格式,而是 RIFF 文件头。用常规图片浏览器无法打开,通过搜索得知这是一种较新的图片文件格式。查阅资料后发现 XnView 支持这种文件格式。
使用 XnView 打开后可以正常显示图像:
总结
至此,解密工作基本完成。接下来只需要编写一个提取工具,将 PAK 文件中的所有资源批量提取出来即可。
整个分析过程总结如下:
- 通过 010 Editor 分析二进制文件结构
- 识别文件头中的文件数量字段
- 解析文件名列表结构
- 确定文件偏移地址和文件大小字段
- 验证数据未加密
- 识别特殊图片格式并找到合适的查看工具

