cocos2d编写android插件,[分享]Xposed插件dump Cocos2d-x应用的lua脚本-程序员宅基地

技术标签: cocos2d编写android插件  

入门示例,大佬轻拍。

没有找到预览,请忍受排版。

很多安卓游戏、应用使用Cocos2d-x和lua开发,并且lua脚本都是加密保存的,根本无法直接阅读。

今天我们基于Xposed开发一个插件,来dump内存中解密过的lua脚本。

由于Xposed原生不支持native的hook,没有实现和提供相关API,所以我们需要借助其他项目的native hook代码。

创建项目

因为我们一直在使用fooXposed项目,并且不打算创建新项目,但是fooXposed不包含C++支持,所以需要手动添加C++支持。

如果你在创建新项目的时候,选择了C++选项,如下图所示,请跳过这一小节。

7e3678ea56262327fbae247529b80b97.png

1. 在fooXposed项目中创建DumpLua模块

2. 从其他包含C++支持的项目中拷贝CMakeLists.txt到模块的根目录

5118004b7a8603e7c6feb850e37dd173.png

3. 修改CMakeLists.txt如下

01e48250f2c9dd395cc954c98af421c4.png

4. 创建JNI目录

右键点击模块=>New=>Folder=>JNI Folder

4c74e199eeb68f3cd87de16b1341996d.png

创建目录之后,在JNI Folder中创建源文件main.c,结果如下

2e7f580e1d08afdf7e8d72579f1485dc.png

5. Link C++ Project with Gradle

右键点击项目=>Link C++ Project with Gradle=>在Project Path中输入CMakeLists.txt文件的完整路径=>OK。

然后等待项目Build完成即可。

96fb596648fdeb18452b53fd2206247a.png

引用native Hook代码

因为Xposed不能支持native hook,所以我们需要使用ele7enxxh大神的Android-Inline-Hook项目,使用方法参考:https://github.com/ele7enxxh/Android-Inline-Hook。

1. 克隆下载Android-Inline-Hook代码到本地

2. 复制以下native hook代码文件到项目的JNI目录中

379c8b7f2e42d114977f3976402dd445.png

3. 修改CMakeLists.txt文件,在add_library中添加inlineHook.c和relocate.c的配置

797113038190d6d67b58e95876a05aa7.png

4. 修改inlinehook.c文件的错误提示

a.添加include声明

#include

#include

b. cacheflush报错,将包含cacheflush的行的代码替换如下

__builtin___clear_cache(CLEAR_BIT0(item->target_addr), CLEAR_BIT0(item->target_addr) + item->length);

lua脚本加载函数

众所周知,lua脚本的加载是通过以下函数完成的,函数的定义参考:

http://www.lua.org/source/5.0/lauxlib.c.html

http://www.lua.org/source/5.1/lauxlib.c.html

LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,const char *name)

其中,参数buff是lua脚本在内存的起始位置,参数size是lua脚本的的大小,参数name是脚本的名称(这个名称可能很长,也可能和buff相同

a3b34f67a638f3077d235430c84699d3.png)。

hook luaL_loadbuffer

按照https://github.com/ele7enxxh/Android-Inline-Hook介绍的方法hook函数luaL_loadbuffer,代码如下(请不要在意代码结构if else为了通过日志显示信息):

#define PACKAGE_NAME "target.package.name" // 目标应用的包名

#define TARGET_SO "/data/data/%s/lib/libcocos2dlua.so" // 目标应用的libcocos2dlua.so

int (*origin_luaL_loadbuffer)(void *lua_state, char *buff, size_t size, char *name) = NULL;

int my_luaL_loadbuffer(void *lua_state, char *buff, size_t size, char *name) {

LOG_INFO("lua size: %d, name: %s", (uint32_t) size, name);  // 打印lua脚本的大小和名称

//    以下代码将lua脚本写入以大小为名称的文件中,这样是有问题的。

//    其实应该以name命名文件,但是以上输出的日志会显示奇奇怪怪的名称。

//    具体细节,作为练习,自己研究吧。

//    char filename[64] = {0};

//    sprintf(filename, "/data/data/%s/%d.lua", PACKAGE_NAME, (unsigned int) size);

//    FILE *fp = fopen(filename, "w");

//    if (fp) {

//        fwrite(buff, size, 1, fp);

//        fclose(fp);

//    }

return origin_luaL_loadbuffer(lua_state, buff, size, name);

}

//JNIEXPORT jint JNICALL __unused JNI_OnLoad(JavaVM *vm, void* reserved){ // 使用这行代码,我的环境编译出错

JNIEXPORT jint JNICALL __unused JNI_OnLoad(JavaVM *vm) {    // 我的环境只能使用这行代码,如果编译JNI_OnLoad出错,请使用上一行代码

LOG_INFO("JNI_OnLoad enter");

JNIEnv *env = NULL;

if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) == JNI_OK) {

LOG_INFO("GetEnv OK");

char so_name[128] = {0};

sprintf(so_name, TARGET_SO, PACKAGE_NAME);

void *handle = dlopen(so_name, RTLD_NOW);

if (handle) {

LOG_INFO("dlopen() return %08x", (uint32_t) handle);

void *luaL_loadbuffer = dlsym(handle, "luaL_loadbuffer");

if (luaL_loadbuffer) {

LOG_INFO("luaL_loadbuffer function address:%08X", (uint32_t) luaL_loadbuffer);

if (ELE7EN_OK == registerInlineHook((uint32_t) luaL_loadbuffer,

(uint32_t) my_luaL_loadbuffer,

(uint32_t **) &origin_luaL_loadbuffer)) {

LOG_INFO("registerInlineHook luaL_loadbuffer success");

if (ELE7EN_OK == inlineHook((uint32_t) luaL_loadbuffer)) {

LOG_INFO("inlineHook luaL_loadbuffer success");

} else {

LOG_INFO("inlineHook luaL_loadbuffer failure");

}

} else {

LOG_INFO("registerInlineHook luaL_loadbuffer failure");

}

} else {

LOG_INFO("dlsym() failure");

}

} else {

LOG_INFO("dlopen() failure");

}

} else {

LOG_INFO("GetEnv failure");

}

LOG_INFO("JNI_OnLoad leave");

return JNI_VERSION_1_6;

}

实现Xposed插件

因为属于普通的插件开发代码,本小节进行了简化描述,表达清楚意思即可。

1. 添加依赖:compileOnly 'de.robv.android.xposed:api:82'

2. 实现接口,Hook Runtime.doLoad()方法public class Main implements IXposedHookLoadPackage {

private static final String TAG = "DumpLua";

private static final String DUMP_LUA_SO = Environment.getDataDirectory()

+ "/data/foo.ree.demos.dumplua/lib/libdumpLua.so";

@Override

public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpp) throws Throwable {

if (!"target.package.name".equals(lpp.packageName)) return;

findAndHookMethod(Runtime.class, "doLoad", String.class, ClassLoader.class, new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) throws Throwable {

String name = (String) param.args[0];

Log.i(TAG, "Load so file: " + name);

if (param.hasThrowable() || name == null || !name.endsWith("libcocos2dlua.so")) {

return;

}

Log.i(TAG, "Loading dump lua so::::::::::::::");

System.load(DUMP_LUA_SO);// 因为权限控制,在高版本的Android系统会执行失败

}

});

}

}

3. 配置assets/xposed_init

4. 配置meta-data

备注

只是介绍入门,介绍方法。

真正执行dump的代码被注释掉了,和文章标题描述有点差别,但是打开注释就能执行dump,但是输出的文件没有名称,会丢失很多信息。这是为了希望入门的同学自己能够动手,发现很多细节的东西。

这些代码在Android 4.4.4上测试过,运行正常。

本例只适用于32位的设备,对于64位的设备,没有测试,可以预见会存在问题。

对于寻求成品插件的同学,说声抱歉。

因为fooXposed使用最新版本的Android Studio 3.1.1开发,对于使用低版本AS的同学,可以拷贝代码到自己的工具中测试。

具体代码参考:https://github.com/fooree/fooXposed/tree/master/DumpLua

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_29378153/article/details/117538166

智能推荐

springboot启动报错 Failed to scan *****/derbyLocale_ja_JP.jar from classloader hierarchy_failed to scan from classloader hierarchy-程序员宅基地

文章浏览阅读4.1k次。问题这是部分报错信息2019-07-11 14:03:34.283 WARN [restartedMain][DirectJDKLog.java:175] - Failed to scan [file:/D:/repo/org/apache/derby/derby/10.14.2.0/derbyLocale_ja_JP.jar] from classloader hierarchyjava...._failed to scan from classloader hierarchy

MATLAB-ones函数_matlab中ones函数-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏7次。在MATLAB中,ones函数用于创建一个指定大小的由1组成的矩阵或数组。_matlab中ones函数

解决PS等软件出现应用程序无法正常启动(0xc000007b)_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。-程序员宅基地

文章浏览阅读3.9w次,点赞2次,收藏9次。  在使用电脑办公过程中,安装应用程序时难免遇到无法安装或者无法正常启动的问题,这对我们使用电脑带来了诸多不便。那遇到应用程序无法正常启动的问题要如何解决呢?相信大家肯定都是十分疑问的,每次都是只能忍痛重新安装软件。今天,小编就和大家探讨下应用程序无法正常启动的解决方法,帮助大家排忧解难。0xc000007b电脑图解1  第一种方案:SFC检查系统完整性来尝试修复丢失文件  1、打开电脑搜索输入cmd.exe,选择以管理员身份运行,跳出提示框时选择继续。0xc000007b电脑图解2_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。

oracle介质恢复和实例恢复的异同-程序员宅基地

文章浏览阅读396次。1、概念 REDO LOG是Oracle为确保已经提交的事务不会丢失而建立的一个机制。实际上REDO LOG的存在是为两种场景准备的:实例恢复(INSTANCE RECOVERY);介质恢复(MEDIA RECOVERY)。 实例恢复的目的是在数据库发生故障时,确保BUFFER CACHE中的数据不会丢失,不会造成数据库的..._oracle 实例恢复和介质恢复

Map中的putAll方法_java map putall-程序员宅基地

文章浏览阅读7k次。HashMap map1=new HashMap(); HashMap map2 = new HashMap();map2.putAll(map1)上面的代码的意思是将map1中所有的<key,value>插入到map2中去。具体参考: HashMap map1=new HashMap(); map1.put("..._java map putall

基于javaweb仿京东商城管理系统的设计与实现(含论文和程序源码及数据库文件)_基于java web的网店管理系统的设计与实现-程序员宅基地

文章浏览阅读1w次,点赞8次,收藏60次。网上购物商城系统以弥补传统购物方式的弊端。在目前的商城里,如果采用网上商城方式,用户购物时就不需要到店里面排队,这样不仅能实时地了解商品的特色,而且方便了顾客,同时也减轻了商城的服务压力。随着WLAN技术的普及,一些规模较大的商城开始考虑利用这种最为先进、最具时尚潮流的网络技术来建设一套灵活、快捷的信息管理系统,以优化管理流程,使网上的服务和管理得到实质性的提升,提高品牌形象和行业核心竞争力。 本课题是实现了网上购物系统的功能,如:商品分类、订单管理等功能。本设计采用安装 JAVA JDK 、安装 IDEA_基于java web的网店管理系统的设计与实现

随便推点

linux中进程退出函数:exit()和_exit()的区别_linux结束进程可以用哪些函数,它们之间有何区别?-程序员宅基地

文章浏览阅读4k次,点赞4次,收藏9次。 linux中进程退出函数:exit()和_exit()的区别(1)_exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核。(2)调用_exit函数时,其会关闭进程所有的文件描述符,清理内存以及其他一些内核清理函数,但不会刷新流(stdin, stdout, stderr ...). exit函数是在_exit..._linux结束进程可以用哪些函数,它们之间有何区别?

sqlserver55555_sqlserver把小数点后面多余的0去掉-程序员宅基地

文章浏览阅读134次。select 5000/10000.0 --想变成0.5select 5500/10000.0 --想变成0.55select 5550/10000.0 --想变成0.555select 5555/10000.0 --想变成0.5555其结果分别为:0.5000000 0.5500000 0.5550000 0.5555000一、如果想去掉数字5后面多余的0 ,需要转化一下:selec..._sql server 去小数 0

Angular6 和 RXJS6 的一些改动_angular6,requestoptions改成了什么-程序员宅基地

文章浏览阅读3.1k次。例一:import { Injectable } from '@angular/core';import { Observable } from 'rxjs';import { User } from "./model/User";import { map } from 'rxjs/operators';import { Http, Response, Headers, RequestOp..._angular6,requestoptions改成了什么

C++解析XML文件_c++ xml解析-程序员宅基地

文章浏览阅读7.9k次,点赞17次,收藏110次。C++读取XML文件_c++ xml解析

R语言使用caret包的train函数构建多元自适应回归样条(MARS)模型构建分类模型、trainControl函数设置交叉验证参数、自定义调优评估指标_多元自适应回归样条 r-程序员宅基地

文章浏览阅读235次。R语言使用caret包的train函数构建多元自适应回归样条(MARS)模型构建分类模型、trainControl函数设置交叉验证参数、自定义调优评估指标、tuneLength参数和tuneGrid参数超参数调优_多元自适应回归样条 r

Android ListView控件显示数据库中图片_安卓获取listview里的图片并显示-程序员宅基地

文章浏览阅读5.8k次。Android中ListView是比较常用的控件,但一直都觉得创建ListView步骤有点繁琐,故在此总结一下,方便查阅。程序效果是实现一个显示联系人的简单信息。使用ListView控件,数据有姓名,和照片,并加入点击事件响应。布局文件:

推荐文章

热门文章

相关标签