(四)Android `Hook` 式插件化

1,666 阅读3分钟

要了解插件化首先要具备三个前提条件:

  1. Android 系统源码阅读与理解

  2. Java 反射机制

  3. Hook 技术

什么是Hook

在事件执行的过程中截获并监控事件的执行流,将自身的代码融入其执行流中。

Hook介绍: blog.csdn.net/qq_39731011…

案例1:通过hook方式拦截View的onClick()事件加入自己的逻辑;

源码: github.com/itang01/jia…

关键点:

  1. 替换(把系统中的 替换成 动态代理)
  2. 动态代理(做我们自己的业务逻辑)

利用动态代理,生成OnClickListener接口代理,在代理回调中,加入自己的逻辑,然后通过反射,将OnClickListener接口代理替换ListenerInfo中的mOnClickListener

案例2:通过hook方式启动未注册的Activity:

源码: github.com/itang01/jia…

关键点:

  1. 通过hook方式,绕过 AMS 检查,在执行 AMS 之前,替换在AndroidManifest.xml里面配置的Activity;
  2. 通过hook方式,hook launchActivity() 方法,准备实例化AndroidManifest.xml里面配置的Activity的时候,将在AndroidManifest.xml里面配置的Activity,替换成未注册的Activity(给mH(Handler)设置 Callback,在 Callback 中做替换逻辑);

案例3:宿主 跳转 插件里面的Activity

源码: github.com/itang01/jia…

直接跳转的话,一定会报错:

Caused by: java.lang.ClassNotFoundException: Didn't find class "com.netease.plugin_package.PluginActivity" on path:
 DexPathList[[zip file "/data/app/com.netease.hookproject-1/base.apk",...... ]]

分析错误原因,来学习Android类加载:

startActivity --> AMS --> ActivityThread(把代理的Activity给换回来了) --> 要去实例化Activity (报错)

 Activity --> Instrumentation --> AMS检查 -->
    ActivityThread (即将加载)-(handleLaunchActivity 类加载Activity performLaunchActivity --> newActivity(cl == PathClassLoader))

分析Android中的ClassLoader:
    1.java中的ClassLoader 和 Android的ClassLoader 是不一样
    2.ClassLoader == PathClassLoader
    3.PathClassLoader == cl.loadClass(className).newInstance();

PathClassLoader.loadClass  --> BaseDexClassLoader -->ClassLoader.loadClass--findClass(空方法) 让覆盖的子类方法去完成 -->
BaseDexClassLoader.findClass() --> pathList.findClass

BaseDexClassLoader.findClass() --> c 为什么为null,--> DexPathList.findClass(className) --> DexFile.loadClassBinaryName(系列步骤后 NDK)

for遍历 dexElements == Element[] ,分析 Element 是什么 ,为什么 Element.dexFile == null?

Android虚拟机 apk中的dex文件相当于Element,Element是dex表现形式的描述 --> Element 中的 dexFile 拥有可执行

为什么 Element == null?
答:因为类加载机制加载的是 宿主的 classes.dex,也就是Elements,没有插件的Element

解决方案:把插件的 dexElements 和 宿主中的 dexElements 融为一体,PathClassLoader 就能加载到 插件/宿主 中的class

Hook式 插件化,就是这么一回事!

补充1:Android ClassLoader介绍

1.java中的ClassLoader 和 Android的ClassLoader 是不一样

2.Android中的ClassLoader 分为两类:

  • 系统提供的ClassLoader --> BootClassLoader(给系统预加载使用),PathClassLoader(给程序/系统程序/应用程序 加载class),DexClassLoader(加载 apk文件)
  • 自定义ClassLoader

补充2:Android 系统启动流程

  1. 内核启动 ...
  2. Init 进程:第一个系统进程
  3. Init 进程启动 Zygote 进程:ZygoteInit.java --> preload() --> preloadClasses() --> BootClassLoader.getInstance() 实例化 BootClassLoader; handleSystemServerProcess () --> PathClassLoaderFactory.createSystemServerClassloader() 实例化 PathClassLoader
  4. zygote 进程孵化 SystemServer
  5. SystemServer 启动很多的服务:AMS、PSM、...

了解到这些后,下一步:将插件的dexElements 和 宿主中的 dexElements 融为一体