日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 反射获取系统的 Element[] dexElements )

發布時間:2025/6/17 Android 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 反射获取系统的 Element[] dexElements ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、dex 文件準備
  • 二、加載 dex 文件流程
  • 三、Element[] dexElements 分析
  • 四、反射獲取系統的 Element[] dexElements



參考博客 :

  • 【Android 安全】DEX 加密 ( 常用 Android 反編譯工具 | apktool | dex2jar | enjarify | jd-gui | jadx )
  • 【Android 安全】DEX 加密 ( Proguard 簡介 | Proguard 相關網址 | Proguard 混淆配置 )
  • 【Android 安全】DEX 加密 ( Proguard 簡介 | 默認 ProGuard 分析 )
  • 【Android 安全】DEX 加密 ( Proguard keep 用法 | Proguard 默認混淆結果 | 保留類及成員混淆結果 | 保留注解以及被注解修飾的類/成員/方法 )
  • 【Android 安全】DEX 加密 ( Proguard 混淆 | 混淆后的報錯信息 | Proguard 混淆映射文件 mapping.txt )
  • 【Android 安全】DEX 加密 ( Proguard 混淆 | 將混淆后的報錯信息轉為原始報錯信息 | retrace.bat 命令執行目錄 | 暴露更少信息 )
  • 【Android 安全】DEX 加密 ( DEX 加密原理 | DEX 加密簡介 | APK 文件分析 | DEX 分割 )
  • 【Android 安全】DEX 加密 ( 多 DEX 加載 | 65535 方法數限制和 MultiDex 配置 | PathClassLoader 類加載源碼分析 | DexPathList )
  • 【Android 安全】DEX 加密 ( 不同 Android 版本的 DEX 加載 | Android 8.0 版本 DEX 加載分析 | Android 5.0 版本 DEX 加載分析 )
  • 【Android 安全】DEX 加密 ( DEX 加密使用到的相關工具 | dx 工具 | zipalign 對齊工具 | apksigner 簽名工具 )
  • 【Android 安全】DEX 加密 ( 支持多 DEX 的 Android 工程結構 )
  • 【Android 安全】DEX 加密 ( 代理 Application 開發 | multiple-dex-core 依賴庫開發 | 配置元數據 | 獲取 apk 文件并準備相關目錄 )
  • 【Android 安全】DEX 加密 ( 代理 Application 開發 | 解壓 apk 文件 | 判定是否是第一次啟動 | 遞歸刪除文件操作 | 解壓 Zip 文件操作 )

在 【Android 安全】DEX 加密 ( 支持多 DEX 的 Android 工程結構 ) 博客中介紹了 DEX 加密工程的基本結構 ,

app 是主應用 , 其 Module 類型是 “Phone & Tablet Module” ,

multiple-dex-core 是 Android 依賴庫 , 其作用是解密并加載多 DEX 文件 , 其 Module 類型是 “Android Library” ,

multiple-dex-tools 是 Java 依賴庫 , 其類型是 “Java or Kotlin Library” , 其作用是用于生成主 DEX ( 主 DEX 的作用就是用于解密與加載多 DEX ) , 并且還要為修改后的 APK 進行簽名 ;


在 【Android 安全】DEX 加密 ( 代理 Application 開發 | multiple-dex-core 依賴庫開發 | 配置元數據 | 獲取 apk 文件并準備相關目錄 ) 博客中講解了 multiple-dex-core 依賴庫開發 , 每次啟動都要解密與加載 dex 文件 , 在該博客中講解到了 獲取 apk 文件 , 并準備解壓目錄 ;

在 【Android 安全】DEX 加密 ( 代理 Application 開發 | 解壓 apk 文件 | 判定是否是第一次啟動 | 遞歸刪除文件操作 | 解壓 Zip 文件操作 ) 博客中講解了 apk 文件解壓操作 ;

本博客中主要講解 dex 文件加載操作 ;





一、dex 文件準備



上一篇博客講解的是 apk 文件解壓 , 繼續后面的步驟 ;


如果本次是第一次啟動 , 則需要 解壓 apk 文件 ,

解壓后 , 將所有的 dex 文件放到 dexDir 中 , 解密該 dex 文件 ,

解密完成后 , 將文件路徑存放在 var dexFiles : ArrayList<File> 集合中 ;


如果本次不是第一次啟動 , 則直接從 dexDir 中獲取 dex 文件 ,

將所有的 dex 文件路徑放在 var dexFiles : ArrayList<File> 集合中 ;

// 遍歷解壓后的 apk 文件 , 將需要加載的 dex 放入如下集合中var dexFiles : ArrayList<File> = ArrayList<File>()// 如果該 dexDir 存在 , 并且該目錄不為空 , 并進行 MD5 文件校驗if( !dexDir.exists() || dexDir.list().size == 0){// 將 apk 中的文件解壓到了 appDir 目錄unZipApk(apkFile, appDir)// 獲取 appDir 目錄下的所有文件var files = appDir.listFiles()// 遍歷文件名稱集合for(i in files.indices){var file = files[i]// 如果文件后綴是 .dex , 并且不是 主 dex 文件 classes.dex// 符合上述兩個條件的 dex 文件放入到 dexDir 中if(file.name.endsWith(".dex") &&TextUtils.equals(file.name, "classes.dex")){// 篩選出來的 dex 文件都是需要解密的// 解密需要使用 OpenSSL 進行解密// 獲取該文件的二進制 Byte 數據// 這些 Byte 數組就是加密后的 dex 數據var bytes = Utils.getBytes(file)// 解密該二進制數據, 并替換原來的加密 dex, 直接覆蓋原來的文件即可Utils.decrypt(bytes, file.absolutePath)// 將解密完畢的 dex 文件放在需要加載的 dex 集合中dexFiles.add(file)}// 判定是否是需要解密的 dex 文件}// 遍歷 apk 解壓后的文件}else{// 已經解密完成, 此時不需要解密, 直接獲取 dexDir 中的文件即可for (file in dexDir.listFiles()) {dexFiles.add(file)}}



二、加載 dex 文件流程



加載上述 dex 文件集合 , 這些 dex 文件已經解密 ;


加載 dex 文件流程 :

1 . 步驟一 : 獲得系統 DexPathList 中的 Element[] dexElements 數組 ,

( libcore/dalvik/src/main/java/dalvik/system/DexPathList.java ) ;

2 . 步驟二 : 在本應用中創建 Element[] dexElements 數組 , 用于存放解密后的 dex 文件 ;

3 . 步驟三 : 將 系統加載的 Element[] dexElements 數組 , 與我們自己創建的 Element[] dexElements 數組進行 合并操作

4 . 步驟四 : 替換 ClassLoader 加載過程中的 Element[] dexElements 數組 ( 封裝在 DexPathList 中 ) ;





三、Element[] dexElements 分析



系統的 Element[] dexElements 數組 封裝在 libcore/dalvik/src/main/java/dalvik/system/DexPathList.java

/*package*/ final class DexPathList {/*** dex/resource (class path) 元素集合.* 應該調用 pathElements , 但是 Facebook 應用通過反射修改 dexElements .*/private final Element[] dexElements;public DexPathList(ClassLoader definingContext, String dexPath,String libraryPath, File optimizedDirectory) {// save dexPath for BaseDexClassLoaderthis.dexElements = makePathElements(splitDexPath(dexPath), optimizedDirectory,suppressedExceptions);} }

參考源碼地址 : 6.0.1_r16/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java


DexPathList 對象被封裝在 libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java 中 ;

public class BaseDexClassLoader extends ClassLoader {private final DexPathList pathList; }

參考源碼地址 : libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java


PathClassLoader 是我們可以拿到的類加載器 , 該類是 BaseDexClassLoader 的子類 ,

源碼位置是 libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java ;

public class PathClassLoader extends BaseDexClassLoader { }

參考源碼地址 : libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java


在 Context 中調用 getClassLoader() 方法 , 可以拿到 PathClassLoader 后 , 需要從其父類 BaseDexClassLoader 中找到 DexPathList , 進而獲取封裝在 DexPathList 類中的 Element[] dexElements 數組 ;





四、反射獲取系統的 Element[] dexElements



上述的 DexPathList 對象 是 BaseDexClassLoader 的 私有成員 , Element[] dexElements 數組 也是 DexPathList 的 私有成員 , 因此只能使用 反射 獲取 Element[] dexElements 數組 ;


反射獲取系統的 Element[] dexElements , 需要分三個階段完成 ;

第一階段 : 在 Context 中調用 getClassLoader() 方法 , 可以 拿到 PathClassLoader ;

classLoader

第二階段 : 從 PathClassLoader 父類 BaseDexClassLoader 中 找到 DexPathList ;

// 階段一二 : 調用 getClassLoader() 方法可以獲取 PathClassLoader 對象// 從 PathClassLoader 對象中獲取 private final DexPathList pathList 成員var pathListField = reflexField(classLoader, "DexPathList");// 獲取 classLoader 對象對應的 DexPathList pathList 成員var pathList = pathListField.get(classLoader)

第三階段 : 獲取封裝在 DexPathList 類中的 Element[] dexElements 數組 ;

/*1 . 獲得系統 DexPathList 中的 Element[] dexElements 數組第一階段 : 在 Context 中調用 getClassLoader() 方法 , 可以拿到 PathClassLoader ;第二階段 : 從 PathClassLoader 父類 BaseDexClassLoader 中找到 DexPathList ;第三階段 : 獲取封裝在 DexPathList 類中的 Element[] dexElements 數組 ;上述的 DexPathList 對象 是 BaseDexClassLoader 的私有成員Element[] dexElements 數組 也是 DexPathList 的私有成員因此只能使用反射獲取 Element[] dexElements 數組*/// 階段一二 : 調用 getClassLoader() 方法可以獲取 PathClassLoader 對象// 從 PathClassLoader 對象中獲取 private final DexPathList pathList 成員var pathListField = reflexField(classLoader, "DexPathList");// 獲取 classLoader 對象對應的 DexPathList pathList 成員var pathList = pathListField.get(classLoader)//階段三 : 獲取封裝在 DexPathList 類中的 Element[] dexElements 數組var dexElementsField = reflexField(pathList, "dexElements")// 獲取 pathList 對象對應的 Element[] dexElements 數組成員var dexElements : Array<Any> = dexElementsField.get(pathList) as Array<Any>

總結

以上是生活随笔為你收集整理的【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 反射获取系统的 Element[] dexElements )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。