Primarily used to inject custom code into specified applications in the cloud machine, allowing modifications to the Java layer or native layer.
Automatic injection of DEX files
Automatic injection of SO files
Built-in Java layer Hook framework: LspLant
Built-in native layer Hook framework: Dobby
Open the project in Android Studio. After compilation, obtain the module file app-debug.apk.
Upload this file to the cloud machine, for example, to the path /sdcard/Download/app-debug.apk.
Use the following commands for installation and viewing:
// First connect to the cloud machine
adb connect xx.xx.xx.xx
// Enter the cloud machine terminal
adb shell
// Then install the module
dplus install patch:/sdcard/Download/app-debug.apk
// After successful installation, view the module
dplus dump
// Uninstall and delete the module by module name
dplus uninstall dplus_demo
The module source code structure is as shown in the figure below.
The config.json file is used to configure the module.
native-lib.cpp implements examples of Dobby hooks.
Entry.java serves as the entry point for Java layer hooks.
This file is primarily used to describe the module and guide the injection process. Sample data is as follows:
{
"name": "dplus_demo", // Module name, used during uninstallation
"package":"com.example.dplus_demo", // Module package name
"desc": "module", // Module description
"type": "user", // Module type, mainly "system" or "user"
"libs": "libdplus_demo.so", // SO files to inject; can be omitted or configured with multiple entries separated by ';'
"pattern": [
"com.android.settings" // Package names where the module takes effect
]
}
The following demonstrates a simple hook on the openat function to output logs:
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() {
// Resolve function address
void *__openat =
DobbySymbolResolver("libc.so", "__openat");
if (__openat == nullptr) {
LOGI("__openat null ");
return;
}
LOGI("Got __openat address ");
// Replace original function with Dobby
if (DobbyHook((void *) __openat,
(void *) MyOpenAt,
(void **) &source_openat) == 0) {
LOGI("DobbyHook __openat success");
}
}
jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
LOGI("Test JNI_OnLoad starting load");
HookOpenAt();
return JNI_VERSION_1_6;
}
The init
function serves as an entry point after the application starts. Execute relevant logic here. The LspLant-related code has been slightly modified, so some classes and functions may not use their original names.
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");
}
});
}
}
This module tests the Settings application. When the Settings app is closed and reopened, the relevant logs are as shown in the figure below.