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());