一、什么是 Hook 技术
Hook 技术又叫做钩子函数,在系统没有调用该函数之前,钩子程序就先捕获该消息,钩子函数先得到控制权,这时钩子函数既可以加工处理,也可以强制结束消息的传递。可以理解位劫持。
被劫持的对象称为hook点,为了保证hook的稳定性,hook点一般选择容易找到并且不易变化的对象,静态变量、单例。
二、hook技术分类
根据语言 :
1)hook java 主要通过反射和代理实现,应用于在skd开发环境修改java代码
2)hook native 在ndk开发环境和系统开发环境修改native代码
根据进程划分:应用程序进程hook、全局hook
根据实现方式
1)通过反射和代理,只能hook当前进程
2)通过hook框架,如xposed,需要 root
这里主要实践Java hook,以hook startActivity为例:
//hook点
Instrumentation mInstrumentation;
@Override
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
&& options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity) null, intent, -1, options);
}
选择ActivityThread类的mInstrumentation作为hook点, 用我们那自己的代理mInstrumentation对象来替换hook点。
那就分为两步,1. 实现代理的mInstrumentation 2.替换hook点
1、实现代理的mInstrumentation
由于mInstrumentation的类型Instrumentation是一个类,不是接口,因此这里采用静态代理
public class ProxyInstrumentation extends Instrumentation {
private static final String TAG = "ProxyInstrumentation";
Instrumentation mBase;
public ProxyInstrumentation(Instrumentation mBase) {
this.mBase = mBase;
}
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
Log.d(TAG, " Hook before");
try {
Method execStartActivity = Instrumentation.class.getDeclaredMethod(
"execStartActivity",
Context.class, IBinder.class, IBinder.class, Activity.class,
Intent.class, int.class, Bundle.class);
execStartActivity.setAccessible(true);
return (ActivityResult) execStartActivity.invoke(mBase, who,
contextThread, token, target, intent, requestCode, options);
} catch (Exception e) {
throw new RuntimeException("do not support!");
}
}
}
2、替换hook点
public void replaceInstrumentation() throws Exception {
//先获取到当前的ActivityThread对象
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
currentActivityThreadMethod.setAccessible(true);
Object currentActivityThread = currentActivityThreadMethod.invoke(null);
// 拿到原始的 mInstrumentation字段
Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");
mInstrumentationField.setAccessible(true);
Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);
// 创建代理对象
Instrumentation evilInstrumentation = new ProxyInstrumentation(mInstrumentation);
//赋值,替换为代理类
mInstrumentationField.set(currentActivityThread, evilInstrumentation);
}
实现时在Activity的onCreate方法中使用replaceInstrumentation来替换即可。
网友评论