【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )
文章目錄
- 前言
- 一、DexPathList 構造函數分析
- 二、DexPathList.makeDexElements 函數分析
- 三、Element 類分析
前言
上一篇博客 【Android 逆向】整體加固脫殼 ( DexClassLoader 加載 dex 流程分析 | 類加載器構造函數分析 | DexPathList 引入 ) 中 , 分析了 DexClassLoader 構造函數的調用流程 , 在構造函數中執行的核心操作就是 在 BaseDexClassLoader 的構造函數中 初始化了 DexPathList 實例對象 ;
本篇博客中重點分析 DexPathList ;
一、DexPathList 構造函數分析
在 DexPathList 構造函數中 , 主要是調用了 makeDexElements() 方法 , 該方法返回 Element[] 數組元素 , 賦值給 private final Element[] dexElements 成員 ;
/*package*/ final class DexPathList {/*** List of dex/resource (class path) elements.* Should be called pathElements, but the Facebook app uses reflection* to modify 'dexElements' (http://b/7726934).*/private final Element[] dexElements;/*** Constructs an instance.** @param definingContext the context in which any as-yet unresolved* classes should be defined* @param dexPath list of dex/resource path elements, separated by* {@code File.pathSeparator}* @param libraryPath list of native library directory path elements,* separated by {@code File.pathSeparator}* @param optimizedDirectory directory where optimized {@code .dex} files* should be found and written to, or {@code null} to use the default* system directory for same*/public DexPathList(ClassLoader definingContext, String dexPath,String libraryPath, File optimizedDirectory) {// 下面的代碼 主要是對 參數合法性判斷 if (definingContext == null) {throw new NullPointerException("definingContext == null");}if (dexPath == null) {throw new NullPointerException("dexPath == null");}if (optimizedDirectory != null) {if (!optimizedDirectory.exists()) {throw new IllegalArgumentException("optimizedDirectory doesn't exist: "+ optimizedDirectory);}if (!(optimizedDirectory.canRead()&& optimizedDirectory.canWrite())) {throw new IllegalArgumentException("optimizedDirectory not readable/writable: "+ optimizedDirectory);}}// 上述代碼是對參數合法性判斷 this.definingContext = definingContext;ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();// 核心邏輯 // 調用 makeDexElements 方法 , 傳入 this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,suppressedExceptions);if (suppressedExceptions.size() > 0) {this.dexElementsSuppressedExceptions =suppressedExceptions.toArray(new IOException[suppressedExceptions.size()]);} else {dexElementsSuppressedExceptions = null;}this.nativeLibraryDirectories = splitLibraryPath(libraryPath);} }源碼路徑 : /libcore/dalvik/src/main/java/dalvik/system/DexPathList.java
二、DexPathList.makeDexElements 函數分析
DexPathList.makeDexElements 函數中 , 主要返回了一個 Element[] 數組 ; Element 是 DexPathList 的內部類 ;
/*package*/ final class DexPathList {/*** Makes an array of dex/resource path elements, one per element of* the given array.*/private static Element[] makeDexElements(ArrayList<File> files, File optimizedDirectory,ArrayList<IOException> suppressedExceptions) {// 創建要返回的 Element 數組對應的集合ArrayList<Element> elements = new ArrayList<Element>();/** 打開并加載 dex 文件 * up front.*/for (File file : files) {File zip = null;DexFile dex = null;String name = file.getName();if (name.endsWith(DEX_SUFFIX)) { // .dex 后綴// dex 后綴是 .dex , 進入該分支 // Raw dex file (not inside a zip/jar).try {// 從文件中加載 dex dex = loadDexFile(file, optimizedDirectory);} catch (IOException ex) {System.logE("Unable to load dex file: " + file, ex);}} else if (name.endsWith(APK_SUFFIX) || name.endsWith(JAR_SUFFIX)|| name.endsWith(ZIP_SUFFIX)) {// .apk , .jar , .zip 后綴 , 命中該分支 zip = file;try {dex = loadDexFile(file, optimizedDirectory);} catch (IOException suppressed) {/** IOException might get thrown "legitimately" by the DexFile constructor if the* zip file turns out to be resource-only (that is, no classes.dex file in it).* Let dex == null and hang on to the exception to add to the tea-leaves for* when findClass returns null.*/suppressedExceptions.add(suppressed);}} else if (file.isDirectory()) {// We support directories for looking up resources.// This is only useful for running libcore tests.elements.add(new Element(file, true, null, null));} else {System.logW("Unknown file type for: " + file);}if ((zip != null) || (dex != null)) {// 調用完畢后 , 如果獲取的 DexFile 不為空 , 創建 Element 對象 , 并加入到 ArrayList 集合中elements.add(new Element(file, false, zip, dex));}}return elements.toArray(new Element[elements.size()]);} }源碼路徑 : /libcore/dalvik/src/main/java/dalvik/system/DexPathList.java
三、Element 類分析
Element 類是 DexPathList 的內部類 , 其第一個成員變量就是 private final File file , 這個就是 dex 文件類 ;
/*package*/ final class DexPathList {/*** Element of the dex/resource file path*//*package*/ static class Element {private final File file;private final boolean isDirectory;private final File zip;private final DexFile dexFile;private ZipFile zipFile;private boolean initialized;public Element(File file, boolean isDirectory, File zip, DexFile dexFile) {this.file = file;this.isDirectory = isDirectory;this.zip = zip;this.dexFile = dexFile;}} }總結
以上是生活随笔為你收集整理的【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 逆向】整体加固脱壳 (
- 下一篇: 【Android 逆向】整体加固脱壳 (