pine

Project Url: canyie/pine
Introduction: Dynamic java method hook framework on ART.
More: Author   ReportBugs   
Tags:

Download LICENSE

中文版本

Introduction

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) ~ 10.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.

Usage

Basic Usage

Add dependencies in build.gradle (like this):

dependencies {
    implementation 'top.canyie.pine:core:<version>'
}

Basic configuration:

PineConfig.debug = true; // Need to print more detailed log?
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);

Xposed Support

Download

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(moudlePath));

// 2. call all 'IXposedHookLoadPackage' callback
PineXposed.onPackageLoad(packageName, processName, appInfo, isFirstApp, classLoader);

Known issues

  • May not be compatible with all devices/systems.

  • When two or more threads enter the same hooked method at the same time, one thread will acquire the lock and the other thread will wait; but when the thread holding the lock has not released the lock, if art needs to suspend all threads , The thread will suspend execution when it reaches the checkpoint, and the thread that does not hold the lock will wait indefinitely, unable to reach the checkpoint, and eventually cause the suspension to time out and trigger runtime abort. So we recommend hooking methods with less concurrency as much as possible, for example: ```java public static void method() { synchronized (sLock) {

      methodLocked();
    

    } }

private static void methodLocked() { // ... } `` In the example, we recommend that the hook method ismethodLockedinstead ofmethod`.

Discussion

QQ Group:949888394

Credits

License

Pine Copyright (c) canyie

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

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

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools