Android hook技术之小试牛刀

一、了解Hook概念

Hook是钩子的意思。我们知道应用运行依赖系统各种各样的API。当某些API不能满足我们的要求时,如果想修改它的功能,使之能满足我们的要求。就要用到Hook技术。

在Android开发中,我们同样能利用Hook的原理让系统某些方法运行时,实际调用的是我们自己定义的方法,从而满足我们的要求。


二、利用java反射实现简单的Hook——将在Manifest中注册的MainActivity替换成没在Manifest中注册过的TestActivity。

2.1)新建一个Android项目,创建MainActivity和TestActivity,TestActivity不在AndroidManifest.xml中配置。

2.2)写一个InstrumentationHook继承系统的Instrumentation,并重写父类的newActivity方法


  1. public class InstrumentationHook extends Instrumentation {  
  2.   
  3.     @Override  
  4.     public Activity newActivity(Class clazz, Context context, IBinder token,  
  5.                                 Application application, Intent intent, ActivityInfo info,  
  6.                                 CharSequence title, Activity parent, String id,  
  7.                                 Object lastNonConfigurationInstance) throws InstantiationException,  
  8.             IllegalAccessException {  
  9.         Log.d(this" CustomInstrumentation#newActivity call 1");  
  10.         return super.newActivity(clazz, context, token, application, intent, info,  
  11.                 title, parent, id, lastNonConfigurationInstance);  
  12.     }  
  13.   
  14.     @Override  
  15.     public Activity newActivity(ClassLoader cl, String className, Intent intent)  
  16.             throws InstantiationException, IllegalAccessException,  
  17.             ClassNotFoundException {  
  18.         Log.d(this" CustomInstrumentation#newActivity call 3 parmas className:" + className + " intent:" + intent.toString());  
  19.         Activity activity = createActivity(intent);  
  20.         if (activity != null) {  
  21.             return activity;  
  22.         }  
  23.         return super.newActivity(cl, className, intent);  
  24.     }  
  25.   
  26.     /*可以在createActivity拦截替换某个activity,下面自是一个简单例子*/  
  27.     protected Activity createActivity(Intent intent) {  
  28.         String className = intent.getComponent().getClassName();  
  29.         Log.d(this"createActivity className=" + className);  
  30.         if ("hook.jason.com.androidhook.MainActivity".equals(className)) {  
  31.             try {  
  32.                 Classextends Activity> PluginActivity = (Classextends Activity>) Class  
  33.                         .forName("hook.jason.com.androidhook.TestActivity");  
  34.                 return PluginActivity.newInstance();  
  35.             } catch (Exception e) {  
  36.                 e.printStackTrace();  
  37.             }  
  38.         }  
  39.         return null;  
  40.     }  
  41. }  


2.3)获取当前应用的ActivityThread,并替换系统默认定义的mInstrumentation实例


[java]
  view plain  copy
  1. /** 
  2.  * Created by zeyu,Jia
  3.  */  
  4.   
  5. public class HookManager {  
  6.     static Object activityThreadInstance;  
  7.   
  8.     public static void init() throws ClassNotFoundException,  
  9.             NoSuchMethodException, IllegalAccessException,  
  10.             IllegalArgumentException, InvocationTargetException {  
  11.         Class activityThread = Class.forName("android.app.ActivityThread");  
  12.         Method currentActivityThread = activityThread  
  13.                 .getDeclaredMethod("currentActivityThread");  
  14.         activityThreadInstance = currentActivityThread.invoke(null);  
  15.     }  
  16.   
  17.     public static void injectInstrumentation() throws NoSuchFieldException,  
  18.             IllegalAccessException, IllegalArgumentException {  
  19.         Log.i(HookManager.class" start injectInstrumentation");  
  20.         Field field_instrumentation = activityThreadInstance.getClass()  
  21.                 .getDeclaredField("mInstrumentation");  
  22.         field_instrumentation.setAccessible(true);  
  23.         InstrumentationHook instrumentationHook = new InstrumentationHook();  
  24.         field_instrumentation.set(activityThreadInstance, instrumentationHook);  
  25.     }  
  26. }  


2.4)在MyApplication的onCreate里替换ActivityThread里的mInstrumentation变量

  1. public class MyApplication extends Application {  
  2.     @Override  
  3.     public void onCreate() {  
  4.         try {  
  5.             Log.d(this" onCreate starting init");  
  6.             HookManager.init();  
  7.             HookManager.injectInstrumentation();  
  8.         } catch (Exception e) {  
  9.             Log.d(this" onCreate e:" + e.toString());  
  10.         }  
  11.         super.onCreate();  
  12.     }  
  13. }  


2.5)运行后界面如下:


2.6)具体log如下:

03-18 17:28:55.621 436-436/hook.jason.com.androidhook D/AndroidHook: MyApplication :  onCreate starting init
03-18 17:28:55.623 436-436/hook.jason.com.androidhook I/AndroidHook: Class :  start injectInstrumentation
03-18 17:28:55.633 436-436/hook.jason.com.androidhook D/AndroidHook: InstrumentationHook :  CustomInstrumentation#newActivity call 3 parmas className:hook.jason.com.androidhook.MainActivity intent:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=hook.jason.com.androidhook/.MainActivity }
03-18 17:28:55.633 436-436/hook.jason.com.androidhook D/AndroidHook: InstrumentationHook : createActivity className=hook.jason.com.androidhook.MainActivity
03-18 17:28:55.674 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onCreate
03-18 17:28:55.752 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onResume
03-18 17:28:55.775 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onPause
03-18 17:28:55.789 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onAttachedToWindow
03-18 17:39:55.838 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onRestart
03-18 17:39:55.855 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onResume
03-18 17:40:26.044 436-436/hook.jason.com.androidhook D/AndroidHook: TestActivity : onPause

从log中可以看出MainActivity的onCreate方法根本没有运行,走的是没有配置的TestActivity类



你可能感兴趣的:(Android,插件化)