標籤:
Hook簡介:
Hook就是鉤子,在安卓中,就是在事件傳送到終點前截獲並監控事件的傳輸,像個鉤子勾上事件一樣,並且能夠在勾上事件時,處理一些自己特定的事件。
Cydia Substrate的官網定義:The powerful code modification platform behind Cydia.
Cydia Substrate是一個代碼修改平台,它可以修改任何主進程的代碼,不管是用Java還是C/C++(native代碼)編寫的。
註:Cydia Substrate架構對於inline Hook的操作目前還是存在一些bug,使用的時候可能會出現崩潰的現象,部分使用了國內定製的ROM的裝置在使用Cydia Substrate架構時會造成裝置無法重新啟動或無法Hook的現象。
使用Cydia Substrate的步驟:
第一步:
安裝Cydia Substrate架構Android本地服務
首先就是在Android裝置中安裝Cydia Substrate架構的本地服務應用substrate.apk
然後,需要"Link Substrate Files"(串連本地的Substrate服務檔案),這一步是需要Root許可權的,串連後還需要重啟裝置才能夠生效。
第二步:
下載使用Cydia Substrate庫(直接去官網下載)。下載完成後,將得到的所有檔案(很多的jar包與so庫),都拷貝到Android項目下的libs檔案夾中,就可以直接使用了。其中的substrate.h標頭檔與lib檔案夾下的so檔案是提供在使用NDK(Native Development Kit,原生開發工具)進行原生Hook程式開發中的函數支援庫。
那麼Cydia Substrate怎麼用呢?
其實很簡單,Cydia Substrate提供了三個靜態方法工具類,我們只需要學會使用它就好。
1、MS.hookClassLoad 拿到指定Class載入時的通知
2、MS.hookMethod 使用一個Java方法去替換另一個Java方法
3、MS.moveUnderClassLoader 使用不同的ClassLoader重載對象
具體說明如下:
/**
* Hook一個指定的Class
*
* @param name Class的包名+類名,如android.content.res.Resources
* @param hook 成功Hook一個Class後的回調
*/
void hookClassLoad(String name, MS.ClassLoadHook hook);
/**
* Hook一個指定的方法,並替換方法中的代碼
*
* @param _class Hook的calss
* @param member Hook class的方法參數
* @param hook 成功Hook方法後的回調
* @param old Hook前方法,類似C中的方法指標
*/
void hookMethod(Class _class, Member member, MS.MethodHook hook, MS.MethodPointer old);
/**
* Hook一個指定的方法,並替換方法中的代碼
*
* @param _class Hook的calss
* @param member Hook class的方法參數
* @param alteration
*/
void hookMethod(Class _class, Member member, MS.MethodAlteration alteration);
/**
* 使用一個ClassLoader重載一個對象
*
* @param loader 使用的ClassLoader
* @param object 帶重載的對象
* @return 重載後的對象
*/
<T> T moveUnderClassLoader(ClassLoader loader, T object);
如何Hook一個應用程式?
案例:我們針對Android作業系統的瀏覽器應用,Hook其首頁Activity的onCreate方法,並在其中注入我們的廣告。
思路:
1、我們根據某廣告平台的規定,在我們的AndroidManifest.xml檔案中填入一些廣告相關的ID。
2、在AndroidManifest.xml檔案中填寫一些使用Cydia Substrate相關的配置與許可權。
3、聲明一個廣告的Activity,並設定此Activity為背景透明的Activity。
實際操作:
其AndroidManifest.xml檔案的部分內容如下所示:
<!-- 廣告相關的許可權 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<!-- 加入substrate許可權 -->
<uses-permission android:name="cydia.permission.SUBSTRATE" />
<!-- 廣告相關參數 -->
<meta-data
android:name="APP_ID"
android:value="c62bd976138fa4f2ec853bb408bb38af" />
<meta-data
android:name="APP_PID"
android:value="DEFAULT" />
<!-- 聲明substrate的注入Main類 -->
<meta-data
android:name="com.saurik.substrate.main"
android:value="com.example.hookad.Main" />
<!-- 透明無動畫的廣告Activity -->
<activity
android:name="com.example.hookad.MainActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<!-- 廣告的action -->
<action android:name="com.example.hook.AD" />
</intent-filter>
</activity>
對於Cydia Substrate的主入口Main類,依照之前的步驟建立一個包含有initialize方法的Main類。
這裡我們使用adb shell下使用dumpsys activity命令找到瀏覽器首頁的Activity名稱為com.android.browser.BrowserActivity。
使用MS.hookClassLoad方法擷取了BrowserActivity之後再hook其onCreate方法,在其中啟動一個含有廣告的Activity。Main類的代碼如下所示:
public class Main { /** * substrate 初始化後的入口 */ static void initialize() { //Hook 瀏覽器的主Activity,BrowserActivity MS.hookClassLoad("com.android.browser.BrowserActivity", new MS.ClassLoadHook() { public void classLoaded(Class<?> resources) { Log.e("test", "com.android.browser.BrowserActivity"); // 擷取BrowserActivity的onCreate方法 Method onCreate; try { onCreate = resources.getMethod("onCreate", Bundle.class); } catch (NoSuchMethodException e) { onCreate = null; } if (onCreate != null) { final MS.MethodPointer old = new MS.MethodPointer(); // hook onCreate方法 MS.hookMethod(resources, onCreate, new MS.MethodHook() { public Object invoked(Object object, Object...args) throws Throwable { Log.e("test", "show ad"); // 執行Hook前的onCreate方法,保證瀏覽器正常啟動 Object result = old.invoke(object, args); // 沒有Context // 執行一個shell 啟動我們的廣告Activity CMD.run("am start -a com.example.hook.AD"); return result; } }, old); } } }); }}
Android Hook工具Cydia Substrate使用