在 Android 中深入 Binder 拦截可以实现多种功能,例如虚拟化、测试验证、检测第三方 SDK 或模块系统服务调用访问情况、逆向分析应用底层服务接口调用实现以及第三方 ROM 扩展 framework 服务等。
现有的一种实现 Binder 拦截的方案是通过 Java 层的 aidl 接口代理来实时分析和拦截进程的 Binder 通信。借助于 Android 系统 Binder 服务接口设计的规范,上层的接口均继承于 IBinder。
具体实现步骤如下:
- 对于已经生成的 Binder 服务对象,需要在应用进程可参与实现逻辑之前找到并替换缓存的对象。例如,对于 AMS(ActivityManagerService),在 Android 8.0 之后的缓存如下:
收起
java
复制
// 获取要替换的对象 Object obj; if (Build.VERSION.SDK_INT < 26) { // <= 7.0 obj = ReflectUtils.getStaticFieldValue("android.app.ActivityManagerNative", "gDefault"); } else { // 8.0 <= obj = ReflectUtils.getStaticFieldValue("android.app.ActivityManager", "iActivityManagerSingleton"); } Object inst = ReflectUtils.getFieldValue(obj, "mInstance"); // 进行替换 ReflectUtils.setFieldValue(obj, "mInstance", createProxy(inst));
- 对于后续运行过程中才获取的 Binder 服务,则需要代理 ServiceManager。代理代码如下:
收起
java
复制
Class<?> cls = ReflectUtils.findClass("android.os.ServiceManager"); Object org = ReflectUtils.getStaticFieldValue(cls, "sServiceManager"); Object pxy = newCreateProxy(org); if (null!= pxy) { ReflectUtils.setStaticFieldValue(getGlobalClass(), "sServiceManager", pxy); }
这样每次在第一次访问该服务时,就会调用 iserviceManager 中的 getService 的方法,而该方法已经被代理拦截,通过参数就可以识别当前获取的是哪个服务。
在实际开发中,还需要根据具体需求进行更多的处理和优化,例如处理不同 Android 版本的差异、复杂的 Binder 通信数据等。同时,进行 Binder 拦截可能需要一定的系统权限,并且这种操作可能会违反 Android 的安全策略,因此在非必要情况下不建议进行此类操作。
请注意,对系统的底层机制进行拦截和修改可能会导致系统不稳定、应用异常,甚至违反设备的使用条款和服务协议。此外,这样的操作也可能会带来安全风险,并在某些情况下导致应用无法正常通过应用商店的审核或更新。在进行任何此类开发之前,请务必充分了解相关的风险和法律规定,并仅在合法和适当的环境中进行测试和实验。