菜单

如何开发模块插件

模块插件使用场景

主要用于在云机中为指定应用注入自己的代码,对java层或native进行修改。

支持的功能

自动注入dex
自动注入so
内置java层Hook框架LspLant
内置native层Hook框架Dobby

模块示例下载

dplus_demo源码
dplus_demo模块

模块安装

使用Android Studio打开该项目。编译后得到模块app-debug.apk

将该文件上传自云机中,例如/sdcard/Download/app-debug.apk路径下

通过下面的命令可进行安装和查看

复制代码
//首先连接到云机
adb connect xx.xx.xx.xx

//进入云机终端
adb shell

//然后安装模块
dplus install patch:/sdcard/Download/app-debug.apk

//成功安装后可以查看模块
dplus dump

//可以通过模块name卸载删除模块
dplus uninstall dplus_demo

模块开发介绍

模块源码结构如下图

config.json文件用于配置模块

native-lib.cpp中实现dobby的hook例子

Entry.java是java层hook的入口

config配置说明

该文件主要用于描述模块,并且引导注入的,样例数据如下

复制代码
{
    "name": "dplus_demo",   //模块名称,卸载时使用
    "package":"com.example.dplus_demo",  //模块的包名
    "desc": "module",       //模块的描述
    "type": "user",         //模块的类型,主要为system和user。
    "libs": "libdplus_demo.so",  //要注入的so,可以不配置或者通过';'配置多条
    "pattern": [
        "com.android.settings"   //需要生效的包名
    ]
}

dobby例子

下面演示了如何简单的对openat函数进行hook输出

复制代码
int (*source_openat)(int fd, const char *path, int oflag, int mode) = nullptr;

int MyOpenAt(int fd, const char *pathname, int flags, int mode) {
    LOGI("MyOpenAt  pathname %s",pathname);
    return source_openat(fd, pathname, flags, mode);
}

void HookOpenAt() {
    //查找函数地址
    void *__openat =
            DobbySymbolResolver("libc.so", "__openat");

    if (__openat == nullptr) {
        LOGI("__openat null ");
        return;
    }

    LOGI("拿到 __openat 地址 ");
    
    //通过dobby替换原函数
    if (DobbyHook((void *) __openat,
                  (void *) MyOpenAt,
                  (void **) &source_openat) == 0) {
        LOGI("DobbyHook __openat sucess");
    }
}

jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {

    LOGI("Test JNI_OnLoad 开始加载");
    HookOpenAt();
    return JNI_VERSION_1_6;
}

java层例子

init函数是作为应用启动完后的一个入口点,在这里执行相关逻辑即可。LspLant相关的代码进行了简单的修改,所以部分类和函数不是原名称。

复制代码
public class Entry {

    public String TAG="demo_Entry";

    public void init(Application app){
        DPLog.i(TAG,"enter init");
        LSPHelpers.findAndHookMethod("java.util.HashMap", app.getClassLoader(), "put",Object.class,Object.class, new LSP_MethodH() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                Log.i(TAG,"enter HashMap.put key:"+param.args[0]+",value:"+param.args[1]);
            }

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Log.i(TAG,"leave HashMap.put");
            }
        });
    }

}

模块注入后的效果

该模块对应用Setting进行测试,关掉Setting应用重新打开时相关日志如下图

最近修改: 2025-10-20Powered by