记一次半吊子逆向工程的…艰难过程
前言
在搞小游戏的过程中需要一些美术资源,从网上购买了一些不是很满意,所以准备对几个精品同类手游下手,捞一手美术资源。
下手
一个某大话私服手游,解压安装包:
1 | ├── AndroidManifest.xml |
打开 lib 目录,下面三个目录对应不同 CPU 架构。
- arm64-v8a
第 8 代 64 位 ARM 处理器,是以后的架构的趋势。 - armeabiv-v7a
第 7 代及以上的 ARM 处理器,目前是主流架构。 - x86 / x86_64
32 位架构,模拟器用的比较多
1 | ├── arm64-v8a |
通过libcocos2dlua.so可以确定游戏引擎是 Cocos2d-Lua 。
如果有
libmono.so,libil2cpp.so等文件,则可能是 Unity 。
res 目录一般是 Android 工程的 Icon、Logo 等文件(忽略)。assets/res 是我们要找的资源目录,随便挑一张图片文件打开是这样的:
通过文本编辑器打开内容是这样的:
打开多个文件发现头都是sm!fd9%3nX4@这几个字符,应该是 XXTEA 算法(这是 Sign,我们需要找到 Key 就可以进行解密资源)。
逆向方案
确定是 XXTEA 算法之后,有两种方式来获取 Key:
- IDA
静态分析,或附加进程动态调试 - Frida
注入 Hook 脚本获取
两种动态获取方式流程大致相同,其原理都是注入程序读取内存之后通过端口进行转发,但是 Frida 相比较容易一些。
准备工作:
- 安卓设备 / 模拟器(本文使用的 Mumu 模拟器)
- 游戏安装包(需要开启 debug 模式)
IDA
IDA 工具拖入 libcocos2dlua.so 等待分析完成,点击 View->Open Subviews->Strings 搜索xxtea,列表中_Z13xxtea_encryptPhjS_jPj、_Z13xxtea_decryptPhjS_jPj这俩就是 xxtea 加解密的函数。
跟进 _Z13xxtea_decryptPhjS_jPj ,找到 xxtea_decrypt 及调用函数。
伪代码中的 v8 就是 Key,这里被标记一段 128 bit 宽度的数据(xmmword,刚好 16 字节),继续跟进 g_xmmword_1220CF0 。
hex -> decimal -> ascii
0x67 -> 103 -> g
0x62 -> 98 -> b
0x34 -> 52 -> 4
0x73 -> 115 -> s
0x5A -> 90 -> Z
0x7A -> 122 -> z
0x6F -> 111 -> o
0x56 -> 86 -> V
0x2F -> 47 -> /
0x66 -> 102 -> f
0x50 -> 80 -> P
0x32 -> 50 -> 2
0x50 -> 80 -> P
0x29 -> 41 -> )
0x74 -> 116 -> t
0x33 -> 51 -> 3
gb4sZzoV/fP2P)t3 这一段就是我们要找的 Key 啦。
Frida
- 安装 Frida 环境
1 | $ pip3 install frida |
- 下载 Frida Server
https://github.com/frida/frida/releases
frida-server-16.2.1-android-x86_64.xz
- 模拟器开启 root 权限,打开 USB 调试模式。
1 | $ cd /Applications/NemuPlayer.app/Contents/MacOS |
- 查看游戏包名
1 | # cd /data/app |
- 启动 Frida Server
1 | cd /data/adb |
- 测试服务
1 | $ frida-ps -U |
- 运行 Hook 脚本
1 | const libName = "libcocos2dlua.so"; |
1 | $ frida -U -f www.cocos.game -l ./key.js |
gb4sZzoV/fP2P)t3 这个就是动态获取的 Key。
解密资源
Cocos2d-x 关于 XXTEA 的 Lua 资源解密流程
CCLuaStack.cpp
1 | int LuaStack::luaLoadBuffer(lua_State *L, const char *chunk, int chunkSize, const char *chunkName) |
根据逻辑可以推出,根据加密资源头部 Sign 来确定是否 XXTEA 加密,解密时把 Sign 忽略。实现如下:
1 | func main() { |
Q&A
- adb shell 提示 error: no devices/emulators found
1 | $ ./adb kill-server |