Introduction
A plug-in loading system similar to Xposed and LSPosed frameworks, which supports Java and Native Hook.
Examples
1.Hooking a Regular App
Preparation
- The target app to be hooked.
- A hook plugin APK.
- Use the apmt command in the terminal of a connected device to load the hook plugin.
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;//webview相关的暂时忽略
}
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
Transfer the hook plugin APK to the phone (in this example, to the SD card directory).
Add the plugin
When the message "add Patch:appdemo success" appears, it indicates the plugin has been successfully added.
You can also check whether the plugin was added successfully by running the command apmt patch list:
Run the target app, enable logcat, and verify the results:
The logs printed by the hook plugin can be observed, indicating that the hook was successful.
2.Hook SystemServer
Preparation
- A hook plugin APK.
- Use the apmt command in the terminal of a connected device to load the 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
Transfer the hook plugin APK to the phone (in this example, to the SD card directory).
Add the plugin
Note: Hook SystemServer -p needs to be specified as "android"
Restart the device, enable logcat, and verify the results:
The logs printed by the hook plugin can be observed, indicating that the hook was successful.
Noun introduction
1. Plugin Operation Commands
The framework uses the "apmtcommands" to operate plugins。
2.Plugins
Hook plugins are written by "customizing plugins" and loaded using the plugin operation commands.
apmt commands
Required Parameters
apmt patch
Basic Operations
1.Add a Patch Package
apmt patch add -n test -p com.armcloud.testapp -f /sdcard/test.apk
2.Delete a Patch Package
apmt patch del -n test
3.Query Patch Packages
apmt patch list
4.View Help Information
apmt patch help
Full Parameter List
Parameter | Description |
---|---|
-n | Plugin name |
-p | Package name of the app to which the plugin is applied |
-u | Download link when the plugin is obtained via URL |
-f | File path when using a local plugin |
Customizing Plugins
1. Hook a Regular App
- The entry class must be named: androidx.app.Entry
- The 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
- The entry class must be named: androidx.app.Entry
- The 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