Skip to content

Latest commit

 

History

History
175 lines (141 loc) · 6.41 KB

README_cn.md

File metadata and controls

175 lines (141 loc) · 6.41 KB

Pine Download LICENSE

简介

Pine是一个在虚拟机层面、以Java方法为粒度的运行时动态hook框架,它可以拦截本进程内几乎所有的java方法调用。

目前它支持Android 4.4(只支持ART)~ 11.0 与 thumb-2/arm64 指令集。

关于它的实现原理,可以参考本文

注:在Android 6.0 & 32位架构上,参数解析可能错误;另外在Android 9.0及以上,Pine会关闭系统的隐藏API限制策略。

使用

JCenter似乎已停止接收新的包,请添加以下行到您的根build.gradle中:

repositories {
    maven {
        url  "https://dl.bintray.com/canyie/pine"
    }
}

Bintray 和 JCenter 即将停止服务. 我们正在寻找一个替代品,但在这之前,请使用bintray。

基础使用

在 build.gradle 中添加如下依赖:

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

配置一些基础信息:

PineConfig.debug = true; // 是否debug,true会输出较详细log
PineConfig.debuggable = BuildConfig.DEBUG; // 该应用是否可调试,建议和配置文件中的值保持一致,否则会出现问题

然后就可以开始使用了。

几个例子:

例子1:监控Activity onCreate(注:仅做测试使用,如果你真的有这个需求更建议使用registerActivityLifecycleCallbacks()等接口)

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()");
    }
});

Pine.CallFrame就相当于Xposed的MethodHookParams。

例子2:拦截所有java线程的创建与销毁:

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);
    }
});

例子3:允许任何线程更改UI(注:绝对不建议在任何APP中使用):

Method checkThread = Class.forName("android.view.ViewRootImpl").getDeclaredMethod("checkThread");
Pine.hook(checkThread, MethodReplacement.DO_NOTHING);

Xposed支持

Download

Pine支持以Xposed风格hook方法和加载Xposed模块(注:目前不支持资源hook等)。

添加依赖:

implementation 'top.canyie.pine:xposed:<version>'

(注:Xposed支持需要依赖core)

然后你可以直接以Xposed风格hook方法:

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");
                    }
                });

也可以使用:

XposedBridge.hookMethod(target, callback);

也可以直接加载Xposed模块:

// 1. load modules
PineXposed.loadModule(new File(modulePath));

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

增强功能

借助Dobby, 你可以使用一些增强功能:

implementation 'top.canyie.pine:enhances:0.0.1'
  • Delay hook (也称为pending hook), hook静态方法无需立刻初始化它所在的类,只需要加入以下代码:
PineEnhances.enableDelayHook();

已知问题:

  • 可能不兼容部分设备/系统。

  • 由于#11,我们建议尽量hook并发较少的方法,举个例子:

public static void method() {
    synchronized (sLock) {
        methodLocked();
    }
}

private static void methodLocked() {
    // ...
}

在这个例子里,我们更建议hook methodLocked 而非 method

交流讨论

QQ群:949888394

致谢

许可证

Pine Copyright (c) canyie

AndroidELF Copyright (c) Swift Gan

Dobby Copyright (c) jmpews

根据 反996许可证 1.0版 (下文称“此许可证”)获得许可。

除非遵守此许可证,否则不得使用本Pine项目。

您可以在以下位置找到此许可证的副本:

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