zoukankan      html  css  js  c++  java
  • VirtualApp

    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());
  • 相关阅读:
    HTML转义字符
    网站项目开发经验总结
    SQL SERVER事务处理
    5种方法在mac系统修改hosts文件
    用MPMoviePlayerController做在线音乐播放
    UISearchBar的使用心得
    10 个免费的 C/C++ 集成开发环境
    TableView有些属性的修改只能在init里面
    UIScrollView的正确使用方法
    设置UIView阴影shadow 边框 边框颜色
  • 原文地址:https://www.cnblogs.com/zhiqixue/p/14386139.html
Copyright © 2011-2022 走看看