canyie/pine
GitHub: canyie/pine
基于 ART 运行时的动态 Java 方法钩子框架,可拦截和修改任意 Java 方法调用行为。
Stars: 1454 | Forks: 259
# Pine [](https://github.com/996icu/996.ICU/blob/master/LICENSE)
[中文版本](README_cn.md)
## 简介
Pine 是一个基于 ART 运行时动态 Java 方法钩子框架,可以拦截当前进程中的几乎所有 Java 方法调用。
目前支持 Android 4.4(仅 ART) ~ **15 Beta 4**,支持 thumb-2/arm64 架构。
关于其工作原理,请参阅这篇中文[文章](https://canyie.github.io/2020/04/27/dynamic-hooking-framework-on-art/)。
注意:对于使用 arm32/thumb-2 架构的 Android 6.0 设备,参数可能会出错;对于 Android 9.0+,Pine 将禁用隐藏 API 限制策略。
~~Pine 这个名字代表了一类以喹硫平和氯氮平为代表的抗精神病药物。它也是"Pine Is Not Epic"的首字母缩写。~~
## 使用说明
### 基本用法
[](https://repo1.maven.org/maven2/top/canyie/pine/core/)
在 build.gradle 中添加依赖(如下所示):
```
dependencies {
implementation 'top.canyie.pine:core:'
}
```
基本配置:
```
PineConfig.debug = true; // Do we need to print more detailed logs?
PineConfig.debuggable = BuildConfig.DEBUG; // Is this process debuggable?
```
示例 1:监控 Activity 的创建
```
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()");
}
});
```
示例 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:
```
Method checkThread = Class.forName("android.view.ViewRootImpl").getDeclaredMethod("checkThread");
Pine.hook(checkThread, MethodReplacement.DO_NOTHING);
```
### Xposed 支持
[](https://repo1.maven.org/maven2/top/canyie/pine/xposed/)
Pine 支持以 Xposed 风格钩取方法和加载 Xposed 模块。(仅支持 Java 方法钩取。使用不支持的功能(如资源钩取)的模块将无法工作。)
```
implementation 'top.canyie.pine:xposed:'
```
以 Xposed 风格直接钩取方法:
```
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);
```
注意:
1. 钩子仅在当前进程中生效。如果希望钩子在其他进程中生效,需要先将代码注入到这些进程中。这与我们无关。
2. 使用不支持的功能(如资源钩取或 XSharedPreferences)的模块将无法工作。
### 增强功能
[](https://repo1.maven.org/maven2/top/canyie/pine/enhances/)
结合 [Dobby](https://github.com/jmpews/Dobby),你可以使用一些增强功能:
```
implementation 'top.canyie.pine:enhances:'
```
- 延迟钩取(也称为待处理钩取)支持,无需立即初始化声明类即可钩取静态方法:
```
PineEnhances.enableDelayHook();
```
### ProGuard
如果你使用 Xposed 功能且需要在模块外部调用 Xposed API(例如调用 `PineXposed.loadModule()` 加载外部模块):
```
# 保留 Xposed APIs
-keep class de.robv.android.xposed.** { *; }
-keep class android.** { *; }
```
## 已知问题
- 可能与某些设备/系统不兼容。
- 由于 [#11](https://github.com/canyie/pine/issues/11) 的原因,我们强烈建议尽可能钩取并发较少的方法,例如:
```
public static void method() {
synchronized (sLock) {
methodLocked();
}
}
private static void methodLocked() {
// ...
}
```
在示例中,我们建议钩取 `methodLocked` 而不是 `method`。
- Pine 默认在初始化时禁用隐藏 API 策略。由于 ART 的一个 bug,如果一个线程在另一个线程正在调用列出类成员的 API 时更改隐藏 API 策略,可能会发生越界写入并导致崩溃。我们无法修复系统 bug,唯一的方法是在其他线程启动之前初始化我们的库以避免竞态条件。更多信息,请参阅 tiann/FreeReflection#60。
- 更多问题,请参阅 [issues](
标签:Android, Android安全, API接口, ART运行时, DSL, Java Hook, JS文件枚举, Method Hook, SSH蜜罐, Xposed, 云资产清单, 动态修改, 域名枚举, 方法钩子, 系统调修, 进程注入, 逆向工程