前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 逆向】Dalvik 函数抽取加壳 ③ ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName函数 )

【Android 逆向】Dalvik 函数抽取加壳 ③ ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName函数 )

作者头像
韩曙亮
发布2023-03-30 09:40:08
2750
发布2023-03-30 09:40:08
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

前言

上一篇博客 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | ClassLoader#loadClass 函数分析 | BaseDexClassLoader#findClass 分析 ) 分析到 , 类加载流程中 , 在 BaseDexClassLoader 中的 findClass 方法中 , 主要调用 DexPathList pathList 成员的 findClass 函数查找类 ;

一、DexPathList.java#findClass 类加载函数源码分析


DexPathList.java#findClass 方法中 ,

首先 , 遍历 Element[] dexElements 成员 , 每个 Element 元素都封装了一个 DexFile , 即 dex 文件 ;

代码语言:javascript
复制
DexFile dex = element.dexFile;

然后尝试从 dex 文件中加载 Java 类 ;

代码语言:javascript
复制
Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);

DexPathList.java#findClass 类加载函数源码 :

代码语言:javascript
复制
/**
 * 一对条目列表,与{@code ClassLoader}关联。
 * 其中一个列表是索引/资源路径—通常提及
 * 作为“类路径”—列表和其他名称目录
 * 包含本机代码库。类路径条目可以是以下任一项:
 * 一个{@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 函数源码 :

代码语言:javascript
复制
/**
 * 操纵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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 前言
  • 一、DexPathList.java#findClass 类加载函数源码分析
  • 二、DexFile.java#loadClassBinaryName 函数源码分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档