Android实现免安装插件(二)

2、 未在androidmanifest.xml中注册如何启动对应Activity

在启动Activity中出现ActivityNotFoundException有两种可能,一种是该Activity的应用未安装,一种是该Activity未在androidmanifest中申明。在插件化中,属于情况一。所以在startActivity中需启动Activity实际是系统中不能找到的,我们又该如何骗过系统,正常启动插件中的Activity呢?这里就要引入hook的机制了,我们用一个正常的Activity代替这个插件Activity骗过系统服务,然后再在自己的进程中拉起插件Activity,而这个Activity就像一个壳一样,帮助我们完成这次欺骗活动。
然后hook的地方需要注意了,在startActivity的流程中找一个单例,确保这个单例对象在每次startActivity都会被用上,而不会被其他对象代替。在这里,我们看到流程中ActivityManager里刚好有个单例(基于Android O框架)

public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

我们想办法把IActivityManagerSingleton.get() hook掉,来看下Singleton是什么

public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

到这里可以分析得到,我们只要把mInstance 替换掉就可以了。如下:

    public void hookActivityManager() {
        try {
            Class activityManager = Class.forName("android.app.ActivityManager");
            Field singleton = activityManager.getDeclaredField("IActivityManagerSingleton");
            singleton.setAccessible(true);
            Object object = singleton.get(null);
            Class single = Class.forName("android.util.Singleton");
            Field instance = single.getDeclaredField("mInstance");
            instance.setAccessible(true);
            Object am = instance.get(object);
            Class<?> IActivityInterface = Class.forName("android.app.IActivityManager");
            Object proxy = Proxy.newProxyInstance(mContext.getClassLoader(), new Class<?>[]{IActivityInterface}, new ActivityInvokeHanlder(am));
            instance.set(object, proxy);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

到这里虽然我们startActivity中虽然指定的是插件Activity,但是在流程中我们用一个壳Activity代替了,系统认为可以正常处理它。

    private class ActivityInvokeHanlder implements InvocationHandler {
        private Object mBase;

        public ActivityInvokeHanlder(Object object) {
            mBase = object;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("startActivity")) {
                for (int i = 0; i < args.length; i++) {
                    if (args[i] instanceof Intent) {
                        Intent intent = (Intent) args[i];
                        if (intent.getComponent() == null) {
                            break;
                        }
                        if (LoadDexUtils.PLUG_ACTIVITY_NAME[0].equals(intent.getComponent().getClassName())
                                || LoadDexUtils.PLUG_ACTIVITY_NAME[1].equals(intent.getComponent().getClassName())) {
                            Log.i(TAG, "invoke = " + intent.getComponent().getClassName());
                            String plugActivity = intent.getComponent().getClassName();
                            intent = new Intent(mContext, mForkActivity);
                            intent.putExtra(LoadDexUtils.EXTRA_PLUG_ACTIVITY, plugActivity);
                            args[i] = intent;
                        }
                    }
                }
            }
            return method.invoke(mBase, args);
        }
    }

到这里,我们开始传的intent对应Activity虽然是插件中的Activity,但是在把它交给系统之前,我们做了一个偷梁换柱的动作,告诉系统一个已经在androidmanifest中注册的Activity。最终系统经过检测,这是一个合法的Intent。

猜你喜欢

转载自blog.csdn.net/rhythmjay/article/details/80705438