Android Hook工具Cydia Substrate使用

Hook簡介:android

Hook就是鉤子,在安卓中,就是在事件傳送到終點前截獲並監控事件的傳輸,像個鉤子勾上事件同樣,而且可以在勾上事件時,處理一些本身特定的事件。shell


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.apkspa

而後,須要"Link Substrate Files"(鏈接本地的Substrate服務文件),這一步是須要Root權限的,鏈接後還須要重啓設備纔可以生效。操作系統

第二步:

下載使用Cydia Substrate庫(直接去官網下載)。下載完成後,將獲得的全部文件(不少的jar包與so庫),都拷貝到Android項目下的libs文件夾中,就能夠直接使用了。其中的substrate.h頭文件與lib文件夾下的so文件是提供在使用NDK(Native Development Kit,原生開發工具)進行原生Hook程序開發中的函數支持庫。

那麼Cydia Substrate怎麼用呢?

其實很簡單,Cydia Substrate提供了三個靜態的方法工具類,咱們只須要學會使用它就好。

一、MS.hookClassLoad   拿到指定Class載入時的通知

二、MS.hookMethod  使用一個Java方法去替換另外一個Java方法

三、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方法,並在其中注入咱們的廣告。

思路:

一、咱們根據某廣告平臺的規定,在咱們的AndroidManifest.xml文件中填入一些廣告相關的ID。

二、在AndroidManifest.xml文件中填寫一些使用Cydia Substrate相關的配置與權限。

三、聲明一個廣告的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);
                }
            }
        });
    }
}
相關文章
相關標籤/搜索