Introduction
A plugin loading system similar to Xposed and LSPosed frameworks, supporting both Java and Native Hook.
Examples
1. Hook Regular Apps
Preparation
- Target app to be hooked
- Hook plugin APK
- Connect to device terminal and execute apmt command to load Hook plugin (execute "vu" command to switch to root environment before running apmt command)
Target App Content
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("test");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
Log.d("___TestApp___", "call onCreate");
Log.d("___TestApp___", "call stringFromJNI(\"haha\") return:" + stringFromJNI("haha"));
Log.d("___TestApp___", "call add(10, 5) return:" + add(10, 5));
Log.d("___TestApp___", "call add(1, 5) return:" + add(1, 5));
}
public native String stringFromJNI(String str);
public native int add(int a, int b);
}
Hook Plugin Content
public class Entry {
private static final String TAG = "___HKAPP___";
private static Context globalContext;
public static void appMain(ClassLoader loader, Context context, String appClass, String pkg, String process) {
Log.d(TAG, "appClass=" + appClass + ", filesDir=" + context.getFilesDir() + ", pid=" + Process.myPid() + ", process=" + process);
if (process.contains("sandboxed_process")) {
return;//temporarily ignore webview related processes
}
if (pkg.equals("com.armcloud.testapp")) {
try {
Log.d(TAG, "do hookTestApp");
Class<?> MainActivity = loader.loadClass("com.armcloud.testapp.MainActivity");
XSHelpers.findAndHookMethod(MainActivity, "stringFromJNI", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d(TAG, "call MainActivity->stringFromJNI arg=" + param.args[0]);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Log.d(TAG, "call stringFromJNI return:" + param.getResult());
param.setResult("byebye");
}
});
// android.app.Activity
XSHelpers.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d(TAG, "call MainActivity->onCreate:" + param.args[0]);
}
});
Log.d(TAG, "exit hookTestApp");
} catch (Exception e) {
Log.d(TAG, "hookTestApp failed:\n" + Log.getStackTraceString(e));
}
}
}
}
Execute apmt Command to Load Plugin
Import the Hook plugin APK to the phone (here imported to SD card path)
Add plugin
The message "add Patch:appdemo success" indicates successful plugin addition.
You can also use "apmt patch list" to check if the plugin was added successfully:

Run the target app, enable logcat, and verify results:


You can see the logs printed by the hook plugin, indicating successful hooking.
2. Hook SystemServer
Preparation
- Hook plugin APK
- Connect to device terminal and execute apmt command to load Hook plugin
Hook Plugin Content
public class Entry {
private static final String TAG = "___HK_SysServer___";
public static void systemMain(ClassLoader classLoader, String pkg, String processName) {
doHook(classLoader);
}
private static void doHook(ClassLoader classLoader) {
try {
@SuppressLint("PrivateApi")
Class<?> timingsTraceAndSlog = classLoader.loadClass("com.android.server.utils.TimingsTraceAndSlog");
XSHelpers.findAndHookMethod("com.android.server.SystemServer", classLoader, "startBootstrapServices",
timingsTraceAndSlog, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d(TAG, "before call startBootstrapServices");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Log.d(TAG, "after call startBootstrapServices");
}
});
Log.d(TAG, "load system hook ok");
} catch (Exception ex) {
ex.printStackTrace();
Log.d(TAG, "doHook failed:" + Log.getStackTraceString(ex));
}
}
}
Execute apmt Command to Load Plugin
Import the Hook plugin APK to the phone (here imported to SD card path)

Add plugin
Note: For hooking SystemServer, the -p parameter must be specified as "android"

Restart the device, enable logcat, and verify results:

You can see the logs printed by the hook plugin, indicating successful hooking.
Terminology
1. Plugin Operation Commands
This framework uses "apmt command" to operate plugins.
2. Plugins
Write Hook plugins through "Custom Plugins" and load plugins using plugin operation commands.
apmt Command
Description
The apmt command only needs to be executed once. After the plugin is successfully added, it will take effect every time the app starts.
Required Parameters
apmt patch
Basic Operations
1. Add Patch Package
apmt patch add -n test -p com.armcloud.testapp -f /sdcard/test.apk
2. Delete Patch Package
apmt patch del -n test
3. Query Patch Package
apmt patch list
4. View Help Information
apmt patch help
All Parameters
| Parameter | Description |
|---|---|
| -n | Plugin name |
| -p | Package name of the app to apply the plugin to |
| -u | Download URL when downloading plugin via URL |
| -f | Plugin file path when using local plugin |
Custom Plugins
1. Hook Regular Apps

- Entry class must be named: androidx.app.Entry
- Entry method must be named: public static void appMain( ClassLoader loader, //class loader Context context, //context String appClass, //package name String process //process name )
2. Hook SystemServer

- Entry class must be named: androidx.app.Entry
- Entry method must be named: public static void systemMain( ClassLoader classLoader, //class loader String pkg, //package name, default is android String processName //process name )
Demo Download
Click to download ArmCloudXposeDemo