1. 程式人生 > >Android hook技術之小試牛刀

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

2.3)獲取當前應用的ActivityThread,並替換系統預設定義的mInstrumentation例項

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

2.4)在MyApplication的onCreate裡替換ActivityThread裡的mInstrumentation變數

  1. publicclass MyApplication extends Application {  
  2.     @Override
  3.     publicvoid 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類