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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 将系统的 dexElements 与 应用的 dexElements 合并 | 替换操作 )

發(fā)布時(shí)間:2025/6/17 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 将系统的 dexElements 与 应用的 dexElements 合并 | 替换操作 ) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 一、將系統(tǒng)的 dexElements 與 應(yīng)用的 dexElements 合并
  • 二、Element[] dexElements 替換操作
  • 三、完整 dex 加載源碼



參考博客 :

  • 【Android 安全】DEX 加密 ( 常用 Android 反編譯工具 | apktool | dex2jar | enjarify | jd-gui | jadx )
  • 【Android 安全】DEX 加密 ( Proguard 簡(jiǎn)介 | Proguard 相關(guān)網(wǎng)址 | Proguard 混淆配置 )
  • 【Android 安全】DEX 加密 ( Proguard 簡(jiǎn)介 | 默認(rèn) ProGuard 分析 )
  • 【Android 安全】DEX 加密 ( Proguard keep 用法 | Proguard 默認(rèn)混淆結(jié)果 | 保留類(lèi)及成員混淆結(jié)果 | 保留注解以及被注解修飾的類(lèi)/成員/方法 )
  • 【Android 安全】DEX 加密 ( Proguard 混淆 | 混淆后的報(bào)錯(cuò)信息 | Proguard 混淆映射文件 mapping.txt )
  • 【Android 安全】DEX 加密 ( Proguard 混淆 | 將混淆后的報(bào)錯(cuò)信息轉(zhuǎn)為原始報(bào)錯(cuò)信息 | retrace.bat 命令執(zhí)行目錄 | 暴露更少信息 )
  • 【Android 安全】DEX 加密 ( DEX 加密原理 | DEX 加密簡(jiǎn)介 | APK 文件分析 | DEX 分割 )
  • 【Android 安全】DEX 加密 ( 多 DEX 加載 | 65535 方法數(shù)限制和 MultiDex 配置 | PathClassLoader 類(lèi)加載源碼分析 | DexPathList )
  • 【Android 安全】DEX 加密 ( 不同 Android 版本的 DEX 加載 | Android 8.0 版本 DEX 加載分析 | Android 5.0 版本 DEX 加載分析 )
  • 【Android 安全】DEX 加密 ( DEX 加密使用到的相關(guān)工具 | dx 工具 | zipalign 對(duì)齊工具 | apksigner 簽名工具 )
  • 【Android 安全】DEX 加密 ( 支持多 DEX 的 Android 工程結(jié)構(gòu) )
  • 【Android 安全】DEX 加密 ( 代理 Application 開(kāi)發(fā) | multiple-dex-core 依賴(lài)庫(kù)開(kāi)發(fā) | 配置元數(shù)據(jù) | 獲取 apk 文件并準(zhǔn)備相關(guān)目錄 )
  • 【Android 安全】DEX 加密 ( 代理 Application 開(kāi)發(fā) | 解壓 apk 文件 | 判定是否是第一次啟動(dòng) | 遞歸刪除文件操作 | 解壓 Zip 文件操作 )
  • 【Android 安全】DEX 加密 ( 代理 Application 開(kāi)發(fā) | 加載 dex 文件 | 反射獲取系統(tǒng)的 Element[] dexElements )
  • 【Android 安全】DEX 加密 ( 代理 Application 開(kāi)發(fā) | 加載 dex 文件 | 使用反射獲取方法創(chuàng)建本應(yīng)用的 dexElements | 各版本創(chuàng)建 dex 數(shù)組源碼對(duì)比 )

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

app 是主應(yīng)用 , 其 Module 類(lèi)型是 “Phone & Tablet Module” ,

multiple-dex-core 是 Android 依賴(lài)庫(kù) , 其作用是解密并加載多 DEX 文件 , 其 Module 類(lèi)型是 “Android Library” ,

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


在 【Android 安全】DEX 加密 ( 代理 Application 開(kāi)發(fā) | multiple-dex-core 依賴(lài)庫(kù)開(kāi)發(fā) | 配置元數(shù)據(jù) | 獲取 apk 文件并準(zhǔn)備相關(guān)目錄 ) 博客中講解了 multiple-dex-core 依賴(lài)庫(kù)開(kāi)發(fā) , 每次啟動(dòng)都要解密與加載 dex 文件 , 在該博客中講解到了 獲取 apk 文件 , 并準(zhǔn)備解壓目錄 ;

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

在 【Android 安全】DEX 加密 ( 代理 Application 開(kāi)發(fā) | 加載 dex 文件 | 反射獲取系統(tǒng)的 Element[] dexElements )博客中講解了 dex 文件加載第一階段 , 獲取系統(tǒng)中的 Element[] dexElements ;

在 【Android 安全】DEX 加密 ( 代理 Application 開(kāi)發(fā) | 加載 dex 文件 | 使用反射獲取方法創(chuàng)建本應(yīng)用的 dexElements | 各版本創(chuàng)建 dex 數(shù)組源碼對(duì)比 ) 博客中講解了講解 dex 文件加載操作 第二階段 , 創(chuàng)建本應(yīng)用的 dex 文件數(shù)組 Element[] dexElements ;


本博客中主要講解 剩余的兩個(gè)操作 :

  • 系統(tǒng)加載的 Element[] dexElements 數(shù)組 與 我們 自己的 Element[] dexElements 數(shù)組 進(jìn)行合并操作 ;
  • 替換 ClassLoader 加載過(guò)程中的 Element[] dexElements 數(shù)組 ( 封裝在 DexPathList 中 )




一、將系統(tǒng)的 dexElements 與 應(yīng)用的 dexElements 合并



加載 dex 文件 需要執(zhí)行的步驟 :

  • 1 . 獲得系統(tǒng) DexPathList 中的 Element[] dexElements 數(shù)組
    ( libcore/dalvik/src/main/java/dalvik/system/DexPathList.java )

  • 2 . 在 本應(yīng)用 中創(chuàng)建 Element[] dexElements 數(shù)組 , 用于存放解密后的 dex 文件

  • 3 . 將 系統(tǒng)加載的 Element[] dexElements 數(shù)組 與 我們自己的 Element[] dexElements 數(shù)組進(jìn)行 合并操作

  • 4 . 替換 ClassLoader 加載過(guò)程中的 Element[] dexElements 數(shù)組 ( 封裝在 DexPathList 中 )


之前的博客中已經(jīng)講解了前兩個(gè)步驟的操作 , 開(kāi)始執(zhí)行第三個(gè)步驟 , 將 系統(tǒng)加載的 Element[] dexElements 數(shù)組 與 我們自己的 Element[] dexElements 數(shù)組進(jìn)行合并操作 ;

首先 創(chuàng)建數(shù)組 , 數(shù)組類(lèi)型與 dexElements 數(shù)組類(lèi)型相同 ,

將 dexElements 數(shù)組中的元素拷貝到 newElements 前半部分, 拷貝元素個(gè)數(shù)是 dexElements.size ,

將 addElements 數(shù)組中的元素拷貝到 newElements 后半部分, 拷貝元素個(gè)數(shù)是 dexElements.size ;


代碼示例 :

/*3 . 將 系統(tǒng)加載的 Element[] dexElements 數(shù)組與 我們自己的 Element[] dexElements 數(shù)組進(jìn)行合并操作首先創(chuàng)建數(shù)組 , 數(shù)組類(lèi)型與 dexElements 數(shù)組類(lèi)型相同將 dexElements 數(shù)組中的元素拷貝到 newElements 前半部分, 拷貝元素個(gè)數(shù)是 dexElements.size將 addElements 數(shù)組中的元素拷貝到 newElements 后半部分, 拷貝元素個(gè)數(shù)是 dexElements.size*/var newElements: Array<Any> = java.lang.reflect.Array.newInstance(dexElements.javaClass.componentType,dexElements.size + addElements.size) as Array<Any>// 將 dexElements 數(shù)組中的元素拷貝到 newElements 前半部分, 拷貝元素個(gè)數(shù)是 dexElements.sizeSystem.arraycopy(dexElements, 0, newElements, 0, dexElements.size)// 將 addElements 數(shù)組中的元素拷貝到 newElements 后半部分, 拷貝元素個(gè)數(shù)是 dexElements.sizeSystem.arraycopy(addElements, 0, newElements, dexElements.size, addElements.size)



二、Element[] dexElements 替換操作



替換 ClassLoader 加載過(guò)程中的 Element[] dexElements 數(shù)組 ( 封裝在 DexPathList 中 )

/*4 . 替換 ClassLoader 加載過(guò)程中的 Element[] dexElements 數(shù)組 ( 封裝在 DexPathList 中 )*/dexElementsField.set(pathList, newElements)

該 Field 字段由之前反射獲得 ;

//階段三 : 獲取封裝在 DexPathList 類(lèi)中的 Element[] dexElements 數(shù)組var dexElementsField = reflexField(pathList, "dexElements")// 獲取 pathList 對(duì)象對(duì)應(yīng)的 Element[] dexElements 數(shù)組成員var dexElements : Array<Any> = dexElementsField.get(pathList) as Array<Any>



三、完整 dex 加載源碼



/*** 加載 dex 文件集合* 這些 dex 文件已經(jīng)解密* 參考博客 : https://hanshuliang.blog.csdn.net/article/details/109608605** 創(chuàng)建自己的 Element[] dexElements 數(shù)組* ( libcore/dalvik/src/main/java/dalvik/system/DexPathList.java )* 然后將 系統(tǒng)加載的 Element[] dexElements 數(shù)組 與 我們自己的 Element[] dexElements 數(shù)組進(jìn)行合并操作* 00:17:07*/fun loadDex(dexFiles : ArrayList<File>, optimizedDirectory : File) : Unit{/*需要執(zhí)行的步驟1 . 獲得系統(tǒng) DexPathList 中的 Element[] dexElements 數(shù)組( libcore/dalvik/src/main/java/dalvik/system/DexPathList.java )2 . 在本應(yīng)用中創(chuàng)建 Element[] dexElements 數(shù)組 , 用于存放解密后的 dex 文件3 . 將 系統(tǒng)加載的 Element[] dexElements 數(shù)組與 我們自己的 Element[] dexElements 數(shù)組進(jìn)行合并操作4 . 替換 ClassLoader 加載過(guò)程中的 Element[] dexElements 數(shù)組 ( 封裝在 DexPathList 中 )*//*1 . 獲得系統(tǒng) DexPathList 中的 Element[] dexElements 數(shù)組第一階段 : 在 Context 中調(diào)用 getClassLoader() 方法 , 可以拿到 PathClassLoader ;第二階段 : 從 PathClassLoader 父類(lèi) BaseDexClassLoader 中找到 DexPathList ;第三階段 : 獲取封裝在 DexPathList 類(lèi)中的 Element[] dexElements 數(shù)組 ;上述的 DexPathList 對(duì)象 是 BaseDexClassLoader 的私有成員Element[] dexElements 數(shù)組 也是 DexPathList 的私有成員因此只能使用反射獲取 Element[] dexElements 數(shù)組*/// 階段一二 : 調(diào)用 getClassLoader() 方法可以獲取 PathClassLoader 對(duì)象// 從 PathClassLoader 對(duì)象中獲取 private final DexPathList pathList 成員var pathListField = reflexField(classLoader, "DexPathList");// 獲取 classLoader 對(duì)象對(duì)應(yīng)的 DexPathList pathList 成員var pathList = pathListField.get(classLoader)//階段三 : 獲取封裝在 DexPathList 類(lèi)中的 Element[] dexElements 數(shù)組var dexElementsField = reflexField(pathList, "dexElements")// 獲取 pathList 對(duì)象對(duì)應(yīng)的 Element[] dexElements 數(shù)組成員var dexElements : Array<Any> = dexElementsField.get(pathList) as Array<Any>/*2 . 在本應(yīng)用中創(chuàng)建 Element[] dexElements 數(shù)組 , 用于存放解密后的 dex 文件不同的 Android 版本中 , 創(chuàng)建 Element[] dexElements 數(shù)組的方法不同 , 這里需要做兼容*/var makeDexElements: Methodvar addElements : Array<Any> = Array(0, {})if(Build.VERSION.SDK_INT <=Build.VERSION_CODES.LOLLIPOP_MR1){ // 5.0, 5.1 makeDexElements// 反射 5.0, 5.1, 6.0 版本的 DexPathList 中的 makeDexElements 方法makeDexElements = reflexMethod(pathList, "makeDexElements",ArrayList::class.java, File::class.java, ArrayList::class.java)var suppressedExceptions: ArrayList<IOException> = ArrayList<IOException>()addElements = makeDexElements.invoke(pathList, dexFiles,optimizedDirectory,suppressedExceptions) as Array<Any>}else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ // 7.0 以上版本 makePathElements// 反射 7.0 以上版本的 DexPathList 中的 makeDexElements 方法makeDexElements = reflexMethod(pathList, "makePathElements",ArrayList::class.java, File::class.java, ArrayList::class.java)var suppressedExceptions: ArrayList<IOException> = ArrayList<IOException>()addElements = makeDexElements.invoke(pathList, dexFiles,optimizedDirectory,suppressedExceptions) as Array<Any>}/*3 . 將 系統(tǒng)加載的 Element[] dexElements 數(shù)組與 我們自己的 Element[] dexElements 數(shù)組進(jìn)行合并操作首先創(chuàng)建數(shù)組 , 數(shù)組類(lèi)型與 dexElements 數(shù)組類(lèi)型相同將 dexElements 數(shù)組中的元素拷貝到 newElements 前半部分, 拷貝元素個(gè)數(shù)是 dexElements.size將 addElements 數(shù)組中的元素拷貝到 newElements 后半部分, 拷貝元素個(gè)數(shù)是 dexElements.size*/var newElements: Array<Any> = java.lang.reflect.Array.newInstance(dexElements.javaClass.componentType,dexElements.size + addElements.size) as Array<Any>// 將 dexElements 數(shù)組中的元素拷貝到 newElements 前半部分, 拷貝元素個(gè)數(shù)是 dexElements.sizeSystem.arraycopy(dexElements, 0, newElements, 0, dexElements.size)// 將 addElements 數(shù)組中的元素拷貝到 newElements 后半部分, 拷貝元素個(gè)數(shù)是 dexElements.sizeSystem.arraycopy(addElements, 0, newElements, dexElements.size, addElements.size)/*4 . 替換 ClassLoader 加載過(guò)程中的 Element[] dexElements 數(shù)組 ( 封裝在 DexPathList 中 )*/dexElementsField.set(pathList, newElements)}

截至到此處 , dex 加載工作基本完成 ;

總結(jié)

以上是生活随笔為你收集整理的【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 将系统的 dexElements 与 应用的 dexElements 合并 | 替换操作 )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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