Service Hook解析
来源:互联网 发布:镇江网络广播电视 编辑:程序博客网 时间:2024/06/05 20:49
4,Service Hook解析
Service/ContentProvider由于没有Activity那么复杂的启动过程,并且Activity的生命周期是由用户交互决定的,
而Service的声明周期是主动通过代码调用的。因此虽然也有替换/还原过程,但是有点不同,是采用代理分发技术。
就是启动宿主的Service/ContentProvider对象,然后管理插件的Service/ContentProvider对象。
Service 的Hook 是通过ActivityManagerProxy完成的。
ActivityManagerProxy类Hook了ActivityManager的7个方法,其中和service相关的有5个,分别是startService/ stopService/
stopServiceToken/bindService/ unbindService,这5个方法主要和service的生命周期有关。并且所有方法的调用流程
完全相同,因此,以startService方法为例来论述。
在AndroidManifest中注册了两类service,一类LocalService,多进程时为RemoteService,
<!-- Local Service running in main process --><service android:name="com.didi.virtualapk.delegate.LocalService" /><!-- Daemon Service running in child process --><service android:name="com.didi.virtualapk.delegate.RemoteService" android:process=":daemon"> <intent-filter> <action android:name="${applicationId}.intent.ACTION_DAEMON_SERVICE" /> </intent-filter></service>
ActivityManagerProxy的invoke方法中有关startService处理的代码如下,
if ("startService".equals(method.getName())) { try { return startService(proxy, method, args);
startService方法如下,
private Object startService(Object proxy, Method method, Object[] args) throws Throwable { IApplicationThread appThread = (IApplicationThread) args[0]; Intent target = (Intent) args[1]; ResolveInfo resolveInfo = this.mPluginManager.resolveService(target, 0); if (null == resolveInfo || null == resolveInfo.serviceInfo) { // is host service return method.invoke(this.mActivityManager, args); } return startDelegateServiceForTarget(target, resolveInfo.serviceInfo, null, RemoteService.EXTRA_COMMAND_START_SERVICE); }
首先调用PluginManager的resolveService方法匹配出目标intent的相关信息,然后调用startDelegateServiceForTarget方法进行替换.
4.1 匹配
PluginManager的resolveService方法流程图如下,
其实,和Activity的匹配过程完全相同。
PluginManager的resolveService方法如下,
public ResolveInfo resolveService(Intent intent, int flags) { for (LoadedPlugin plugin : this.mPlugins.values()) { ResolveInfo resolveInfo = plugin.resolveService(intent, flags); if (null != resolveInfo) { return resolveInfo; } } return null;}
从mPlugins变量中逐个取出所有插件对应的LoadedPlugin对象,然后逐个进行intent匹配,
LoadedPlugin 的resolveService方法如下,
public ResolveInfo resolveService(Intent intent, int flags) { List<ResolveInfo> query = this.queryIntentServices(intent, flags); if (null == query || query.isEmpty()) { return null; } ContentResolver resolver = this.mPluginContext.getContentResolver(); return chooseBestActivity(intent, intent.resolveTypeIfNeeded(resolver), flags, query); }
首先调用queryIntentActivities方法匹配intent,完成之后调用chooseBestActivity选择最符合条件的那个对象。
LoadedPlugin的queryIntentServices方法如下,
ComponentName component = intent.getComponent();List<ResolveInfo> resolveInfos = new ArrayList<ResolveInfo>();ContentResolver resolver = this.mPluginContext.getContentResolver();for (PackageParser.Service service : this.mPackage.services) { if (service.getComponentName().equals(component)) { ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.serviceInfo = service.info; resolveInfos.add(resolveInfo); } else if (component == null) { // only match implicit intent for (PackageParser.ServiceIntentInfo intentInfo : service.intents) { if (intentInfo.match(resolver, intent, true, TAG) >= 0) { ResolveInfo resolveInfo = new ResolveInfo(); resolveInfo.serviceInfo = service.info; resolveInfos.add(resolveInfo); break; } } }}
4.2 替换
ActivityManagerProxy的startDelegateServiceForTarget方法如下,
private ComponentName startDelegateServiceForTarget(Intent target, ServiceInfo serviceInfo, Bundle extras, int command) { Intent wrapperIntent = wrapperTargetIntent(target, serviceInfo, extras, command); return mPluginManager.getHostContext().startService(wrapperIntent);}
首先调用wrapperTargetIntent替换intent,然后调用startService启动替换后的intent。
wrapperTargetIntent方法如下,
private Intent wrapperTargetIntent(Intent target, ServiceInfo serviceInfo, Bundle extras, int command) { // fill in service with ComponentName target.setComponent(new ComponentName(serviceInfo.packageName, serviceInfo.name)); String pluginLocation = mPluginManager.getLoadedPlugin(target.getComponent()).getLocation(); // start delegate service to run plugin service inside boolean local = PluginUtil.isLocalService(serviceInfo); Class<? extends Service> delegate = local ? LocalService.class : RemoteService.class; Intent intent = new Intent(); intent.setClass(mPluginManager.getHostContext(), delegate); intent.putExtra(RemoteService.EXTRA_TARGET, target); intent.putExtra(RemoteService.EXTRA_COMMAND, command); intent.putExtra(RemoteService.EXTRA_PLUGIN_LOCATION, pluginLocation); if (extras != null) { intent.putExtras(extras); }return intent;}
重新初始化了Intent,设置了目标类为LocalService(多进程时设置为RemoteService),
然后将原本的Intent存储到EXTRA_TARGET,携带command为EXTRA_COMMAND_START_SERVICE,以及插件apk路径。
4.3 代理分发
实际上启动的是LocalService和RemoteService, 并且RemoteService继承于LocalService, LocalService的
onStartCommand方法主要逻辑如下,
1,获取目标intent,
Intent target = intent.getParcelableExtra(EXTRA_TARGET);
2,判断intent所在的插件是否加载,如果没有加载,就加载该插件。
String pluginLocation = intent.getStringExtra(EXTRA_PLUGIN_LOCATION);ComponentName component = target.getComponent();LoadedPlugin plugin = PluginManager.getInstance(this).getLoadedPlugin(component);if (plugin == null && pluginLocation != null) { try { PluginManager.getInstance(this).loadPlugin(new File(pluginLocation)); •••
3,调用父类LocalService的onStartCommand方法,
return super.onStartCommand(intent, flags, startId);
其实代理分发的整个精华部分就在于LocalService的onStartCommand方法,该方法主要逻辑如下,
1,获取intent以及相关信息,
Intent target = intent.getParcelableExtra(EXTRA_TARGET);•••ComponentName component = target.getComponent();LoadedPlugin plugin = mPluginManager.getLoadedPlugin(component);
2,获取service生命周期的相关信息,
int command = intent.getIntExtra(EXTRA_COMMAND, 0);
3,根据intent以及周期的相关信息控制目标service。
switch (command) { case EXTRA_COMMAND_START_SERVICE: {
那么,service周期信息是如何放入的呢?
在ActivityManagerProxy的这5个方法startService/ stopService/ stopServiceToken/bindService/ unbindService中,
都会调用startDelegateServiceForTarget方法将信息塞入intent中,
startService方法中调用startDelegateServiceForTarget方法如下,
startDelegateServiceForTarget(target, resolveInfo.serviceInfo, null, RemoteService.EXTRA_COMMAND_START_SERVICE);
stopService方法中调用startDelegateServiceForTarget方法如下,
startDelegateServiceForTarget(target, resolveInfo.serviceInfo, null, RemoteService.EXTRA_COMMAND_STOP_SERVICE);
stopServiceToken方法中调用startDelegateServiceForTarget方法如下,
startDelegateServiceForTarget(target, resolveInfo.serviceInfo, null, RemoteService.EXTRA_COMMAND_STOP_SERVICE);
bindService方法中调用startDelegateServiceForTarget方法如下,
startDelegateServiceForTarget(target, resolveInfo.serviceInfo, bundle, RemoteService.EXTRA_COMMAND_BIND_SERVICE);
unbindService方法中调用startDelegateServiceForTarget方法如下,
startDelegateServiceForTarget(target, resolveInfo.serviceInfo, null, RemoteService.EXTRA_COMMAND_UNBIND_SERVICE);
LocalService的onStartCommond方法中对这4类消息的处理流程和方法完全相同,
以EXTRA_COMMAND_START_SERVICE方法为例论述,主要逻辑如下,
1,利用反射获取进程的ActivityThread等信息,
ActivityThread mainThread = (ActivityThread)ReflectUtil.getActivityThread(getBaseContext());IApplicationThread appThread = mainThread.getApplicationThread();
2,判断目标service是否已启动,
if (this.mPluginManager.getComponentsHandler().isServiceAvailable(component)) { service = this.mPluginManager.getComponentsHandler().getService(component);
如果已启动就直接获取目标service。
3,如果目标service未启动,首先加载并构造service组件,然后利用反射设置相关信息,最后调用service的onCreate方法,
service = (Service) plugin.getClassLoader().loadClass(component.getClassName()).newInstance();Application app = plugin.getApplication();IBinder token = appThread.asBinder();Method attach = service.getClass().getMethod("attach", Context.class, ActivityThread.class, String.class, IBinder.class, Application.class, Object.class);IActivityManager am = mPluginManager.getActivityManager();attach.invoke(service, plugin.getPluginContext(), mainThread, component.getClassName(), token, app, am);service.onCreate();
当然,启动的service会进行统一管理,
this.mPluginManager.getComponentsHandler().rememberService(component, service);
ComponentsHandler中有三个ArrayMap保存service信息,
private ArrayMap<ComponentName, Service> mServices = new ArrayMap<ComponentName, Service>();private ArrayMap<IBinder, Intent> mBoundServices = new ArrayMap<IBinder, Intent>();private ArrayMap<Service, AtomicInteger> mServiceCounters = new ArrayMap<Service, AtomicInteger>();
mServices保存通过startservice方法启动的服务,
mBoundServices保存通过bindservice方法绑定的服务,
mServiceCounters保存服务的相关信息。
- Service Hook解析
- Service Hook
- Hook API 原理 解析
- Activity Hook解析
- ContentProvider Hook解析
- Service解析
- Service解析
- Service 解析
- LocationManagerService API的Hook解析
- Miranda的HOOK及SERVICE机制分析
- HOOK和Inline-HOOK进程隐藏技术全面解析
- HOOK和Inline-HOOK进程隐藏技术全面解析
- android native hook 源码 及 解析
- Beego源码解析(四)-Hook函数
- 解析service(一)
- 解析service(二)
- 解析Activity、Intent、Service
- init.c解析service
- 通信类顶级会议及期刊
- DOM节点删除之保留数据的删除操作detach()
- js数组
- 数组常用的属性和方法
- logback配置文件
- Service Hook解析
- 网络学习笔记-MAC地址
- 通过内存缓存来提升计算性能(golang代码)
- Spark共享变量---Scala
- Zeppelin源码分析-独立解释器 JVM 相关分析(1)
- 互联网金融的分类监管主体
- 文件IO 实现学生信息管理系统
- ORM思想
- SpringBoot跳转HTML问题汇总(IntelliJ IDEA)