Pine
Introduction
Pine is a dynamic java method hook framework on ART runtime, which can intercept almost all java method calls in the current process.
Currently it supports Android 4.4(ART only) ~ 13 with thumb-2/arm64 architecture.
About its working principle, you can refer to this Chinese article.
Note: For Android 6.0 devices with arm32/thumb-2 architectures, the arguments may be wrong; and for Android 9.0+, pine will disable the hidden api restriction policy.
Usage
Basic Usage
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 ui:
Method checkThread = Class.forName("android.view.ViewRootImpl").getDeclaredMethod("checkThread");
Pine.hook(checkThread, MethodReplacement.DO_NOTHING);
Xposed Support
Pine supports hooking methods in Xposed-style and loading Xposed modules. (Only java method hooking is supported. Modules using unsupported features like Resource-hooking won't work.)
implementation 'top.canyie.pine:xposed:<version>'
Directly 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);
Enhanced Features
With Dobby, you can use some enhanced features:
implementation 'top.canyie.pine:enhances:<version>'
- Delay hook (aka pending hook) support, hooking static methods without initializing its declaring class immediately:
PineEnhances.enableDelayHook();
Known issues
-
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 you to hook methodLocked
instead of method
.
- For more, see issues.
Discussion
QQ Group:949888394 Telegram Group: @DreamlandFramework
Credits
License
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