当前位置:网站首页>学习笔记:插件化Activity之Hook点位

学习笔记:插件化Activity之Hook点位

2022-06-10 23:05:00 InfoQ

四大组件之Activity:

名词解释

AMS:AMS Binder对象AMN:app中获取AMS代理的对象ATP:ApplicationThreadProxy用于AMS和APP通信,AT的代理对象APT:ApplicationThread APP中的Binder对象。APT中会利用mh这个Handler发送消息做对应处理AT:APT会调用AT得方法,AT中给mh发消息mh:App的Handler,用于接受处理AMS等系统服务发送的消息处理

原始流程

startActivity交互过程如下:

App:ContextTheme--->ContextWrapper--->Context--->ContextImpl:ContextImpl内部调用Instrumention.startActivity()传入启动Activity的类名(用于校验是否注册过没有注册抛异常)等信息,该方法其中通过AMN获取AMS代理对象和AMS进行通信。

AMS远端:获取要启动的activity类名,观察是否在清单文件中注册过(PMS在安装时会解析对应APK清单文件存储到本地)。接着给启动activity的进程发送一个pause的消息通过ATP

然后判断该进程是否启动过(没有启动需要先和zygote用socket通信先创建一个进程Process.start)1.没有启动过(没有启动需要先和zygote用socket通信先创建一个进程Process.start,接着创建ActivityThread,利用AMN把ATP传给AMS(这样AMS就可以和APP通信了)接着AMS在给ATP发消息 AT收到给mh发送消进行反射创建Application调用onCreate,在接着就是下面2中所说的进程已经启动情况的步骤了)

2.启动过(AMS会封装Activity变成一个ActivityClientRecord,该对象会携带cl后面mh会根据这个cl去反射创建Activity。)

APP中:

ATP中收到AMS发过来的消息取出ActivityClientRecord,调用AT吧这个参数传进去。AT中调用mh的handlerPerformLaunchActivity。mh其实是一个handler,handleCallBack中来决定调用哪个方法对应于本示例startActivity为下面的逻辑

回调中取出acRecord,利用acRecord的classloader对象来反射创建对应activity,并调用onCreate方法

通知最开始pause的那个activity恢复运行~(利用ATP也是)至此交互结束

Hook点

我们可以Hook哪些点呢?提炼出精华我们在哪里可以把狸猫换成太子~

第一个点:

Instrumention利用AMN获取到AMS代理,将信息传给AMS校验(我们在Instrumention中拦截这个代理,替换为我们自定义的对象。检测到startActivity时将Activity换成我们宿主中已经注册了的StubActivity)好了,现在AMS校验过了,他要通知APP创建Activity对象了。但是这个时候是StubService的Activity。我们需要把他换掉我们真实启动的Activity。

第二个点:

我们怎么知道真实启动的Activity是谁呢?在第一步中其实整个流程传递的都是Intent,包括我们接受到ANS消息时也是Intent。既然是同一个Intent对象。我们在这个Intent中动手脚(APP调用AMS把真实启动的Activity保存到Intent中,在AMS通知APP创建的时候在取出来)

好,第一个是在Instrumention中换成我们的代理接下来就会和AMS交互(这里是最后一步下一步就要和AMS通信因此选在这里进行Hook)那么通知ATP,AT,mh中都可以进行还原取出Intent中真实启动的activity。

我们在mh中最后一步反射创建的地方进行修改(和上面一样,在最接近现场的地方进行Hook)。将mh替换为我们的mh。这样我们收到handlerPerformLaunchActivity的消息时,就可以做我们自己的操作了

不同的ClassLoader会加载不同的类,classloader中如果没有这个class是加载不了的。所以我们要用正确的cl去加载对象。这个cl其实就是插件的cl,也就是dexcl。我们在和AMS交互的时候可以传入对应的cl,之后创建再取出正确的cl。

注意点:

由于Activity默认是Standard模式,所以宿主中的一个Activity可以对应插件中的多个标准模式的Activity。每次启动都会创建一个实例。但是Android中是有LaunchMode的,不同的启动模式对应的效果也不同。那么如何支持LaunchMode呢

原网站

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://xie.infoq.cn/article/fc73ca3e86bd52da450b49ad8