Pine is a dynamic java method hook framework on ART runtime, it can intercept almost all java method calls in this process.
Currently it supports Android 4.4(ART only) ~ 11.0 with thumb-2/arm64 architecture.
About its working principle, you can refer to this Chinese article.
Note: For Android 6.0 and 32-bit mode, the arguments may be wrong; and for Android 9.0+, pine will disable the hidden api restriction policy.
JCenter seems to have stopped receiving new packages. Please add the following line to your root build.gradle:
repositories {
maven {
url "https://dl.bintray.com/canyie/pine"
}
}
Bintray and JCenter will be sunset. We are looking for an alternative; but before that, please use bintray.
Add dependencies in build.gradle (like this):
dependencies {
implementation 'top.canyie.pine:core:<version>'
}
Basic configuration:
PineConfig.debug = true; // Do we need to print more detailed logs?
PineConfig.debuggable = BuildConfig.DEBUG; // Is this process debuggable?
Example 1: monitor the creation of activities
Pine.hook(Activity.class.getDeclaredMethod("onCreate", Bundle.class), new MethodHook() {
@Override public void beforeCall(Pine.CallFrame callFrame) {
Log.i(TAG, "Before " + callFrame.thisObject + " onCreate()");
}
@Override public void afterCall(Pine.CallFrame callFrame) {
Log.i(TAG, "After " + callFrame.thisObject + " onCreate()");
}
});
Example 2: monitor the creation and destroy of all java threads
final MethodHook runHook = new MethodHook() {
@Override public void beforeCall(Pine.CallFrame callFrame) throws Throwable {
Log.i(TAG, "Thread " + callFrame.thisObject + " started...");
}
@Override public void afterCall(Pine.CallFrame callFrame) throws Throwable {
Log.i(TAG, "Thread " + callFrame.thisObject + " exit...");
}
};
Pine.hook(Thread.class.getDeclaredMethod("start"), new MethodHook() {
@Override public void beforeCall(Pine.CallFrame callFrame) {
Pine.hook(ReflectionHelper.getMethod(callFrame.thisObject.getClass(), "run"), runHook);
}
});
Example 3: force allow any threads to modify the ui:
Method checkThread = Class.forName("android.view.ViewRootImpl").getDeclaredMethod("checkThread");
Pine.hook(checkThread, MethodReplacement.DO_NOTHING);
Pine supports hooking methods in Xposed-style and loading Xposd modules. (Only supports java method hook now.)
implementation 'top.canyie.pine:xposed:<version>'
Direct hook methods in Xposed-style:
XposedHelpers.findAndHookMethod(TextView.class, "setText",
CharSequence.class, TextView.BufferType.class, boolean.class, int.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.e(TAG, "Before TextView.setText");
param.args[0] = "hooked";
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Log.e(TAG, "After TextView.setText");
}
});
or like this:
XposedBridge.hookMethod(target, callback);
and you can load xposed modules (resources hook is not supported now):
// 1. load modules
PineXposed.loadModule(new File(modulePath));
// 2. call all 'IXposedHookLoadPackage' callback
PineXposed.onPackageLoad(packageName, processName, appInfo, isFirstApp, classLoader);
With Dobby, you can use some enhancements of Pine:
implementation 'top.canyie.pine:enhances:0.0.1'
- Delay hook (aka pending hook) support, hooking static methods without initialize its declaring class now:
PineEnhances.enableDelayHook();
-
May not be compatible with some devices/systems.
-
Due to #11, we recommend hooking methods with less concurrency as much as possible, for example:
public static void method() {
synchronized (sLock) {
methodLocked();
}
}
private static void methodLocked() {
// ...
}
In the example, we recommend that the hook method is methodLocked
instead of method
.
- For more, see issues.
AndroidELF Copyright (c) Swift Gan
Licensed under the Anti 996 License, Version 1.0 (the "License");
you may not use this "Pine" project except in compliance with the License.
You may obtain a copy of the License at