【笔记】cocos2dx xxtea逆向获取lua脚本和资源文件
参考链接:
https://blog.csdn.net/cjbbdd/article/details/103583764
使用的一些注意点,链接中未提到的:
1.NDK版本:
使用的ndk版本为r9d,下载地址:
- windows:https://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip
- linux:https://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2
参考博客有大部分ndk版本下载:Android开发之NDK相关版本下载链接
2.获取包名
参考博客:如何获取Android的apk的包名及其入口
主要使用的指令为:
aapt dump badging <*.apk的完整路径>。(可以直接将.apk文件拖拽到命令行中,可直接获取.apk的完整路径)
3.模拟器
参考博客使用的是雷电模拟器,我使用的是夜神模拟器,博客连接安装的XposedInstaller并不能在夜神模拟器上正常运行,其实一般的模拟器都有XposedInstaller的下载地址,下载对应的版本即可。夜神模拟器在游戏中心,搜索框输入XposedInstaller下载即可。
雷电模拟器的一些问题:
(1)执行adb service 提示报错
adb server version (36) doesn't match this client (41); killing...
从报错信息上看,是由于SDK 的adb与夜神模拟器的adb的版本不匹配导致的。
解决办法
- 把AndroidSDK\platform-tools下的adb.exe赋值到桌面上,重命名为nox_adb.exe
- 把夜神模拟器下的nox_adb.exe修改为nox_adb_old.exe
- 把桌面上的nox_adb.exe拷贝到夜神模拟器下bin路径下
- 重启夜神模拟器
参考博客:解决adb server version (36) doesn‘t match this client (41); killing...
(2)AndroidStdio DDMS连接夜神模拟器
AndroidStdio打开DDMS方式:Tools——>Android——>android devices monitor.
问题:若打开DDMS后没有显示连接的device。
解决办法:
①先启动夜神模拟器
②然后运行cmd命令,cd到夜神安装目录(bin文件夹下),执行命令nox_adb.exe connect 127.0.0.1:62001或直接打开夜神模拟器安装目录(bin文件夹),然后在地址栏输入adb回车,再执行命令nox_adb.exe connect 127.0.0.1:62001或将夜神模拟器安装目录(bin文件夹)路径,配置在环境变量path中,直接执行cmd命令nox_adb.exe connect 127.0.0.1:620010即可连接到模拟器
③如果无法看到夜神模拟器,请adb后,重新启动下夜神模拟器
④注意:不要开启其他模拟器,因为夜神模拟器与其他模拟器不兼容(开启多个不同种类模拟器,会同时开启多个adb.exe进程,而系统只能识别一个adb.exe进行)
参考链接:AndroidStdio DDMS连接夜神模拟器
4.AndroidEagleEye 源码修改:
(1)如果日志报错提示‘cannot read memory map’,可能原因是加载内存map的缓存过小,load_memmap函数需要将raw数组大小,加载的内存map数据可能会超过缓存大小。
static int load_memmap(pid_t pid, struct mm *mm, int *nmmp)
{char raw[80000]; // increase this if needed for larger "maps"// 将80000修改为更大的缓存大小,80000->800000// ...
}
(2) 如果日志报错提示‘cannot read symbol table’,可能是加载libc.so符号集的open函数读取文件失败,实际系统文件是存在的,根据内存map读取的是‘/system/lib/arm/nb/libc.so’,但open函数读取文件失败,调用strerror(errno)错误提示为文件不存在(No such file or directory),具体原因未知,
R11 Plus:/ # ll /system/lib/arm/nb/libc.so
-rw-r--r-- 1 root root 1011828 2021-10-23 01:05 /system/lib/arm/nb/libc.so
查看根目录发现如下链接
R11 Plus:/ # ll /
total 1832
dr-xr-xr-x 17 root root 0 2023-02-23 18:07 acct
lrwxrwxrwx 1 root root 50 1970-01-01 08:00 bugreports -> /data/user_de/0/com.android.shell/files/bugreports
drwxrwx--- 6 system cache 4096 2021-09-18 10:26 cache
lrwxrwxrwx 1 root root 13 1970-01-01 08:00 charger -> /sbin/healthd
dr-x------ 2 root root 40 1970-01-01 08:00 config
lrwxrwxrwx 1 root root 17 1970-01-01 08:00 d -> /sys/kernel/debug
drwxrwx--x 34 system system 4096 2021-09-18 10:26 data
-rw-r--r-- 1 root root 959 1970-01-01 08:00 default.prop
drwxr-xr-x 17 root root 4020 2023-02-23 18:07 dev
lrwxrwxrwx 1 root root 11 1970-01-01 08:00 etc -> /system/etc
-rw-r--r-- 1 root root 77090 1970-01-01 08:00 file_contexts.bin
-rw-r----- 1 root root 396 1970-01-01 08:00 fstab.qcom
-rwxr-x--- 1 root root 1490548 1970-01-01 08:00 init
-rwxr-x--- 1 root root 887 1970-01-01 08:00 init.environ.rc
-rwxr-x--- 1 root root 3689 1970-01-01 08:00 init.qcom.rc
-rwxr-x--- 1 root root 25284 1970-01-01 08:00 init.rc
-rwxr-x--- 1 root root 582 1970-01-01 08:00 init.superuser.rc
-rwxr-x--- 1 root root 9283 1970-01-01 08:00 init.usb.configfs.rc
-rwxr-x--- 1 root root 5716 1970-01-01 08:00 init.usb.rc
-rwxr-x--- 1 root root 411 1970-01-01 08:00 init.zygote32.rc
lrwxrwxrwx 1 root root 10 2023-02-23 18:07 lib -> system/lib
最下面有一个lib与system/lib的链接,推测应该是android系统与底层linux之间的问题,故此在源代码load_symtab函数中做了路径替换
static symtab_t load_symtab(char *filename)
{int fd;symtab_t symtab;symtab = (symtab_t) xmalloc(sizeof(*symtab));memset(symtab, 0, sizeof(*symtab));// 增加的替换路径代码 开始if (strncmp("/system/lib", filename, 11) == 0) {char strtmp[1024] = "/lib";strncpy(strtmp + 4, filename + 11, strlen(filename) - 11);memset(filename, 0, strlen(filename));strncpy(filename, strtmp, sizeof(strtmp));}// 增加的替换路径代码 结束fd = open(filename, O_RDONLY);if (0 > fd) {return NULL;}if (0 > do_load(fd, symtab)) {log("Error ELF parsing %s\n", filename)free(symtab);symtab = NULL;}close(fd);return symtab;
}
5.参考博客文章,为避免失效,直接复制下来的,如有侵权还请告知删除:
参考链接:cocos2dx xxtea逆向获取lua脚本和资源文件_cjbbdd的博客-CSDN博客_xxtea lua
工具准备:
IDA Pro 7,具体大家想用正版还是x版,自行决定。
Android SDK 和 NDK
AndroidEagleEye,链接地址为:AndroidEagleEye
AndroidEagleEye需要XposedInstaller,直接百度下载一个最新的版本。我知道大家懒,所以链接为:XposedInstaller
一台ROOT之后的Andrid手机 或 雷电模拟器
好了,接下来接入正题。本文以一位网友发给我的一个叫做jjw.apk的【久久玩】的QP游戏。
解压缩APK文件,找到libs/armeabi/libcocos2d.so文件和位于assets目录下的src和res文件夹,这是我们需要解密的东西。我发现这个APK使用了xxtea加密。右击打开一个luac文件显示为:
luac代码内容
我们在此处看到了lua加密的签名为红色圆圈中的内容,先找个文件记录一下,以后要用。
然后打开任意一张png图片,显示为:
png资源内容
我们同样找到了png资源的签名,找到刚才的文件,记录下来。
启动IDA Pro 7 把libcocos2dlua.so托到工具中。估计这玩意会有点卡,等待IDA分析完毕这个so文件,然后找到functions视图,如果你发现你的IDA上没有这个视图,请点击View->Open SubViews->Functions打开它。如下图:
IDA Functions View
我们先来处理lua脚本。用过cocos2dxlua的都知道,引擎第一次加载lua脚本会调用cocos2d::LuaStack::executeScriptFile这个方法,所以我们选中Function Name窗口中任意一个方法,然后按下CTRL + F键,进行搜索。你会看到Function Name下方出现了一个输入框,在输入框中输入LuaStack,然后你会得到以下结果,如图所示:
搜索LuaStack结果
我们开始对结果进行分析,最开始的时候我发现了一个很奇怪的乱码一样的方法,就是cocos2d::LuaStack::hfhgjrhrhfxs,上图中有显示,于是我就双击了这个方法。因为cocos2dx作为一个开源的引擎,官方的命名是固定规则的,那么这个方法肯定是一个自定义的方法。
hfhgjrhrhfxs方法
这个肯定是看的头大的,所以我们在这里按下F5,就会变成下面的样子:
反编译之后的hfhgjrhrhfxs方法
看不出来有什么特别的地方,暂时不管他,通过上面的操作,我们暂时学会了,查找方法,类,以及反编译某个方法。接下来我们开始加速。
回到Functions window,双击cocos2d::LuaStack::executeScriptFile这个方法并进行反编译。拖动到最下边的时候发现了我们想找的方法cocos2d::LuaStack::luaLoadBuffer。如下图所示:
找到luaLoadBuffer方法的调用
双击这个地方的方法进行跟进,我们发现了今天的正主:
使用了xxtea加密
好了,我们关闭除了Functions window以外的所有窗口,然后搜索xxtea_decrypt方法,并双击,然后回打开以下内容
xxtea_decrypt方法汇编
记录下红色框中的内容,这是我们需要的方法的具体名称,我们之后的HOOK中需要用到。
红色框下方有两行绿色的方法,这是显示了,有某些地方调用到了这个方法,双击cocos2d::LuaStack::luaLoadBuffer(lua_State *,char const*,int,char const*)+D0↑p ...进去查看。
LuaStack::luaLoadBuffer中调用xxtea_decrypt的地方
我们发现这个方法的参数类型为:unsigned char* ,unsigned int, unsigned char*, unsigned int,unsigned int*,记录下来。
我找了LuaStack中的方法,发现并没有老板本cocos2dx的setxxteaKeyAndSign方法,所以我们只能通过以下方式来强行获取解密的key。
本文章使用的是雷电模拟器。打开雷电模拟器,并安装jjw.apk。
打开下载好的EagleEye,找到EagleEye.apk并安装。
安装Xposed Installer并安装激活Xposed框架,然后重启模拟器。安装完成以后,你应该看到以下界面:
Xposed安装并激活框架
然后点击左上角的菜单按钮,选择【模块】并勾选EagleEye,重启Xposed。
启用EagleEye
找到EagleEye\jni\hooks\hook_apis.c文件并打开进行编辑。
刚才我们已经知道了需要HOOK的方法的所有信息,接下来,我们需要编写我们自己的HOOK API到这个文件的末尾。
unsigned char* eagle_xxtea_decrypt(unsigned char* a,unsigned int a1,unsigned char* b,unsigned int b1,unsigned int* c);
HOOK_INFO custom_hook_info_xxtea_decrypt = {{},"libcocos2dlua","_Z13xxtea_decryptPhjS_jPj",eagle_xxtea_decrypt,eagle_xxtea_decrypt};
unsigned char* eagle_xxtea_decrypt(unsigned char* a,unsigned int a1,unsigned char* b,unsigned int b1,unsigned int* c)
{
unsigned char* (*orig_xxtea_decrypt)(unsigned char* a,unsigned int a1,unsigned char* b,unsigned int b1,unsigned int* c);
struct hook_t eph = custom_hook_info_xxtea_decrypt.eph;
orig_xxtea_decrypt = (void*)eph.orig;
LOGI("###########COMING TO HOOK xxtea_decrypt with key: %s",b);
hook_precall(&eph);
unsigned char* res = orig_xxtea_decrypt(a,a1,b,b1,c);
hook_postcall(&eph);
return res;
}
应该是有点懵逼的,没有关系,如果看不懂,就看看EagleEye的中文文档吧。这个代码的目的就是在Android的控制台打印出我需要的解密的key。
进入到EagleEye的安卓工程根目录:
EagleEye的Android工程更目录
然后进入jni目录,ndk-build编译它。
然后在根目录新建配置文件,native_lib.config。这个文件告诉EagleEye,HOOK什么so文件。内容为:
native_lib.config
这个so文件的名字就是我们刚才解压的apk里面的so文件名。
然后我们需要把编译好的EagleEye的so文件和native_lib.config这个文件推送到模拟器上。
新建doPush.bat批处理,内容如下:
adb push libs/armeabi/libeagleeyenative.so /data/data/com.mindmac.eagleeye/lib/libeagleeyenative.so
adb push native_lib.config /data/data/com.jiujiuwan.jjw/native_lib.config
pause
这个操作的目的是将libeagleeyenative.so这个文件推送到已经安装好的EagleEye中,将native_lib.config配置文件推送到需要破解的jjw.apk目录。
至于这个包名怎么来的,我想大家应该都知道吧,我就不说了。
然后打开你的命令行,找到jjw的userId:
拿到jjw的userId
进入jjw.apk的安装路径,确保native_lib.config属性可读,并设置EagleEye的系统属性:
设置文件可读性和EagleEye的属性
重启你的EagleEye和Xposed。找打Android SDK根目录->tools->monitor.bat等待Android Device Monitor开启,并检测到模拟器的日志输出。
Android Device Monitor
好了,现在启动你的jjw.apk,检查日志输出吧:
HOOK日志
我们看到了两条不一样的日志输出,没关系。我在这边文章之前多HOOK了一个方法,毕竟这个apk的作者,把luaload过程改了一个遍,让我一顿好找,所以我又遵循之前的轨迹,找到了他修改的lua_loadx方法,于是,我给了一个HOOK:
int eagle_lua_loadx(int a1, int a2, int a3, const char *a4, int a5);
HOOK_INFO custom_hook_info_lua_loadx = {{},"libcocos2dlua","lua_loadx",eagle_lua_loadx,eagle_lua_loadx};
int eagle_lua_loadx(int a1, int a2, int a3, const char *a4, int a5){
int (*orig_lua_loadx)(int a1, int a2, int a3, const char *a4, int a5);
struct hook_t eph = custom_hook_info_lua_loadx.eph;
orig_lua_loadx = (void*)eph.orig;
LOGI("###########COMING TO HOOK lua_loadx with string: %s",a4);
hook_precall(&eph);
int result = orig_lua_loadx(a1,a2,a3,a4,a5);
hook_postcall(&eph);
return result;
}
所以,这才看到了,我把加载的lua文件名给打印了出来。那么下方长的那个就是lua的密钥,短的嘛,肯定是png了啊。
接下来我们要做的就是,打开百度,搜索一个可以解密xxtea文件的玩意儿,我懒,所以我不想去写一堆解密代码了,传送门附带:XXTEA解密工具
XXTEA解密工具
好了,给大家看看结果吧:
PNG解密之后
解密之后的LUA代码
以上便是今天的全部教程,感谢大家的观看。
【笔记】cocos2dx xxtea逆向获取lua脚本和资源文件相关推荐
- cocos2dx xxtea逆向获取lua脚本和资源文件
第一次写博客,什么格式,排版都很low,大家不要喷我啊... 工具准备: IDA Pro 7,具体大家想用正版还是x版,自行决定. Android SDK 和 NDK AndroidEagleEye, ...
- 血族手游Lua脚本及资源文件解密
之前一直和朋友在玩手游血族.有一天朋友问我能不能把里面某个角色的立绘拿下来.当时没多想就答应了,以为只要解压找到图片就行了.但是万万没想到,图片竟然打不开(被加密了). 快速分析 下载最新的血族apk ...
- 在Cocos2dX游戏中使用Lua脚本进行游戏开发(基础篇)
对于游戏公司而言,采用游戏脚本lua.python等进行开发也很常见,但是很多童鞋对脚本并没有很熟悉的概念,本篇则向大家简单介绍脚本的用途以及在Cocos2dx基础用法: Lua和python这些详细 ...
- freeswitch学习笔记:将电话路由到Lua脚本
在快速测试的情况下,可以直接使用如下的originate命令在FreeSWITCH中外呼一路通话,并在电话的本端执 行Lua脚本: originate user/1000 &lua(test. ...
- 【Rainmeter】写Lua脚本遇到的文件读写问题
在为Rainmeter写lua脚本的时候,如果需要文件读写(io)操作,需要注意的是不管lua脚本是哪个skin或者哪个组件调用的,它的工作目录都不是组件的根目录(即.ini文件所在的位置),而是在R ...
- java资源文件获取属性_Java读写资源文件类Properties
Java中读写资源文件最重要的类是Properties 1) 资源文件要求如下: 1.properties文件是一个文本文件 2.properties文件的语法有两种,一种是注释,一种属性配置. 注 ...
- 安卓获取res下的资源文件:string字符串、color颜色、dimen尺寸、array数组、drawable图片和xml、anim/animator动画、raw媒体、assets资源
全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓获取内部资源并应用. 1.获取res/values文件夹下的string.xml的字符串.color.xml的颜色.dimen.xml的尺寸.ar ...
- android apk反编译(获取源码,资源文件等)
android apk反编译,是让你可以去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局是怎么实现的 一.当然我们也需要借助工具: apktool (资源文件获取,可以提取出图片文件和布局文件 ...
- android获取drawable路径,从资源文件中获取drawable
丑话说前头,本文转自: http://stackoverflow.com/questions/29041027/android-getresources-getdrawable-deprecated- ...
最新文章
- 第十四周项目二-两个成员的类模版(1)
- POJ3345 Bribing FIPA 【背包类树形dp】
- 后现代婚礼机器人显神通_机器人显神通
- 并发基础篇(四): java中线程的状态深入浅出
- 拓荒会员电商“无人区”,考拉海购能否拿下“新船票”?
- Linux学习之系统编程篇:使用条件变量实现“生产者和消费者模型”
- ajax二级联动源代码,Ajax二级联动菜单实现原理及代码
- java虚拟机读写其他进程的数据
- stack overflow--技术问答网站
- python控制步进电机驱动器_树莓派操作案例1-使用python GPIO+TB6612驱动步进电机
- 智能音箱“好耳朵”的设计奥秘
- redis mysql 事务_Mysql与Redis事务
- 转载关于星座理论的套路
- 后门及持久化访问1----辅助功能镜像劫持
- IE安全系列:脚本先锋(IV)—网马中的Shellcode
- OpenSees二次开发实例01
- Java 1072 开学寄语
- 网站logo服务器更换显示以前,网站更换logo
- telnet 不是内部或外部命令,也不是可运行的程序解决方案
- Android中按钮的点击事件的四种写法