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);
                }
            }
        });
    }
}
相关文章
相关标签/搜索