ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | Class.cpp#findClassNoInit 函数 | DexFile.cpp#dexFindClass 函数分析 )

2021-12-18 22:03:53  阅读:185  来源: 互联网

标签:DexFile 函数 descriptor cpp Class dexFindClass 加载


文章目录

前言


上一篇博客 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | native 函数查询 | dalvik_system_DexFile.cpp#defineClassNative 函数 ) 中 , dalvik_system_DexFile.cpp#Dalvik_dalvik_system_DexFile_defineClassNative 函数中 , 调用了 Class.cpp#dvmDefineClass 函数 ;





一、Class.cpp#dvmDefineClass 函数分析



在 Class.cpp#dvmDefineClass 函数中 , 主要调用了 Class.cpp#findClassNoInit 函数 ;


Class.cpp#dvmDefineClass 函数源码 :

/*
 * 从指定的DEX文件加载命名类(按描述符)。
 * 由类装入器用于从
 * 虚拟机管理的DEX。
 */
ClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
    Object* classLoader)
{
    assert(pDvmDex != NULL);

    return findClassNoInit(descriptor, classLoader, pDvmDex);
}

源码路径 : /dalvik/vm/oo/Class.cpp#dvmDefineClass





二、Class.cpp#findClassNoInit 函数分析



在 Class.cpp#findClassNoInit 函数中 ,

先调用 dvmLookupClass 函数 , 查询当前已经加载的类 , 一般情况下 , 第一次加载 , 查询到的结果是空的 ;

	// 查询当前已经加载的类 , 第一次加载 , 一般查询不到 
    clazz = dvmLookupClass(descriptor, loader, true);

然后进入到 clazz == NULL 分支 , 执行 dexFindClass 函数 , 此处调用了 dexFindClass , 就是在该函数中 , 恢复被抽取的函数 , 《Android中实现「类方法指令抽取方式」加固方案原理解析 | 作者 : 姜维》 博客 中恢复抽取函数的 hook 点 , 就是 dexFindClass 中 ;

pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);

参考 【Android 逆向】Dalvik 函数抽取加壳 ( Dalvik 下的函数指令抽取与恢复 | dex 函数指令恢复时机点 | 类加载流程 : 加载、链接、初始化 ) 博客 ;


Class.cpp#findClassNoInit 函数源码 :

/*
 * 查找命名类(按描述符)。如果还没有加载,
 * 我们加载并链接它,但不执行<clinit>。(越南船民
 * 事件可能导致初始化的特定限制。)
 * 
 * 如果“pDexFile”为空,我们将在bootclasspath中搜索条目。
 * 
 * 失败时,返回NULL并引发异常。
 * 
 * TODO:我们需要返回一个是否加载了类的指示
 * 使用现有的定义。如果有人故意加载
 * 在同一个类加载器中初始化两次,它们将得到LinkageError,
 * 但无意中同时引用类应该“正常工作”。
 */
static ClassObject* findClassNoInit(const char* descriptor, Object* loader,
    DvmDex* pDvmDex)
{

	// 查询当前已经加载的类 , 第一次加载 , 一般查询不到 
    clazz = dvmLookupClass(descriptor, loader, true);
    if (clazz == NULL) {
		// 第一次查询 , 肯定会进入该分支
        const DexClassDef* pClassDef;

        dvmMethodTraceClassPrepBegin();
        profilerNotified = true;

#if LOG_CLASS_LOADING
        u8 startTime = dvmGetThreadCpuTimeNsec();
#endif

        if (pDvmDex == NULL) {
            assert(loader == NULL);     /* shouldn't be here otherwise */
            pDvmDex = searchBootPathForClass(descriptor, &pClassDef);
        } else {
			// 此处调用了 dexFindClass , 就是在该函数中 , 恢复被抽取的函数 
			//《Android中实现「类方法指令抽取方式」加固方案原理解析 | 作者 : 姜维》 博客
			// 中恢复抽取函数的 hook 点 , 就是 dexFindClass 中
            pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
        }

    return clazz;
}

源码路径 : /dalvik/vm/oo/Class.cpp#findClassNoInit





三、DexFile.cpp#dexFindClass 函数分析



在该 DexFile.cpp#dexFindClass 函数 中 , 恢复被抽取的函数 , 《Android中实现「类方法指令抽取方式」加固方案原理解析 | 作者 : 姜维》 博客 中恢复抽取函数的 hook 点 , 就是 dexFindClass 中 ;


DexFile.cpp#dexFindClass 函数源码 :

/*
 * 按描述符查找类定义条目。
 * 
 * “描述符”应该像“Landroid/debug/Stuff;”。
 */
const DexClassDef* dexFindClass(const DexFile* pDexFile,
    const char* descriptor)
{
    const DexClassLookup* pLookup = pDexFile->pClassLookup;
    u4 hash;
    int idx, mask;

    hash = classDescriptorHash(descriptor);
    mask = pLookup->numEntries - 1;
    idx = hash & mask;

    /*
     * 搜索,直到找到匹配的条目或空插槽。
     */
    while (true) {
        int offset;

        offset = pLookup->table[idx].classDescriptorOffset;
        if (offset == 0)
            return NULL;

        if (pLookup->table[idx].classDescriptorHash == hash) {
            const char* str;

            str = (const char*) (pDexFile->baseAddr + offset);
            if (strcmp(str, descriptor) == 0) {
                return (const DexClassDef*)
                    (pDexFile->baseAddr + pLookup->table[idx].classDefOffset);
            }
        }

        idx = (idx + 1) & mask;
    }
}

源码路径 : /dalvik/libdex/DexFile.cpp#dexFindClass

标签:DexFile,函数,descriptor,cpp,Class,dexFindClass,加载
来源: https://blog.csdn.net/han1202012/article/details/122014404

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有