【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | ClassLoader#loadClass 函数分析 | BaseDexClassLoader#findClass 分析 )
文章目錄
- 一、ClassLoader.java#loadClass 類加載函數源碼分析
- 二、BaseDexClassLoader.java#findClass 函數源碼分析
一、ClassLoader.java#loadClass 類加載函數源碼分析
分析類加載器的 雙親委派機制 ; 在 ClassLoader.java 類加載器中 , 雙親委托機制如下 :
首先 , 查看要加載的 Java 類是否已經被加載了 , 如果已經被加載 , 直接返回 ;
// 如果已經被加載了 , 則直接返回Class<?> clazz = findLoadedClass(className);如果沒有被加載過 , 則開始進行雙親委派 , 讓父節點類加載器加載該類 ;
// 如果還沒有進行加載 , 則開始雙親委派 if (clazz == null) {try {// 讓父節點類加載器加載該類 clazz = parent.loadClass(className, false);} catch (ClassNotFoundException e) {// Don't want to see this.}如果父類沒有加載成功 , 返回空 , 這是雙親委派輪完一輪之后 , 發現父節點都沒有加載成功 , 則自己開始加載 , 如果自己加載不了 , 則繼續委托給子節點執行加載 ;
// 這是雙親委派輪完一輪之后 , 發現父節點都沒有加載成功 // 則自己開始加載 // 如果自己加載不了 , 則繼續委托給子節點執行加載if (clazz == null) {clazz = findClass(className);}實際上加載類的方法是 findClass 函數 , 這是類加載過程的核心業務 ;
ClassLoader.java#loadClass 類加載函數源碼 :
public abstract class ClassLoader {/*** 加載具有指定名稱的類,可以選擇在* 裝載。執行以下步驟:* <ol>* <li>調用{@link#findLoadedClass(String)}以確定請求的* 類已加載</li>* <li>如果類尚未加載:在* 父類加載器</li>* <li>如果類尚未加載:調用* {@link#findClass(String)}查找類</li>* </ol>* <p>* <strong>注意:</strong>在Android參考實現中* {@code resolve}參數被忽略;類從不鏈接。* </p>* * @返回{@code Class}對象。* @param className* 要查找的類的名稱。* @param-resolve* 指示加載后是否應解析該類。這* 參數在Android參考實現中被忽略;* 未解析類。* @ClassNotFoundException* 如果找不到該類。*/protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {// 如果已經被加載了 , 則直接返回Class<?> clazz = findLoadedClass(className);// 如果還沒有進行加載 , 則開始雙親委派 if (clazz == null) {try {// 讓父節點類加載器加載該類 clazz = parent.loadClass(className, false);} catch (ClassNotFoundException e) {// Don't want to see this.}// 這是雙親委派輪完一輪之后 , 發現父節點都沒有加載成功 // 則自己開始加載 // 如果自己加載不了 , 則繼續委托給子節點執行加載if (clazz == null) {// ★ 核心跳轉clazz = findClass(className);}}return clazz;} }源碼路徑 : /libcore/libdvm/src/main/java/java/lang/ClassLoader.java#loadClass
二、BaseDexClassLoader.java#findClass 函數源碼分析
在類加載器中 , findClass 函數是核心業務 , 加固廠商在 Dalvik 虛擬機下 , 使用的類加載器是 DexClassLoader , 該類加載器只定義了構造函數 , findClass 函數定義在其父類 BaseDexClassLoader 中 ;
下面分析 BaseDexClassLoader 中的 findClass 方法 ;
在 BaseDexClassLoader 中的 findClass 函數中 , 主要調用了 DexPathList pathList 成員的 findClass 函數 ;
Class c = pathList.findClass(name, suppressedExceptions);DexPathList pathList 成員在 BaseDexClassLoader 構造函數 , 即實例化時 ,
public BaseDexClassLoader(String dexPath, File optimizedDirectory,String libraryPath, ClassLoader parent) {super(parent);this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);}就已經構造完畢 , 其中包含了所有的字節碼類信息 ,
BaseDexClassLoader.java#findClass 函數源碼 :
/*** 用于各種基于dex的數據庫之間的通用功能的基類* {@link ClassLoader}實現。*/ public class BaseDexClassLoader extends ClassLoader {private final DexPathList pathList;/*** 構造一個實例。* * @param dexPath 包含類和* 資源,由{@code File.pathSeparator}分隔,其中* Android上的默認值為{@code”:“}* @param optimizedDirectory 目錄,其中包含優化的dex文件* 應該是書面的;可能是{@code null}* @param libraryPath 包含本機* 庫,由{@code File.pathSeparator}分隔;可能是* {@code null}* @param parent 父類加載器*/public BaseDexClassLoader(String dexPath, File optimizedDirectory,String libraryPath, ClassLoader parent) {super(parent);this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {List<Throwable> suppressedExceptions = new ArrayList<Throwable>();// ★ 核心跳轉Class c = pathList.findClass(name, suppressedExceptions);if (c == null) {ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);for (Throwable t : suppressedExceptions) {cnfe.addSuppressed(t);}throw cnfe;}return c;} }總結
以上是生活随笔為你收集整理的【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | ClassLoader#loadClass 函数分析 | BaseDexClassLoader#findClass 分析 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 逆向】Dalvik 函
- 下一篇: 【Android 逆向】Dalvik 函