代理Hook
来源:互联网 发布:休斯顿国际电影节知乎 编辑:程序博客网 时间:2024/06/02 02:15
【本人也是小白一个,如有错误欢迎大家指出,本文是个人理解所得。】
什么是Hook呢?
Hook的英文含义是钩子。你可以这么理解用钩子把要Hook的对象勾过来,然后再把我们的替换对象送回去。Hook其实就是把原来对象的替换成我们仿造的对象,替换完成为所欲为。还有一点就是,必须拿到当前对象
里的某个属性进行Hook,否则你的hook是失败的,没有意义的。(注意是当前对象)
Hook点
所谓hook点就是你可以实现替换需求的某个对象。
Hook点怎么找呢?
总结一下就是:容易找又不容易变的对象 被static、final修饰的变量和单例
:在一个进程之内,静态变量和单例变量
是相对不容易发生变化的,因此非常容易定位,而普通的对象则要么无法标志,要么容易改变。我们根据这个原则找到所谓的Hook点。 有这么一句话“Hook的越早越好”为什么这么说呢?因为可以避免产生一些bug,Hook早的话,一些其他对本对象的操作或者本对象对其他的操作都是我们hook以后的对象了。不会产生一些莫名其妙的问题。
Hook例子
【本示例代码的Android版本是19】【注意有的ROM改写了系统源码可能Hook失败】
我们都知道Android系统有两个startActivity()方法,第一个是Context的startActivity()方法,第二个是Activity的startActivity()方法。
1、Hook Context类的startActivity()方法。
Context的startActivity()方法具体实现实在ContextImpl
类中,
// code@Overridepublic void startActivity(Intent intent, Bundle options) { warnIfCallingFromSystemProcess(); if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { 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);}
重点在这里:mMainThread.getInstrumentation().execStartActivity(…),由此可知startActivity()实际上是调用的Instrumentation
类中的execStartActivity()
方法。
请注意mMainThread
属性,他是ActivityThread
的实例,而ActivityThread 实际上是主线程,主线程只有一个,所以Hook他十分合适。而且ActivityThread类中还有currentActivityThread()
方法,可以获得当前的ActivityThread对象。
请看代码:
public static void hookStartActivity_context() { try { // 先获取到当前的ActivityThread对象 Class<?> activityThreadClass = Class.forName("android.app.ActivityThread"); Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread"); currentActivityThreadMethod.setAccessible(true); //currentActivityThread是一个static函数所以可以直接invoke,不需要带实例参数 // 当前的currentActivityThread对象 Object currentActivityThread = currentActivityThreadMethod.invoke(null); // 原始的 mInstrumentation字段 Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation"); mInstrumentationField.setAccessible(true); // 得到当前currentActivityThread对象的mInstrumentation对象 Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread); // 创建代理对象 InstrumentationProxy instrumentationProxy = new InstrumentationProxy(mInstrumentation); // 将得到当前currentActivityThread对象中的mInstrumentation对象替换为我们的代理对象 mInstrumentationField.set(currentActivityThread, instrumentationProxy); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); }}
在Activity的attachBaseContext(…)方法中调用这个方法
@Overrideprotected void attachBaseContext(Context newBase) { super.attachBaseContext(newBase); HookHelper.hookStartActivity_context();}
然后启动一个Activity
getApplicationContext().startActivity(new Intent(this, Main2Activity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));因为上面的startActivity()方法里有if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {...}如果不addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),就会进入这个if方法体里面的代码,会报错。具体请看一下源码。
2、Hook Activity类的startActivity()方法。
找源码得知:
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, child, intent, requestCode, options);
最终起作用的是这句话,那么我们HookActivity类中的mInstrumentation
属性。
/** * @param activity:当前的Activity */public static void hookStartActivity_activity(Activity activity) { try { Class clazz = Class.forName("android.app.Activity"); // 得到Activity类中的mInstrumentation字段 Field mInstrumentation_Field = clazz.getDeclaredField("mInstrumentation"); mInstrumentation_Field.setAccessible(true); // 得到当前Activity对象的mInstrumentation属性 Instrumentation instrumentation = (Instrumentation) mInstrumentation_Field.get(activity); // 创建代理类 InstrumentationProxy instrumentationProxy = new InstrumentationProxy(instrumentation); // 替换 mInstrumentation_Field.set(activity, instrumentationProxy); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }}
因为据查看源码得知Activity的mInstrumentation
属性是在attachBaseContext(…)方法之后赋值的,因此就不可以在attachBaseContext()方法里Hook,所以我这次是在onCreate(…)方法里Hook。
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 调用Hook方法 HookHelper.hookStartActivity_activity(this); setContentView(R.layout.activity_main2); initView();}
然后启动一个Activity进行测试。
startActivity(new Intent(this, Main2Activity.class));
***下面贴出InstrumentationProxy的代码:
public class InstrumentationProxy extends Instrumentation { private static final String TAG = "InstrumentationProxy"; private Object obj; // 原来的对象 public InstrumentationProxy(Object obj) { this.obj = obj; } public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { Toast.makeText(who, "hook success!", Toast.LENGTH_SHORT).show(); // Hook之前, 打印个日志! Log.d(TAG, "\n执行了startActivity, 参数如下: \n" + "who = [" + who + "], " + "\ncontextThread = [" + contextThread + "], \ntoken = [" + token + "], " + "\ntarget = [" + target + "], \nintent = [" + intent + "], \nrequestCode = [" + requestCode + "], \noptions = [" + options + "]"); try { Method method = Instrumentation.class.getDeclaredMethod("execStartActivity", Context.class, IBinder.class, IBinder.class, Activity.class, Intent.class, int.class, Bundle.class); return (ActivityResult) method.invoke(obj, who, contextThread, token, target, intent, requestCode, options); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }}
参考文章:http://weishu.me/2016/01/28/understand-plugin-framework-proxy-hook/
- 代理Hook
- hook+android动态代理
- Android插件化开发-hook动态代理
- Android插件化开发-hook动态代理
- Android 插件之Hook机制动态代理
- 动态代理实现方法以及对象HooK
- 360 DroidPlugin框架 Hook代理的实现方式
- 【Android】Android动态代理为SurfaceHolder添加Hook
- Android 插件化原理----Hook机制之动态代理
- 插件化开发---Hook之动态代理方式
- Android动态代理实践之Hook系统剪切板服务
- 动态代理hook自己进程的startActivity方法
- hook
- HOOK
- hook
- Hook
- Hook
- hook
- BigDecimal用法之计算等额本金和等额本息
- SPSS:T检验、方差分析、非参检验、卡方检验的使用要求和适用场景
- 浅析Fragment中startActivityForResult()与getActivity().startActivityForResult()的异同
- MCWebBridgeNative ,webview内容与本地交互,有非常非常爽的功能 (附 源码)
- RabbitMQ案例七之RPC远程过程调用
- 代理Hook
- React Native 中遇到的问题
- Mysql-Client编码问题
- PHP基础补全系列:异常处理
- httpClient 绕证书
- HTML初探
- 第一节 javascript的简史
- 初学构建小项目之仓库管理系统货物管理功能实现(四)
- 什么时候需要重写equals方法?为什么重写equals方法,一定要重写HashCode方法?