2019年5月23日 星期四

Android Method Hook

使用IDA Pro動態分析Android APP,有時會因為前端的介面不能逾時太久,不然APP會瞬間崩潰,那麼也有可能會遇到偵測APP是否有被Debug,如果有,APP也會瞬間閃退,因此我們需要透過一種辦法,能不在動態分析APP的情況,也能獲取Method的傳入結果;也要能偽造回傳結果,這樣就能取代傳統的動態分析,因此就不會遇到上述的問題,不過要如何辦到既能獲取Method的傳入結果,也要能偽造回傳結果呢 ?

本篇是在探討關於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攔截位置


由於我想要Hook所有APP的Method,我們勢必要找到,在執行onCreate之前就要能夠Hook它。

從newActivity的Method能獲取APP的ClassLoader和className,這樣就能利用loadClass,將APP的Class載入進來,然後再Hook它的Method。



二、探討Android JAVA與JNI的互相調用


接下來是要了解Android是如何在JAVA和JNI的互相調用函式(Function)或Method,這樣我們也可以依樣畫葫蘆的仿效它的作法

在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。