日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

【Android 插件化】Hook 插件化框架 ( 通过反射获取 “宿主“ 应用中的 Element[] dexElements )

發(fā)布時(shí)間:2025/6/17 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 插件化】Hook 插件化框架 ( 通过反射获取 “宿主“ 应用中的 Element[] dexElements ) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Android 插件化系列文章目錄

【Android 插件化】插件化簡介 ( 組件化與插件化 )
【Android 插件化】插件化原理 ( JVM 內(nèi)存數(shù)據(jù) | 類加載流程 )
【Android 插件化】插件化原理 ( 類加載器 )

【Android 插件化】“ 插樁式 “ 插件化框架 ( 原理與實(shí)現(xiàn)思路 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 類加載器創(chuàng)建 | 資源加載 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 注入上下文的使用 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 獲取插件入口 Activity 組件 | 加載插件 Resources 資源 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 運(yùn)行應(yīng)用 | 代碼整理 )

【Android 插件化】Hook 插件化框架 ( Hook 技術(shù) | 代理模式 | 靜態(tài)代理 | 動(dòng)態(tài)代理 )
【Android 插件化】Hook 插件化框架 ( Hook 實(shí)現(xiàn)思路 | Hook 按鈕點(diǎn)擊事件 )
【Android 插件化】Hook 插件化框架 ( Hook Activity 啟動(dòng)過程 | 靜態(tài)代理 )
【Android 插件化】Hook 插件化框架 ( 從 Hook 應(yīng)用角度分析 Activity 啟動(dòng)流程 一 | Activity 進(jìn)程相關(guān)源碼 )
【Android 插件化】Hook 插件化框架 ( 從 Hook 應(yīng)用角度分析 Activity 啟動(dòng)流程 二 | AMS 進(jìn)程相關(guān)源碼 | 主進(jìn)程相關(guān)源碼 )

【Android 插件化】Hook 插件化框架 ( hook 插件化原理 | 插件包管理 )
【Android 插件化】Hook 插件化框架 ( 通過反射獲取 “插件包“ 中的 Element[] dexElements )
【Android 插件化】Hook 插件化框架 ( 通過反射獲取 “宿主“ 應(yīng)用中的 Element[] dexElements )


文章目錄

  • Android 插件化系列文章目錄
  • 前言
  • 一、通過反射獲取 "宿主" 中的 Element[] dexElements
    • 1、反射獲取 BaseDexClassLoader.class
    • 2、反射獲取 DexPathList pathList 字段
    • 3、反射獲取 DexPathList pathList 對(duì)象
    • 4、獲取 DexPathList pathList 對(duì)象
    • 5、反射獲取 Element[] dexElements 字段
    • 6、反射獲取 Element[] dexElements 對(duì)象
  • 二、完整代碼示例
  • 三、博客資源


前言

在上一篇博客 【Android 插件化】Hook 插件化框架 ( 通過反射獲取 “插件包“ 中的 Element[] dexElements ) 介紹了從 " 插件包 " APK 文件中獲取 Element[] dexElements 流程 , 本篇博客中介紹獲取 “宿主“ 應(yīng)用中的 Element[] dexElements ;


Android 中的類加載器 DexClassLoader , PathClassLoader 的父類是 BaseDexClassLoader ,

BaseDexClassLoader 中有 private final DexPathList pathList 成員變量 ,

DexPathList 中有 private Element[] dexElements 成員變量 ,

Element[] dexElements 就是最終存放 Dex 字節(jié)碼數(shù)據(jù)的內(nèi)存變量 , 最終將 " 宿主 " 應(yīng)用中讀取的 dexElements 合并到 " 宿主 " 應(yīng)用的 dexElements 中 ;


獲取 " 宿主 " 與 " 插件包 " Element[] dexElements 的區(qū)別在于 ,

" 插件包 " 的類加載器是 DexClassLoader , 是由開發(fā)者自己創(chuàng)建的 ;

// 創(chuàng)建類加載器 DexClassLoader plugin_dexClassLoader =new DexClassLoader(apkPath, // 插件包路徑cachePath, // 插件包加載時(shí)產(chǎn)生的緩存路徑null, // 庫的搜索路徑, 可以設(shè)置為空mBase.getClassLoader() // 父加載器, PathClassLoader);java

" 宿主 " 應(yīng)用的類加載器 PathClassLoader 是由 Android 上下文 Context 提供的 , 也就是由系統(tǒng)創(chuàng)建的 ;

PathClassLoader host_pathClassLoader = (PathClassLoader) mBase.getClassLoader();




一、通過反射獲取 “宿主” 中的 Element[] dexElements



反射 " 宿主 " 應(yīng)用的 dexElement 執(zhí)行步驟 :

① 反射獲取 BaseDexClassLoader.class

② 反射獲取 BaseDexClassLoader.calss 中的 private final DexPathList pathList 成員字段

③ 獲取 PathClassLoader 類加載器中的 DexPathList pathList 成員對(duì)象

④ 獲取 DexPathList.class

⑤ 反射獲取 DexPathList.class 中的 private Element[] dexElements 成員變量的 Field 字段對(duì)象

⑥ 反射獲取 DexPathList 對(duì)象中的 private Element[] dexElements 成員變量對(duì)象


1、反射獲取 BaseDexClassLoader.class


反射獲取 BaseDexClassLoader.class , 通過反射獲取插件包中的 dexElements , 這種類加載是合并類加載 , 將所有的 Dex 文件 , 加入到應(yīng)用的 dex 文件集合中 , 可參考 dex 加固 , 熱修復(fù) , 插裝式插件化 的實(shí)現(xiàn)步驟 ;

反射出 BaseDexClassLoader 類 , PathClassLoader 和 DexClassLoader 都是 BaseDexClassLoader 的子類 ;

參考 : https://www.androidos.net.cn/android/9.0.0_r8/xref/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java

代碼示例 :

// ① 反射獲取 BaseDexClassLoader.class Class<?> host_baseDexClassLoaderClass = null; try {host_baseDexClassLoaderClass = Class.forName("dalvik.system.BaseDexClassLoader"); } catch (ClassNotFoundException e) {e.printStackTrace(); }

2、反射獲取 DexPathList pathList 字段


// ② 反射獲取 BaseDexClassLoader.calss 中的 private final DexPathList pathList 成員字段 Field host_pathListField = null; try {host_pathListField = host_baseDexClassLoaderClass.getDeclaredField("pathList");// 設(shè)置屬性的可見性host_pathListField.setAccessible(true); } catch (NoSuchFieldException e) {e.printStackTrace(); }

3、反射獲取 DexPathList pathList 對(duì)象


根據(jù) Field 字段獲取 成員變量 , DexClassLoader 繼承了 BaseDexClassLoader, 因此其內(nèi)部肯定有 private final DexPathList pathList 成員變量 ;

// ③ 反射獲取 DexClassLoader 類加載器中的 DexPathList pathList 成員對(duì)象 // 根據(jù) Field 字段獲取 成員變量 // DexClassLoader 繼承了 BaseDexClassLoader, 因此其內(nèi)部肯定有 // private final DexPathList pathList 成員變量 PathClassLoader host_pathClassLoader = (PathClassLoader) mBase.getClassLoader(); Object host_pathListObject = null; try {host_pathListObject = host_pathListField.get(host_pathClassLoader); } catch (IllegalAccessException e) {e.printStackTrace(); }

4、獲取 DexPathList pathList 對(duì)象


獲取 DexPathList.class , 之前已經(jīng)通過反射獲取了 DexPathList pathList 對(duì)象 , 這里直接通過調(diào)用該對(duì)象的 getClass 方法 , 獲取該類對(duì)象 ;

參考 : https://www.androidos.net.cn/android/9.0.0_r8/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java

// ④ 獲取 DexPathList.class // DexPathList 類中有 private Element[] dexElements 成員變量 // 通過反射獲取該成員變量 // 參考 https://www.androidos.net.cn/android/9.0.0_r8/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java // 獲取 DexPathList pathList 成員變量的字節(jié)碼類型 ( 也可以通過反射獲得 ) // 獲取的是 DexPathList.class Class<?> host_dexPathListClass = host_pathListObject.getClass();

5、反射獲取 Element[] dexElements 字段


// ⑤ 反射獲取 DexPathList.class 中的 private Element[] dexElements 成員變量的 Field 字段對(duì)象 Field host_dexElementsField = null; try {host_dexElementsField = host_dexPathListClass.getDeclaredField("dexElements");// 設(shè)置屬性的可見性host_dexElementsField.setAccessible(true); } catch (NoSuchFieldException e) {e.printStackTrace(); }

6、反射獲取 Element[] dexElements 對(duì)象


// ⑥ 反射獲取 DexPathList 對(duì)象中的 private Element[] dexElements 成員變量對(duì)象Object host_dexElementsObject = null;try {host_dexElementsObject = host_dexElementsField.get(host_pathListObject);} catch (IllegalAccessException e) {e.printStackTrace();}



二、完整代碼示例



package kim.hsl.plugin;import android.content.Context;import java.lang.reflect.Field;import dalvik.system.DexClassLoader; import dalvik.system.PathClassLoader;/*** 使用 Hook 實(shí)現(xiàn)的插件使用入口* 1. 加載插件包中的字節(jié)碼* 2. 直接通過 hook 技術(shù), 鉤住系統(tǒng)的 Activity 啟動(dòng)流程實(shí)現(xiàn)* ① Activity 對(duì)象創(chuàng)建之前 , 要做很多初始化操作 , 先在 ActivityRecord 中加載 Activity 信息* 如果修改了該信息 , 將要跳轉(zhuǎn)的 Activity 信息修改為插件包中的 Activity* 原來的 Activity 只用于占位 , 用于欺騙 Android 系統(tǒng)* ② 使用 hook 技術(shù) , 加載插件包 apk 中的 Activity* ③ 實(shí)現(xiàn)跳轉(zhuǎn)的 Activity ( 插件包中的 )* 3. 解決 Resources 資源沖突問題* ( 使用上述 hook 插件化 , 可以不用考慮 Activity 的聲明周期問題 )** 插件包中的 Activity 是通過正規(guī)流程 , 由 AMS 進(jìn)行創(chuàng)建并加載的* 但是該 Activity 并沒有在 AndroidManifest.xml 清單文件中注冊(cè)* 這里需要一個(gè)已經(jīng)在清單文件注冊(cè)的 Activity 欺騙系統(tǒng)** 插裝式插件化 是通過代理 Activity , 將插件包加載的字節(jié)碼 Class 作為一個(gè)普通的 Java 類* 該普通的 Java 類有所有的 Activity 的業(yè)務(wù)邏輯* 該 Activity 的聲明周期 , 由代理 Activity 執(zhí)行相關(guān)的生命周期方法* hook 插件化 : hook 插件化直接鉤住系統(tǒng)中 Activity 啟動(dòng)流程的某個(gè)點(diǎn)* 使用插件包中的 Activity 替換占位的 Activity*/ public class PluginManager {/*** 上下文*/private Context mBase;/*** 單例*/private static PluginManager instance;public static PluginManager getInstance(Context context) {if (instance == null) {instance = new PluginManager(context);}return instance;}private PluginManager(Context context) {this.mBase = context;}/*** Application 啟動(dòng)后 , 調(diào)用該方法初始化插件化環(huán)境* 加載插件包中的字節(jié)碼*/private void init() {// 加載 apk 文件loadApk();}private void loadApk() {// 插件包的絕對(duì)路徑 , /data/data/< package name >/files/String apkPath = mBase.getFilesDir().getAbsolutePath() + "plugin.apk";// 加載插件包后產(chǎn)生的緩存文件路徑// /data/data/< package name >/app_plugin_cache/String cachePath =mBase.getDir("plugin_cache", Context.MODE_PRIVATE).getAbsolutePath();// 創(chuàng)建類加載器DexClassLoader plugin_dexClassLoader =new DexClassLoader(apkPath, // 插件包路徑cachePath, // 插件包加載時(shí)產(chǎn)生的緩存路徑null, // 庫的搜索路徑, 可以設(shè)置為空mBase.getClassLoader() // 父加載器, PathClassLoader);// 1. 反射 " 插件包 " 應(yīng)用的 dexElement// 執(zhí)行步驟 :// ① 反射獲取 BaseDexClassLoader.class// ② 反射獲取 BaseDexClassLoader.calss 中的 private final DexPathList pathList 成員字段// ③ 反射獲取 DexClassLoader 類加載器中的 DexPathList pathList 成員對(duì)象// ④ 反射獲取 DexPathList.class// ⑤ 反射獲取 DexPathList.class 中的 private Element[] dexElements 成員變量的 Field 字段對(duì)象// ⑥ 反射獲取 DexPathList 對(duì)象中的 private Element[] dexElements 成員變量對(duì)象// ① 反射獲取 BaseDexClassLoader.class// 通過反射獲取插件包中的 dexElements// 這種類加載是合并類加載 , 將所有的 Dex 文件 , 加入到應(yīng)用的 dex 文件集合中// 可參考 dex 加固 , 熱修復(fù) , 插裝式插件化 的實(shí)現(xiàn)步驟// 反射出 BaseDexClassLoader 類 , PathClassLoader 和 DexClassLoader// 都是 BaseDexClassLoader 的子類// 參考 https://www.androidos.net.cn/android/9.0.0_r8/xref/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.javaClass<?> baseDexClassLoaderClass = null;try {baseDexClassLoaderClass = Class.forName("dalvik.system.BaseDexClassLoader");} catch (ClassNotFoundException e) {e.printStackTrace();}// ② 反射獲取 BaseDexClassLoader.calss 中的 private final DexPathList pathList 成員字段Field plugin_pathListField = null;try {plugin_pathListField = baseDexClassLoaderClass.getDeclaredField("pathList");// 設(shè)置屬性的可見性plugin_pathListField.setAccessible(true);} catch (NoSuchFieldException e) {e.printStackTrace();}// ③ 反射獲取 plugin_dexClassLoader 類加載器中的 DexPathList pathList 成員對(duì)象// 根據(jù) Field 字段獲取 成員變量// DexClassLoader 繼承了 BaseDexClassLoader, 因此其內(nèi)部肯定有// private final DexPathList pathList 成員變量Object plugin_pathListObject = null;try {plugin_pathListObject = plugin_pathListField.get(plugin_dexClassLoader);} catch (IllegalAccessException e) {e.printStackTrace();}// ④ 獲取 DexPathList.class// DexPathList 類中有 private Element[] dexElements 成員變量// 通過反射獲取該成員變量// 參考 https://www.androidos.net.cn/android/9.0.0_r8/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java// 獲取 DexPathList pathList 成員變量的字節(jié)碼類型 ( 也可以通過反射獲得 )// 獲取的是 DexPathList.classClass<?> plugin_dexPathListClass = plugin_pathListObject.getClass();// ⑤ 反射獲取 DexPathList.class 中的 private Element[] dexElements 成員變量的 Field 字段對(duì)象Field plugin_dexElementsField = null;try {plugin_dexElementsField = plugin_dexPathListClass.getDeclaredField("dexElements");// 設(shè)置屬性的可見性plugin_dexElementsField.setAccessible(true);} catch (NoSuchFieldException e) {e.printStackTrace();}// ⑥ 反射獲取 DexPathList 對(duì)象中的 private Element[] dexElements 成員變量對(duì)象Object plugin_dexElementsObject = null;try {plugin_dexElementsObject = plugin_dexElementsField.get(plugin_pathListObject);} catch (IllegalAccessException e) {e.printStackTrace();}// 2. 反射 " 宿主 " 應(yīng)用的 dexElement// 執(zhí)行步驟 :// ① 反射獲取 BaseDexClassLoader.class// ② 反射獲取 BaseDexClassLoader.calss 中的 private final DexPathList pathList 成員字段// ③ 反射獲取 PathClassLoader 類加載器中的 DexPathList pathList 成員對(duì)象// ④ 反射獲取 DexPathList.class// ⑤ 反射獲取 DexPathList.class 中的 private Element[] dexElements 成員變量的 Field 字段對(duì)象// ⑥ 反射獲取 DexPathList 對(duì)象中的 private Element[] dexElements 成員變量對(duì)象// ① 反射獲取 BaseDexClassLoader.classClass<?> host_baseDexClassLoaderClass = null;try {host_baseDexClassLoaderClass = Class.forName("dalvik.system.BaseDexClassLoader");} catch (ClassNotFoundException e) {e.printStackTrace();}// ② 反射獲取 BaseDexClassLoader.calss 中的 private final DexPathList pathList 成員字段Field host_pathListField = null;try {host_pathListField = baseDexClassLoaderClass.getDeclaredField("pathList");// 設(shè)置屬性的可見性host_pathListField.setAccessible(true);} catch (NoSuchFieldException e) {e.printStackTrace();}// ③ 反射獲取 DexClassLoader 類加載器中的 DexPathList pathList 成員對(duì)象// 根據(jù) Field 字段獲取 成員變量// DexClassLoader 繼承了 BaseDexClassLoader, 因此其內(nèi)部肯定有// private final DexPathList pathList 成員變量PathClassLoader host_pathClassLoader = (PathClassLoader) mBase.getClassLoader();Object host_pathListObject = null;try {host_pathListObject = host_pathListField.get(host_pathClassLoader);} catch (IllegalAccessException e) {e.printStackTrace();}// ④ 獲取 DexPathList.class// DexPathList 類中有 private Element[] dexElements 成員變量// 通過反射獲取該成員變量// 參考 https://www.androidos.net.cn/android/9.0.0_r8/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java// 獲取 DexPathList pathList 成員變量的字節(jié)碼類型 ( 也可以通過反射獲得 )// 獲取的是 DexPathList.classClass<?> host_dexPathListClass = host_pathListObject.getClass();// ⑤ 反射獲取 DexPathList.class 中的 private Element[] dexElements 成員變量的 Field 字段對(duì)象Field host_dexElementsField = null;try {host_dexElementsField = host_dexPathListClass.getDeclaredField("dexElements");// 設(shè)置屬性的可見性host_dexElementsField.setAccessible(true);} catch (NoSuchFieldException e) {e.printStackTrace();}// ⑥ 反射獲取 DexPathList 對(duì)象中的 private Element[] dexElements 成員變量對(duì)象Object host_dexElementsObject = null;try {host_dexElementsObject = host_dexElementsField.get(host_pathListObject);} catch (IllegalAccessException e) {e.printStackTrace();}} }



三、博客資源



博客資源 :

  • GitHub : https://github.com/han1202012/Plugin_Hook

總結(jié)

以上是生活随笔為你收集整理的【Android 插件化】Hook 插件化框架 ( 通过反射获取 “宿主“ 应用中的 Element[] dexElements )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。