记录一个用来启动未注册的Activity的Hook

目录

1. 代码

2. 简单逻辑说明


1. 代码如下

public class HookApplication extends Application {
    private static final String TAG = "HookApplication";

    @Override
    public void onCreate() {
        super .onCreate();
        hookInstrumentation();
    }

    private void hookInstrumentation() {
        try {
            Field mMainThread = getBaseContext().getClass().getDeclaredField("mMainThread");
            mMainThread.setAccessible(true);
            Object o = mMainThread.get(getBaseContext());
            Field mInstrumentation = o.getClass().getDeclaredField("mInstrumentation");
            mInstrumentation.setAccessible(true);

            Instrumentation instrumentation = (Instrumentation) mInstrumentation.get(o);
            InstrumentationProxy proxy = new InstrumentationProxy(instrumentation);
            mInstrumentation.set(o, proxy);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static class InstrumentationProxy extends Instrumentation {
        protected Instrumentation instrumentation;

        public InstrumentationProxy(Instrumentation instrumentation) {
            this.instrumentation = instrumentation;
        }
        public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {

            Log.i(TAG, "proxy execStartActivity");

            // 带欺骗标志则用注入欺骗activity的ComponentName(即下方的MainActivity)
            String activityTag = intent.getStringExtra("isUnRegister");
            if(activityTag != null) {
                ComponentName realComponentName = intent.getComponent();
                intent.putExtra("realComponentName", realComponentName);

                ComponentName fakeComponentName = new ComponentName(MainActivity.class.getPackage().getName(), MainActivity.class.getName());
                intent.setComponent(fakeComponentName);
            }
            Class[] classes = new Class[]{Context.class, IBinder.class, IBinder.class, Activity.class, Intent.class, int.class, Bundle.class};
            try {
                Method method = getClass().getSuperclass().getDeclaredMethod("execStartActivity", classes);
                Log.i(TAG, "proxy execstartActivity Method:"+ method);
                if (method != null) {
                //注意这里的obj必须用原本的Instrumentation
                    return (ActivityResult) method.invoke(instrumentation, new Object[]{who, contextThread, token, target, intent, requestCode, options});
                }
                } catch (NoSuchMethodException | IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.getTargetException().printStackTrace();
                }
                return null;
            }
            public Activity newActivity(ClassLoader cl, String className, Intent intent)
                    throws InstantiationException, IllegalAccessException, ClassNotFoundException {
                Log.i(TAG, "proxy newActivity");

                String newClassName = className;
                String activityTag = intent.getStringExtra("isUnRegister");
                ComponentName componentName = intent.getParcelableExtra("realComponentName");
                if(activityTag != null && componentName != null) {
                    newClassName = componentName.getClassName();
                    intent.setComponent(componentName);
                }

                return instrumentation.newActivity(cl, newClassName, intent);
            }
        }
}

2. 简单逻辑说明

startActivity(Intent) 时会走android.app.Activity中的startActivityForResult,然后通过mInstrumentation的execStartActivity开始启动,

经过一系列操作后,在ActivityThread中handleLaunchActivity,然后调用mInstrumentation的newActivity获取activity实例。

so 只要重写下mInstrumentation的两个方法就可以简单实现免注册启动activity

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值