写点什么

【干货篇】Android 各版本拦截进程对 AMS 的请求实战,移动互联网开发技术就业前景

用户头像
Android架构
关注
发布于: 刚刚

} catch (e: Exception) {


e.printStackTrace()


}


}


// 即 IActivityManagerSingleton 实例


protected abstract fun getHookObj(): Any?


// 即 mInstance


protected abstract fun getHookField(): Field?


// 即 am


abstract fun getTarget(): Any?


// 接口,用来创建 Proxy


abstract fun getInterfaces(): Array<Class<*>>


}


在 Android P 平台上的实现如下,具体看注释:


class AmsPHooker : AmsHooker() {


override fun getHookObj(): Any? {


val amClass = ReflectUtils.getClass("android.app.ActivityManager")


// 拿到 IActivityManagerSingleton 属性


return ReflectUtils.readStaticField(amClass, "IActivityManagerSingleton")


}


override fun getHookField(): Field? {


// 获取 mInstance Field


return ReflectUtils.getField(ReflectUtils.getClass("android.util.Singleton"), "mInstance")


}


override fun getTarget(): Any? {


// ActivityManager.getService()返回 am


return ReflectUtils.getClass("android.app.ActivityManager").getDeclar


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


edMethod("getService").invoke(null)


}


// 获取 interfaces,用来创建动态代理


override fun getInterfaces(): Array<Class<*>> {


return arrayOf(ReflectUtils.getClass("android.app.IActivityManager"))


}


}


接下来创建代理类(代码有删减):


public class AMSProxy implements InvocationHandler {


private AmsHooker hooker; // 根据不同 Android 平台返回不同实现


private Object origAm; // 原有 am 对象


private boolean ensureInit() {


// ...


hooker = getHooker();


origAm = hooker.getTarget();


}


private AmsHooker getHooker() {


if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {


return new AmsQHooker();


} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {


return new AmsPHooker();


} else {


return new AmsNHooker();


}


}


@Override


public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {


// ...


}


// 创建代理


Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),


hooker.getInterfaces(), this);


// 替换系统 am 对象


hooker.hookAms(proxy);


}


上面以 AMSProxy 实例为参数创建了一个代理对象 Proxy,并用这个 Proxy 对象通过 hookAms 方法替换掉了 am 对象,这样在本进程通过 ActivityManager.getService() 来调用相关方法时,会调用到上述的 invoke 方法,在这可以做拦截:


@Override


public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {


try {


if (callback.canIntercept(method, args)) {


if (callback.autoRemove()) {


// 将 am 对象还原


// ...


}


// 拦截 am 的请求,做自己的业务处理


return callback.intercept(origAm, method, args);


}


return method.invoke(origAm, args);


} catch (Exception e) {


e.printStackTrace();


}


return null;


}


当本进程中有代码尝试通过 am 来调用相关方法(比如说 startActivity 等)时,都会被 invoke 方法所拦截,然后通过我们设置的拦截条件(canIntercept)去选择是否拦截。建议每次完成了拦截的业务需求后,就把原 am 对象通过 hookAms 方法还原,防止的本次进程中持续拦截系统请求。这里一直强调是本次进程,显而易见,通过反射去替换 am 对象的方式,只会针对本进程起作用。


Android Q


========================================================================


在 Android Q 上,上述 Instrumentation 中的调用变成如下:


int result = ActivityTaskManager.getService().startActivity(whoThread, who.getBasePackageName(), intent, ...);


这变成了 ActivityTaskManager.getService():


/** @hide */


public static IActivityTaskManager getService() {


return IActivityTaskManagerSingleton.get();


}


private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton = new Singleton<IActivityTaskManager>() {


@Override


protected IActivityTaskManager create() {


final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);


return IActivityTaskManager.Stub.asInterface(b);


}


};


可以看到在 Android Q 上从 ActivityManager 变成了 ActivityTaskManager 系列的类,于是我们的 AmsQHooker 实现如下:


class AmsQHooker : AmsHooker() {


override fun getHookObj(): Any? {


val amClass = ReflectUtils.getClass("android.app.ActivityTaskManager")


// 拿到 IActivityTaskManagerSingleton 属性


return ReflectUtils.readStaticField(amClass, "IActivityTaskManagerSingleton")


}


override fun getHookField(): Field? {


return ReflectUtils.getField(ReflectUtils.getClass("android.util.Singleton"), "mInstance")


}


override fun getTarget(): Any? {


// Reflective access to getService is forbidden when targeting API 29 and above


// val getServiceMethod = amClass.getDeclaredMethod("getService")


return ReflectUtils.getClass("android.util.Singleton").getDeclaredMethod("get").invoke(getHookObj())


}


override fun getInterfaces(): Array<Class<*>> {


return arrayOf(ReflectUtils.getClass("android.app.IActivityTaskManager"))


}


}


其它的步骤跟 Android P 是一样的。


Android N


========================================================================


在 Android 7.1 及以下,Instrumentation 的调用又不一样:


int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent, ...);


这变成了 ActivityManagerNative.getDefault():


static public IActivityManager getDefault() {


return gDefault.get();


}


private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {


protected IActivityManager create() {


IBinder b = ServiceManager.getService("activity");


IActivityManager am = asInterface(b);


return am;


}


};


可以看到虽然类名和方法有所变化,但还是借助了 Singleton 类,所以只需要继承 AmsHooker 重写相关方法即可:

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
【干货篇】Android各版本拦截进程对AMS的请求实战,移动互联网开发技术就业前景