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.                 Class<? extends Activity> PluginActivity = (Class<? extends 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類



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章