Hook 原来是这么回事

一、安卓逆向工程

1、逆向工程:直接从成品推导出产品的设计原理。
2、逆向工程分类:
  • 静态分析:不执行程序情况下对程序进行分析

  • 动态分析:程序运行时对程序进行调试分析。Hook技术就属于动态分析。

二、Hook

1、被hook的对象被称为hook点
2、Hook点要稳定、不易变化(如静态变量、单例)
3、分类:根据不同的规定可以有不同的划分,这里主要讲java代码Hook 实现原理需要知识点:
  • 代理设计模式
  • 反射
  • 多态的理解(查找方法时,优先查找子类对象方法,找不到时再去查找父类对象中的方法。这点与双亲委派思想正好相反)

三、Hook startActivity

1、Hook Activity的startActivity方法

思路:startActivity 最终调用的是Instrumentation对象的execStartActivity方法。activity中有Instrumentation 的成员变量。我们搞个代理类代理Instrumentation 的execStartActivity 即可。然后把activity的成员Instrumentation 替换代理对象。这样执行startActivity 时会优先查找代理类的execStartActivity 方法。

2、Hook Context 的startActivity方法

context的startActivity方法是通过ContextImpl来实现的,最终表现为调用ActivityThread类的成员变量 Instrumentation来实现。所以代理 Instrumentation对象即可。这里我们把hook点换成 ActivityThread。即可。

3、实践
/**
 * Created by sunnyday on 2021/3/26 11:03
 */
public class InstrumentationProxy extends Instrumentation {
    private static final String TAG = "InstrumentationProxy";
    private static final String EXEC_START_ACTIVITY = "execStartActivity";
    private Instrumentation mInstrumentation;

    public InstrumentationProxy(Instrumentation mInstrumentation) {
        this.mInstrumentation = mInstrumentation;
    }

    /**
     * 代理 Instrumentation 的 execStartActivity方法。
     */
    @SuppressLint("DiscouragedPrivateApi")
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        Log.i(TAG, "execStartActivity () HooK 成功:" + who);
        try {
            Method clazz = Instrumentation.class.getDeclaredMethod(
                    EXEC_START_ACTIVITY,
                    Context.class,
                    IBinder.class,
                    IBinder.class,
                    Activity.class,
                    Intent.class,
                    int.class,
                    Bundle.class);
            return (ActivityResult) clazz.invoke(mInstrumentation, who, contextThread, token, target, intent, requestCode, options);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

    }

    /**
     * 工具类,替换Activity成员变量mInstrumentation。
     * 把Activity Instrumentation 类型成员变量替换为InstrumentationProxy代理类类型。
     *
     * @param activity 要操作的activity
     */
    public static void replaceActivityInstrumentation(Activity activity) {
        try {
            Field field = Activity.class.getDeclaredField("mInstrumentation");
            field.setAccessible(true);
            Instrumentation instrumentation = (Instrumentation) field.get(activity);
            Instrumentation instrumentationProxy = new InstrumentationProxy(instrumentation);
            field.set(activity, instrumentationProxy);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 工具类,替换ActivityThread 类成员变量mInstrumentation。
     * 把ActivityThread Instrumentation 类型成员变量替换为InstrumentationProxy代理类类型。
     */
    @SuppressLint("PrivateApi")
    public static void replaceContextInstrumentation() {
        try {
            // 获取ActivityThread的class对象
            Class<?> activityThreadClazz = Class.forName("android.app.ActivityThread");
            // 获取ActivityThread类的字段。sCurrentActivityThread(ActivityThread类型)
            Field sCurrentActivityThreadField = activityThreadClazz.getDeclaredField("sCurrentActivityThread");
            sCurrentActivityThreadField.setAccessible(true);
            // 获取类的静态字段值
            Object sCurrentActivityThread = sCurrentActivityThreadField.get(null);//ActivityThread 不对开发者开发,这里就使用Object吧。

            // 获取activityThread 内的instrumentation字段
            Field instrumentationField = activityThreadClazz.getDeclaredField("mInstrumentation");
            instrumentationField.setAccessible(true);
            Instrumentation instrumentation = (Instrumentation) instrumentationField.get(sCurrentActivityThread);

            // 替换字段值
            Instrumentation instrumentationProxy = new InstrumentationProxy(instrumentation);
            instrumentationField.set(sCurrentActivityThread, instrumentationProxy);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
//        1、Hook Activity的Instrumentation
//        InstrumentationProxy.replaceActivityInstrumentation(this);
//        this.startActivity(new Intent(this,SecActivity.class));

        //2、Hook Context的Instrumentation
        //安主P以上会抛出异常 程序不会crash(Instrumentation: Uninitialized ActivityThread, likely app-created Instrumentation, disabling AppComponentFactory)
        InstrumentationProxy.replaceContextInstrumentation();
        getApplicationContext().startActivity(new Intent(this,SecActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值