VirtualApp - 2 -2 InvocationStubManager注入 hook 详解

 

VirtualCore.startup(Context context) 中调用:

/**
  * hook 系统类
  * InvocationStubManager来完成对这个进程的系统服务的BinderProxy的hook
  * 依次完成InvocationStubManager的初始化和执行系统的注入;
  */
InvocationStubManager invocationStubManager = InvocationStubManager.getInstance();
invocationStubManager.init();
invocationStubManager.injectAll();

 

invocationStubManager.init();
把我们需要用到的系统 IInterface 的引用 反射 到 我们自定义类对于的 IInterface 属性中。
并且 对 IInterface 进行动态代理,得到 我们可以使用的 mProxyInterface 接口。

set1:通过反射:
      把需要代理注入 跟IPC有关的stub类,加入到Map集合中,并且忽略这些类中需要使用值的修饰符。
      把需要注入跟IPC有关的类 的成员属性的引用 进行反射 到 我们自定义的类中。
      主要在 RefClass.load(Class<?> mappingClass, String className) 中实现。
set2:通过注入代理:(主要注入跟 IInterface 有关的方法)
     对set1 反射出来的 IInterface 的变量 进行动态代理,代理到 mProxyInterface 接口类中。
     在动态代理的过程中,重写IInterface的 invoke() 方法里面,在实际调用 invoke() 方法之前 注入了 beforeCall() 方法;
     在 实际调用invoke() 后注入了 afterCall() 方法;
     (IInterface: Android系统中用于AIDL和IPC通信所使用的到的接口)

 

invocationStubManager.injectAll(); 
把反射出来需要用的IPC IInterface的变量 注入 对系统 一些 manager 和 service 中。
用stub替换系统中的管理类和服务类中对象的值。就完成了插桩操作。

把 invocationStubManager.init() 注入IInterface的代理类 的 引用 mProxyInterface,
通过反射,把mProxyInterface的引用 赋值给 app 运行过程中,系统其他类 需要用到的地方,
防止 有些系统 工具类 或者 服务类 的 成员属性 不是 我们自己写的代理类。
如果不需要反射 mProxyInterface 类,则替换某些服务类。

 

 


invocationStubManager.init(); 源码 详解:

 

invocationStubManager.init() 调用的是 invocationStubManager.injectInternal();

private void injectInternal() throws Throwable {
    // 这里注入其实就是完成Java层的hook操作,
    // 自身app当然不需要hook,服务进程需要管理应用因此需要hook AMS和PMS,
    // 而对于应用进程,则需要hook整个framework框架,保证所有调用重定向到VA的框架里。

    if (VirtualCore.get().isMainProcess()) {
        //是VA 应用的主进程, 进程名例如 io.virtualapp
        logger.w("injectInternal >> processType == MainProcess, 是VA 应用的主进程,return掉。不在注入任何hook");
        return;
    }
    if (VirtualCore.get().isServerProcess()) {
        logger.d("injectInternal >> processType == ServerProcess, 是VA 服务进程 >> 注入hook: ActivityManagerStub 和 PackageManagerStub");
        addInjector(new ActivityManagerStub());
        addInjector(new PackageManagerStub());
        return;
    }
    if (VirtualCore.get().isVAppProcess()) {
        logger.d("injectInternal >> processType == VAppProces, 是 copy App的今 >> 注入hook:  LibCoreStub(整个 framework),ActivityManagerStub 和 PackageManagerStub ");
        addInjector(new LibCoreStub());
        addInjector(new ActivityManagerStub());
        addInjector(new PackageManagerStub());
        addInjector(HCallbackStub.getDefault());
        addInjector(new ISmsStub());
        addInjector(new ISubStub());
        addInjector(new DropBoxManagerStub());
        addInjector(new NotificationManagerStub());
        addInjector(new LocationManagerStub());
        addInjector(new WindowManagerStub());
        addInjector(new ClipBoardStub());
        addInjector(new MountServiceStub());
        addInjector(new BackupManagerStub());
        addInjector(new TelephonyStub());
        addInjector(new TelephonyRegistryStub());
        addInjector(new PhoneSubInfoStub());
        addInjector(new PowerManagerStub());
        addInjector(new AppWidgetManagerStub());
        addInjector(new AccountManagerStub());
        addInjector(new AudioManagerStub());
        addInjector(new SearchManagerStub());
        addInjector(new ContentServiceStub());
        addInjector(new ConnectivityStub());

        //这边是 做不同版本的支持,还是 兼容 ????????????????  ZhiQi

        if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR2) {
            addInjector(new VibratorStub());
            addInjector(new WifiManagerStub());
            addInjector(new BluetoothStub());
            addInjector(new ContextHubServiceStub());
        }
        if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR1) {
            addInjector(new UserManagerStub());
        }

        if (Build.VERSION.SDK_INT >= JELLY_BEAN_MR1) {
            addInjector(new DisplayStub());
        }
        if (Build.VERSION.SDK_INT >= LOLLIPOP) {
            addInjector(new PersistentDataBlockServiceStub());
            addInjector(new InputMethodManagerStub());
            addInjector(new MmsStub());
            addInjector(new SessionManagerStub());
            addInjector(new JobServiceStub());
            addInjector(new RestrictionStub());
        }
        if (Build.VERSION.SDK_INT >= KITKAT) {
            addInjector(new AlarmManagerStub());
            addInjector(new AppOpsManagerStub());
            addInjector(new MediaRouterServiceStub());
        }
        if (Build.VERSION.SDK_INT >= LOLLIPOP_MR1) {
            addInjector(new GraphicsStatsStub());
            addInjector(new UsageStatsManagerStub());
        }
        if (Build.VERSION.SDK_INT >= M) {
            addInjector(new FingerprintManagerStub());
            addInjector(new NetworkManagementStub());
        }
        if (Build.VERSION.SDK_INT >= N) {
    addInjector(new WifiScannerStub());
    addInjector(new ShortcutServiceStub());
    addInjector(new DevicePolicyManagerStub());
    }
    if (Build.VERSION.SDK_INT >= 26) {
            addInjector(new AutoFillManagerStub());
        }
    }
}

 

业务逻辑理解,举例 : VirtualCore.get().isServerProcess() 如果是服务进程 ; 则 addInjector(new ActivityManagerStub());。

查看 ActivityManagerStub 源码:

@Inject(MethodProxies.class)
public class ActivityManagerStub extends MethodInvocationProxy<MethodInvocationStub<IInterface>> {

    public ActivityManagerStub() {
        //这边 传入到 MethodInvocationStub(T baseInterface) 的 参数值 主要是 各个系统类中,最为 IPC进程通信的 IInterface 的 变量。
        super(new MethodInvocationStub<>(ActivityManagerNative.getDefault.call()));
    }

    @Override
    public void inject() throws Throwable {
        //把自己的代理注入类 设置到 系统对于的隐藏属性中
        if (BuildCompat.isOreo()) {
            //Android Oreo(8.X)
            Object singleton = ActivityManagerOreo.IActivityManagerSingleton.get();
            Singleton.mInstance.set(singleton, getInvocationStub().getProxyInterface());
        } else {
            if (ActivityManagerNative.gDefault.type() == IActivityManager.TYPE) {
                ActivityManagerNative.gDefault.set(getInvocationStub().getProxyInterface());
            } else if (ActivityManagerNative.gDefault.type() == Singleton.TYPE) {
                Object gDefault = ActivityManagerNative.gDefault.get();
                Singleton.mInstance.set(gDefault, getInvocationStub().getProxyInterface());
            }
        }
        BinderInvocationStub hookAMBinder = new BinderInvocationStub(getInvocationStub().getBaseInterface());
        hookAMBinder.copyMethodProxies(getInvocationStub());
        ServiceManager.sCache.get().put(Context.ACTIVITY_SERVICE, hookAMBinder);
    }

    //...
}

 

1.1ActivityManagerNative.getDefault.call() 详解 :

public class ActivityManagerNative {
    public static Class<?> TYPE = RefClass.load(ActivityManagerNative.class, "android.app.ActivityManagerNative");
    public static RefStaticObject<Object> gDefault;
    public static RefStaticMethod<IInterface> getDefault;
}

 

1.2 RefClass.load(Class<?> mappingClass, String className) 详解:

    public static Class<?> load(Class<?> mappingClass, String className) {
        try {
            return load(mappingClass, Class.forName(className));
        } catch (Exception e) {
            return null;
        }
    }

 

 public static Class load(Class mappingClass, Class<?> realClass) {
        //set1: 遍历 Mirror 类的所有字段
        Field[] fields = mappingClass.getDeclaredFields();
        for (Field field : fields) {
            try {
                //如果是静态的成员属性。field.getModifiers() 是Java反射方法中,获得 修饰符的值,static 静态的值为 8.
                if (Modifier.isStatic(field.getModifiers())) {
                    //set2
                    Constructor<?> constructor = REF_TYPES.get(field.getType());
                    if (constructor != null) {
                       //set3 : constructor.newInstance(realClass, field)
                       //set4: field.set(null, value);
                        field.set(null, constructor.newInstance(realClass, field));
                    }
                }
            }
            catch (Exception e) {
                // Ignore
            }
        }
        return realClass;
    }

set1: 遍历 自定义mappingClass 类 的属性,

set2:从预设的  Map (REF_TYPES)中找到 RefXXXX 的构造器 constructor

  Constructor 构造方法,每个属性 或者 方法 在反射的时候,都是自己的一个类,所以可以用 Constructor构造类命名。

       例如:field.getType() 为 mirror.RefStaticMethod, 获得的 Constructor 就是 mirror.RefStaticMethod 的构造器。

set3: constructor.newInstance(realClass, field) : 主要作用把 自定义映射类 对于的 系统源码类的对应属性 的修饰符 忽略掉,方便之后使用。

       这边忽略的是 系统源码里面的属性

  举例 如果 constructor 为  mirror.RefStaticObject。

public class RefStaticObject<T> {
    private Field field;

    public RefStaticObject(Class<?> cls, Field field) throws NoSuchFieldException {
        this.field = cls.getDeclaredField(field.getName());
        this.field.setAccessible(true);
    }
    //...
}

 

set4: field.set(null, constructor.newInstance(realClass, field))

  把系统源码里面 对于的 属性值 赋值给 自定义类中的对应属性,如果是复杂数据类型,则意味着两者的 引用是同一个,访问的是同一个内存数据

 


 

 

    public static Class load(Class mappingClass, Class<?> realClass) {
        /**
         * 遍历 自定义mappingClass 类 的属性,
         * 把需要的静态属性,在对应的系统类中,忽略掉 修饰符。
         * 并且通过系统对于类的方法,实例化系统对象。
         * 并且把这些实例化的系统对象的值或者引用,赋值给 自定义类mappingClass对于的属性。
         * 方便我们通过自定义类mappingClass 来使用获取 系统运行中 对于的值。
         *
         * constructor.newInstance(realClass, field) 通过静态代理,得到一个新的代理类。(constructor == mappingConstructor)
         * 这边最后是 field.set(obj,value) ; 进行赋值。 (这里的field.set() == mappingField.set() )
         * 把系统对于的区域值/引用 赋值 给 自定义的 mappingClass。 方便自己通过 自定义的mappingClass 来或许系统运行时候对应的值。
         *
         *          * 最后调用的话 MirrorClass.mirrorField.get(instance),MirrorClass.mirrorField.set(instance),就相当于直接调用 framework 层的隐藏字段了。
         *          * 自定义 mappingClass 类中 所有的成员属性,除了 TYPE 外,其他的属性都在 realClass需要注入的系统类中。
         */

        //set1: 遍历 Mirror包下 mappingClass 类的所有字段
        Field[] fields = mappingClass.getDeclaredFields();
//        Log.d("ZhiQiConstructor","mappingClass "+mappingClass.getName());
        for (Field field : fields) {
            try {
                //set2 如果是静态的成员属性。field.getModifiers() 是Java反射方法中,获得 修饰符的值,static 静态的值为 8.
                if (Modifier.isStatic(field.getModifiers())) {
//                    Log.d("ZhiQiConstructor","field "+field.getName());
                    /**
                     * set3:从预设的  Map (REF_TYPES)中找到 RefXXXX 的构造器 constructor
                     * Constructor 构造方法,每个属性 或者 方法 在反射的时候,都是自己的一个类,所以可以用 Constructor构造类命名。
                     */
                    Constructor<?> constructor = REF_TYPES.get(field.getType());
                    if (constructor != null) {
                        /**
                         *
                         *     newInstance() 实例化对象。
                         *
                         * 由于Constructor<?> constructor 中, <?> 代表的class 是值 mirror.RefObject 或者 mirror.RefMethod 等
                         * 所以 constructor.newInstance(Class<?> cls, Field field) 是调用的 mirror.RefObject(Class<?> cls, Field field)  方法
                         * 所以 constructor.newInstance(realClass, field) 是获得Andorid系统的类,然后 忽略 field 的修饰符。 以便之后修改值。并返回 Andorid系统的类
                         *
                         *          如果 type 是 RefStaticObject mirror.RefStaticObject RefStaticObject(Class<?> cls, Field field)
                         *          如果 type 是 RefStaticMethod 那么调用的是 mirror.RefStaticMethod
                         * 以 : mirror.android.app.ActivityManagerNative 为例子
                         * 这边是把自己写的所有 Fields 成员属性
                         * 例如 field = TYPE   (其中 getType : java.lang.Class)
                         *     field = gDefault (其中 getType : mirror.RefStaticObject;   constructor: mirror.RefStaticObject)
                         *     field = getDefault (其中 getType : mirror.RefStaticMethod;   constructor: mirror.RefStaticMethod)
                         *
                         *  newInstance 是把 自定义的 field 反射赋值给 对应的系统类 realClass: android.app.ActivityManagerNative 中。
                         *  这边写的作用是,自己对于写的field hook了 系统的对应的 field。
                         *
                         * field.setset(Object obj, Object value): hook 的方法。
                         *    让自己的field 代理 系统类 realClass 对于的 区域。
                         *    让自己定义的field 持有 系统类对于区域的引用,或者 把系统类对于的值 赋值给 自定义的field
                         */

                        field.set(null, constructor.newInstance(realClass, field));
                        //constructor.newInstance(realClass, field) 构建代理对象。(通过静态代理)
                        //      把自定义代理的field 注入到 系统的realClass中,得到一个新的代理对象。
                        //field.set(Object obj, Object value) 通过反射,替换/赋值。 让自己写的属性 持有 系统类的对应的引用
                        //通过反射注入业务层自己实现的AppInstrumentation了。
                        //因为代理的这些方法在底层,所以需要用到反射
                    }
                }
            }
            catch (Exception e) {
                // Ignore
            }
        }
        return realClass;
    }

 


 

2.2 new MethodInvocationStub<>(ActivityManagerNative.getDefault.call()) 详解

通过动态代理,把 ActivityManagerNative.getDefault.call() 反射出来的 IInterface接口,代理到 mProxyInterface 中,

    public MethodInvocationStub(T baseInterface, Class<?>... proxyInterfaces) {
        this.mBaseInterface = baseInterface;
        if (baseInterface != null) {
            if (proxyInterfaces == null) {
                //如果没有设置要代理的IInterface 接口,
                // 则获得 baseInterface 这个接口对象 所有实现的接口,以及递归baseInterface父类(基类)所实现的所有接口。
                proxyInterfaces = MethodParameterUtils.getAllInterface(baseInterface.getClass());
            }
            /**
             * 通过Proxy获得动态代理对象: Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
             *      loader: 用哪个类加载器去加载代理对象
             *      interfaces:动态代理类需要实现的接口
             *      h:动态代理方法在执行时,会调用h里面的invoke方法去执行。
             *          我们会看到 HookInvocationHandler() 里面重写了 invoke() 方法。
             *          并且 HookInvocationHandler() invoke() 方法里面,在实际调用 invoke() 方法之前 注入了 beforeCall() 方法;
             *          在 实际调用invoke() 后注入了 afterCall() 方法;
             *
             *  用 Proxy.newProxyInstance() 实例化代理类,并在客户端代码中直接使用。
             */
            mProxyInterface = (T) Proxy.newProxyInstance(baseInterface.getClass().getClassLoader(), proxyInterfaces, new HookInvocationHandler());
        } else {
            VLog.d(TAG, "Unable to build HookDelegate: %s.", getIdentityName());
        }
    }

 

mProxyInterface 的作用是:

在 invocationStubManager.injectAll() 里面,各个加载进来需要的类,在 执行 inject() 方法的时候,又 反射设置到 各自的对应的系统服务里面。

例如 

NotificationManager.sService.set(getInvocationStub().getProxyInterface());

 

posted @ 2021-02-07 17:56  梦话四叶  阅读(550)  评论(0编辑  收藏  举报