/pine

Dynamic java method hook framework on ART. Allowing you to change almost all java methods' behavior dynamically.

Primary LanguageJava

Pine LICENSE

中文版本

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

Download

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

Download

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

Download

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.

Discussion

QQ Group:949888394 Telegram Group: @DreamlandFramework

Credits

License

Pine Copyright (c) canyie

AndroidELF Copyright (c) Swift Gan

Dobby Copyright (c) jmpews

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

https://github.com/996icu/996.ICU/blob/master/LICENSE