【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 )

简介: 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 )

文章目录

前言

一、RawDexFile.cpp 中 dvmRawDexFileOpen() 方法分析

前言

上一篇博客 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 ) 中 , dalvik_system_DexFile.cpp 的 Dalvik_dalvik_system_DexFile_openDexFileNative() 方法中 , 调用了 RawDexFile.cpp 中的 dvmRawDexFileOpen() 方法 ;






一、RawDexFile.cpp 中 dvmRawDexFileOpen() 方法分析


调用 open 函数 以只读形式 , 打开了 DEX 文件 ;


 

dexFd = open(fileName, O_RDONLY);


校验 DEX 文件 ;


verifyMagicAndGetAdler32(dexFd, &adler32) < 0


调用 DexPrepare.cpp 中的 dvmOptimizeDexFile() 函数 , 优化 DEX 文件 ;


     

result = dvmOptimizeDexFile(optFd, dexOffset, fileSize,
                fileName, modTime, adler32, isBootstrap);


源码示例 :


/*
 * 打开一个未优化的 DEX 文件.
 */
/* 请参阅页眉中的文档注释. */
int dvmRawDexFileOpen(const char* fileName, const char* odexOutputName,
    RawDexFile** ppRawDexFile, bool isBootstrap)
{
    /*
     * TODO: 这复制了JarFile.c 中 dvmJarFileOpen() 的大量代码。这应该被重构。
     */
    DvmDex* pDvmDex = NULL;
    char* cachedName = NULL;
    int result = -1;
    int dexFd = -1;
    int optFd = -1;
    u4 modTime = 0;
    u4 adler32 = 0;
    size_t fileSize = 0;
    bool newFile = false;
    bool locked = false;
  // 调用 open 函数 以只读形式 , 打开了 DEX 文件
    dexFd = open(fileName, O_RDONLY);
    if (dexFd < 0) goto bail;
    /* If we fork/exec into dexopt, don't let it inherit the open fd. */
    dvmSetCloseOnExec(dexFd);
  // 校验 DEX 文件 
    if (verifyMagicAndGetAdler32(dexFd, &adler32) < 0) {
        ALOGE("Error with header for %s", fileName);
        goto bail;
    }
    if (getModTimeAndSize(dexFd, &modTime, &fileSize) < 0) {
        ALOGE("Error with stat for %s", fileName);
        goto bail;
    }
  /*
  * 查看缓存的文件是否匹配。如果是这样,optFd将成为一个参考
  * 到缓存文件,并将被查找到刚刚超过“opt”
  * 标题。
  */
    if (odexOutputName == NULL) {
      // 优化的过程 
        cachedName = dexOptGenerateCacheFileName(fileName, NULL);
        if (cachedName == NULL)
            goto bail;
    } else {
        cachedName = strdup(odexOutputName);
    }
    ALOGV("dvmRawDexFileOpen: Checking cache for %s (%s)",
            fileName, cachedName);
    optFd = dvmOpenCachedDexFile(fileName, cachedName, modTime,
        adler32, isBootstrap, &newFile, /*createIfMissing=*/true);
    if (optFd < 0) {
        ALOGI("Unable to open or create cache for %s (%s)",
                fileName, cachedName);
        goto bail;
    }
    locked = true;
    /*
     * 如果optFd指向一个新文件(因为没有缓存
     * 版本,或缓存的版本已过时),生成
     * 优化的DEX。返回的文件描述符仍处于锁定状态,
     * 并定位在刚好超过优化标题的位置。
     */
    if (newFile) {
        u8 startWhen, copyWhen, endWhen;
        bool result;
        off_t dexOffset;
        dexOffset = lseek(optFd, 0, SEEK_CUR);
        result = (dexOffset > 0);
        if (result) {
            startWhen = dvmGetRelativeTimeUsec();
            result = copyFileToFile(optFd, dexFd, fileSize) == 0;
            copyWhen = dvmGetRelativeTimeUsec();
        }
        if (result) {
            result = dvmOptimizeDexFile(optFd, dexOffset, fileSize,
                fileName, modTime, adler32, isBootstrap);
        }
        if (!result) {
            ALOGE("Unable to extract+optimize DEX from '%s'", fileName);
            goto bail;
        }
        endWhen = dvmGetRelativeTimeUsec();
        ALOGD("DEX prep '%s': copy in %dms, rewrite %dms",
            fileName,
            (int) (copyWhen - startWhen) / 1000,
            (int) (endWhen - copyWhen) / 1000);
    }
  /*
  * 映射缓存的版本。这会立即倒带fd,因此
  * 不需要在任何地方寻找。
  */
    if (dvmDexFileOpenFromFd(optFd, &pDvmDex) != 0) {
        ALOGI("Unable to map cached %s", fileName);
        goto bail;
    }
    if (locked) {
        /* unlock the fd */
        if (!dvmUnlockCachedDexFile(optFd)) {
            /* uh oh -- this process needs to exit or we'll wedge the system */
            ALOGE("Unable to unlock DEX file");
            goto bail;
        }
        locked = false;
    }
    ALOGV("Successfully opened '%s'", fileName);
    *ppRawDexFile = (RawDexFile*) calloc(1, sizeof(RawDexFile));
    (*ppRawDexFile)->cacheFileName = cachedName;
    (*ppRawDexFile)->pDvmDex = pDvmDex;
    cachedName = NULL;      // don't free it below
    result = 0;
bail:
    free(cachedName);
    if (dexFd >= 0) {
        close(dexFd);
    }
    if (optFd >= 0) {
        if (locked)
            (void) dvmUnlockCachedDexFile(optFd);
        close(optFd);
    }
    return result;
}


目录
相关文章
|
Linux Android开发
测试程序之提供ioctl函数应用操作GPIO适用于Linux/Android
测试程序之提供ioctl函数应用操作GPIO适用于Linux/Android
497 0
|
Java 调度 Android开发
Android经典实战之Kotlin的delay函数和Java中的Thread.sleep有什么不同?
本文介绍了 Kotlin 中的 `delay` 函数与 Java 中 `Thread.sleep` 方法的区别。两者均可暂停代码执行,但 `delay` 适用于协程,非阻塞且高效;`Thread.sleep` 则阻塞当前线程。理解这些差异有助于提高程序效率与可读性。
457 1
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin中常见作用域函数
**Kotlin作用域函数概览**: `let`, `run`, `with`, `apply`, `also`. `let`安全调用并返回结果; `run`在上下文中执行代码并返回结果; `with`执行代码块,返回结果; `apply`配置对象后返回自身; `also`附加操作后返回自身
431 8
|
Android开发 Kotlin
Android面试题之kotlin中怎么限制一个函数参数的取值范围和取值类型等
在Kotlin中,限制函数参数可通过类型系统、泛型、条件检查、数据类、密封类和注解实现。例如,使用枚举限制参数为特定值,泛型约束确保参数为Number子类,条件检查如`require`确保参数在特定范围内,数据类封装可添加验证,密封类限制为一组预定义值,注解结合第三方库如Bean Validation进行校验。
548 6
|
Android开发
Android构建系统:Android.mk(2)函数详解
Android构建系统:Android.mk(2)函数详解
400 1
|
Android开发
Android Makefile中inherit-product函数和include的区别
Android Makefile中inherit-product函数和include的区别
458 0
|
安全 Java 数据安全/隐私保护
Android和iOS应用程序加固方法详解:混淆、加壳、数据加密、动态加载和数字签名实现
Android和iOS应用程序加固方法详解:混淆、加壳、数据加密、动态加载和数字签名实现
650 0
|
安全 Java Android开发
Android App开发之安全加固中反编译、代码混淆、第三方加固以及重签名的讲解及实战(图文解释 简单易懂)
Android App开发之安全加固中反编译、代码混淆、第三方加固以及重签名的讲解及实战(图文解释 简单易懂)
1060 0
|
监控 Android开发
【Android 逆向】函数拦截 ( GOT 表拦截 与 插桩拦截 | 插桩拦截简介 | 插桩拦截涉及的 ARM 和 x86 中的跳转指令 )
【Android 逆向】函数拦截 ( GOT 表拦截 与 插桩拦截 | 插桩拦截简介 | 插桩拦截涉及的 ARM 和 x86 中的跳转指令 )
363 0
【Android 逆向】函数拦截 ( GOT 表拦截 与 插桩拦截 | 插桩拦截简介 | 插桩拦截涉及的 ARM 和 x86 中的跳转指令 )
|
存储 Android开发
【Android 逆向】函数拦截 ( GOT 表数据结构分析 | 函数根据 GOT 表进行跳转的流程 )
【Android 逆向】函数拦截 ( GOT 表数据结构分析 | 函数根据 GOT 表进行跳转的流程 )
264 0
【Android 逆向】函数拦截 ( GOT 表数据结构分析 | 函数根据 GOT 表进行跳转的流程 )