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

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

文章目录

前言

一、Class.cpp#dvmDefineClass 函数分析

二、Class.cpp#findClassNoInit 函数分析

三、DexFile.cpp#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);

1

参考 【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 {

/*
 * 查找命名类(按描述符)。如果还没有加载,
 * 我们加载并链接它,但不执行<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



目录
相关文章
|
安全 算法 小程序
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
1115 28
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
1049 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
576 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
10772 2
|
6天前
|
存储 弹性计算 缓存
阿里云服务器租赁费用:新版租赁收费标准及活动报价参考
本文更新了2026年阿里云全系列云服务器租赁活动报价,所有特惠资源均可前往阿里云活动中心选购,整体覆盖从个人入门到企业级高性能场景的全梯度需求。其中轻量应用服务器主打极致性价比,2核2G峰值200M带宽配置每日10点、15点限时抢购价仅38元/年,2核4G配置379元/年起;高性价比的经济型e实例、通用算力型u2i实例覆盖2核4G至4核32G全档位,适配开发测试与中小型企业业务;搭载英特尔至强6处理器的第九代c9i企业级实例算力较上代提升20%,支撑高并发生产环境,不同实例规格价差清晰,用户可根据自身业务负载与预算灵活选型。
1633 116
|
7天前
|
人工智能 程序员 API
Codex 接入 DeepSeek-V4-Flash:还能补上识图,提供两套方案
Codex 接入 DeepSeek-V4-Flash 怎么配?本文覆盖 CLI 与桌面端,再用 qwen3-vl-flash 补识图,两套方案可直接照做
1112 5
|
13天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1954 9
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
7天前
|
编解码 人工智能 安全
2核4G/4核8G/8核16G阿里云服务器如何选择实例?经济型e、通用算力型u2i与计算型c9i选哪个?
本文介绍了阿里云2核4G、4核8G、8核16G三档主流配置下经济型e、通用算力型u2i和计算型c9i三种实例的最新活动价格与适用场景。同配置下三者价差显著,以2核4G为例,经济型e低至599.93元/年,计算型c9i则高达1742.08元/年。文章详细解析了各实例的性能定位:经济型e适合轻负载入门场景,u2i兼顾稳定算力与性价比,c9i凭借第9代至强处理器与芯片级安全能力支撑高性能业务。同时提示用户可叠加满减优惠券享受折上折,建议根据业务负载与预算综合决策。
539 112

热门文章

最新文章