【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName 函数 )
文章目錄
- 前言
- 一、DexPathList.java#findClass 類加載函數源碼分析
- 二、DexFile.java#loadClassBinaryName 函數源碼分析
前言
上一篇博客 【Android 逆向】Dalvik 函數抽取加殼 ( 類加載流程分析 | ClassLoader#loadClass 函數分析 | BaseDexClassLoader#findClass 分析 ) 分析到 , 類加載流程中 , 在 BaseDexClassLoader 中的 findClass 方法中 , 主要調用 DexPathList pathList 成員的 findClass 函數查找類 ;
一、DexPathList.java#findClass 類加載函數源碼分析
在 DexPathList.java#findClass 方法中 ,
首先 , 遍歷 Element[] dexElements 成員 , 每個 Element 元素都封裝了一個 DexFile , 即 dex 文件 ;
DexFile dex = element.dexFile;然后嘗試從 dex 文件中加載 Java 類 ;
Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);DexPathList.java#findClass 類加載函數源碼 :
/*** 一對條目列表,與{@code ClassLoader}關聯。* 其中一個列表是索引/資源路徑&mdash;通常提及* 作為“類路徑”&mdash;列表和其他名稱目錄* 包含本機代碼庫。類路徑條目可以是以下任一項:* 一個{@code.jar}或{@code.zip}文件,其中包含一個可選的* 頂級{@code classes.dex}文件以及任意資源,* 或者是一個普通的{@code.dex}文件(不可能與* 資源)。* * <p>此類還包含使用這些列表進行查找的方法* 課程和資源</p>*/ /*package*/ final class DexPathList {/*** 索引/資源(類路徑)元素的列表。* 應該稱為pathElements,但Facebook應用程序使用反射* 要修改“dexElements”(http://b/7726934).*/private final Element[] dexElements;/*** 在所指向的某個dex文件中查找命名類* 這個例子。這將在最早的列表中找到一個* 路徑元素。如果已找到類但尚未找到* 已定義,則此方法將在定義中定義它* 構造此實例時使用的上下文。* * @param要查找的類的名稱* @param查找類時遇到抑制異常* @返回已命名的類或{@code null}(如果該類不是空的)* 在任何dex文件中找到*/public Class findClass(String name, List<Throwable> suppressed) {// 對 DexPathList 中的 Element 數組進行遍歷 for (Element element : dexElements) {// 每個 Element 元素都封裝了一個 DexFile , 即 dex 文件DexFile dex = element.dexFile;if (dex != null) {// 嘗試從 dex 文件中加載 Java 類 // ★ 核心跳轉Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);if (clazz != null) {return clazz;}}}if (dexElementsSuppressedExceptions != null) {suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));}return null;} }源碼路徑 : /libcore/dalvik/src/main/java/dalvik/system/DexPathList.java#findClass
二、DexFile.java#loadClassBinaryName 函數源碼分析
在 DexFile.java#loadClassBinaryName 函數中 , 調用了 defineClass 方法 , 在 defineClass 方法中 , 調用了 native 函數 defineClassNative ;
在 DexFile.java 的 loadClass 函數中 , 也會調用 DexFile.java#loadClassBinaryName 函數 , 進行類的加載 ;
DexFile.java#loadClassBinaryName 函數源碼 :
/*** 操縱DEX文件。這門課在原則上與我們的課相似* {@link java.util.zip.ZipFile}。它主要由類裝入器使用。* <p>* 注意,我們不直接打開并讀取這里的DEX文件。它們是內存映射的* 由VM只讀。*/ public final class DexFile {/*** 加載一個類。成功返回類或{@code null}引用* 一旦失敗。* <p>* 如果不是從類加載器調用此函數,則很可能不是* 去做你想做的事。改用{@link Class#forName(String)}。* <p>* 如果類* 找不到,因為在每個* 在我們查看的第一個DEX文件中找不到類的時間。* * @param name* 類名,看起來應該像“java/lang/String”* * @param裝載機* 嘗試加載類的類加載器(在大多數情況下* 方法的調用方* * @返回表示類的{@link Class}對象,或{@code null}* 如果無法加載該類*/public Class loadClass(String name, ClassLoader loader) {String slashName = name.replace('.', '/');return loadClassBinaryName(slashName, loader, null);}/*** 請參閱{@link#loadClass(String,ClassLoader)}。* * 這需要一個“二進制”類名來更好地匹配類加載器語義。* * @隱藏*/public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) {return defineClass(name, loader, mCookie, suppressed);}private static Class defineClass(String name, ClassLoader loader, int cookie,List<Throwable> suppressed) {Class result = null;try {result = defineClassNative(name, loader, cookie);} catch (NoClassDefFoundError e) {if (suppressed != null) {suppressed.add(e);}} catch (ClassNotFoundException e) {if (suppressed != null) {suppressed.add(e);}}return result;}// ★ 核心跳轉private static native Class defineClassNative(String name, ClassLoader loader, int cookie)throws ClassNotFoundException, NoClassDefFoundError; }源碼路徑 : /libcore/dalvik/src/main/java/dalvik/system/DexFile.java#loadClassBinaryName
總結
以上是生活随笔為你收集整理的【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName 函数 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 逆向】Dalvik 函
- 下一篇: 【Android 逆向】Dalvik 函