本篇是在探討關於Method Hook的技術,其實在Android平台上已經有現成的技術可使用了,就像是registerNatives,此API是可以將Method強制跳轉到JNI裡面的函式,這樣就能控制Method的輸入與輸出值了。
那麼還有另一個問題就是要如何獲取其他APP的Class呢?
常見的做法有2種,第1種是注入.so (JNI)到想要攔截Method的APP,不過有個缺點,它需要APP先執行,然後再攔截Method,因此有些Method可能早就執行完了;第2種是注入.so到Zygote,我們知道Zygote(主程式app_process)是啟動APP到記憶體上的主要功臣,因此可以藉由.so注入到Zygote就能控制所有APP的Class了。
一、探討全局Class攔截位置
從newActivity的Method能獲取APP的ClassLoader和className,這樣就能利用loadClass,將APP的Class載入進來,然後再Hook它的Method。
二、探討Android JAVA與JNI的互相調用
在Android裡面,dvmInvokeMethod是可以直接調用一個Method,其中它會利用dvmIsNativeMethod判斷是否為JNI程式碼,如果是,會直接運行method->nativeFunc的DalvikBridgeFunc函式(Function),DalvikBridgeFunc是調用JNI函式的一個橋接函式(Function),它必須處理JAVA相關的參數(Object轉jobject、String轉jstring等等),然後才會再調用JNI函式。
判斷是否為JNI函式,其實就只是一個ACC_NATIVE旗標。
dvmCallJNIMethod是DalvikBridgeFunc函式(Function),主要是為了轉換JAVA參數的型別和一些初始化,這樣就能支援JNI函式(Function)的參數。
1. 由於JAVA的第一個參數其實是this指標,那麼JAVA又有Static的Method,因此就需要分開處理。
2. 只要在JAVA是Object相關的型別,都需要利用addLocalReference函式(Function)來轉換成內部JNI的參數,那麼case ‘L’就是在JNI判斷Object相關型別的依據。
3. 都處理差不多後,會使用dvmPlatformInvoke調用JNI函式,其中method->insns就是指向JNI函式的起始位址。
最後將所有運行的APP的Class都列舉出來,這樣就能Hook它們的Method。