Android 逆向整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 )(代
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 逆向整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 )(代相关的知识,希望对你有一定的参考价值。
前言
上一篇博客 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexFile loadDexFile 函数 | 构造函数 | openDexFile 函数 ) 中 , 介绍了 DexFile 中加载 Dex 文件的流程 , 入口函数是 DexFile 的 loadDexFile 函数 , 然后在该函数中调用了 DexFile
的构造函数 , 之后再构造函数中调用了 openDexFile 函数 , 最终调用了 openDexFileNative 方法 ;
openDexFileNative
方法在 C++ 代码中实现 , 本篇博客介绍该 C++ 实现 ;
一、查找 DexFile 对应的 C++ 代码
1、根据 Native 文件命名惯例查找 C++ 代码
DexFile.java 的路径是
/libcore/dalvik/src/main/java/dalvik/system/DexFile.java
按照 android 的惯例 , DexFile 对应的 C++ 代码名称一般是将路径中的 “/” 替换成 “_” ;
dalvik/system/DexFile.java 的 Java 代码对应的 C++ 代码一般命名为 dalvik_system_DexFile.cpp , 尝试在 dalvik 模块中搜索该 C++ 代码 ;
dalvik_system_DexFile.cpp 源码路径为 /dalvik/vm/native/dalvik_system_DexFile.cpp
2、根据方法名查找
也可以直接在 http://androidxref.com/4.4.4_r1/ 地址的 Full Search 中 , 搜索 openDexFileNative
方法 , 注意选中 dalvik 模块 ;
二、dalvik_system_DexFile.cpp 源码分析
在下面的代码中 , 从参数张红获取 dex 文件路径 和 优化 dex 文件路径 ,
// dex 文件路径
StringObject* sourceNameObj = (StringObject*) args[0];
// 优化 dex 文件路径
StringObject* outputNameObj = (StringObject*) args[1];
判断 dex 文件是否以 " .dex " 结尾 ,
hasDexExtension(sourceName)
如果文件是以 .dex 结尾 , 则进入 dvmRawDexFileOpen 函数执行 ,
dvmRawDexFileOpen(sourceName, outputName, &pRawDexFile, false)
dalvik_system_DexFile.cpp 相关代码示例 :
/*
* 私有静态int-openDexFileNative(字符串sourceName、字符串outputName、,
* int标志)引发IOException
*
* 打开一个DEX文件,返回指向内部数据结构的指针。
*
* “sourceName”应该指向“source”jar或DEX文件。
*
* 如果“outputName”为空,则DEX代码将自动查找
* 缓存目录中的“优化”版本,必要时创建它。
* 如果它不为NULL,则将使用指定的文件。
*
* TODO:目前,我们很乐意多次打开同一个文件。
* 为了优化这一点,我们可以在散列中搜索现有条目
* 表并重新计算它们。需要原子操作或添加“已同步”
* 指向在此调用的非本机代码。
*
* TODO:应该使用“long”作为指针。
*/
static void Dalvik_dalvik_system_DexFile_openDexFileNative(const u4* args,
JValue* pResult)
// dex 文件路径
StringObject* sourceNameObj = (StringObject*) args[0];
// 优化 dex 文件路径
StringObject* outputNameObj = (StringObject*) args[1];
DexOrJar* pDexOrJar = NULL;
JarFile* pJarFile;
RawDexFile* pRawDexFile;
char* sourceName;
char* outputName;
if (sourceNameObj == NULL)
dvmThrowNullPointerException("sourceName == null");
RETURN_VOID();
sourceName = dvmCreateCstrFromString(sourceNameObj);
if (outputNameObj != NULL)
outputName = dvmCreateCstrFromString(outputNameObj);
else
outputName = NULL;
/*
* 我们必须处理可能有人试图
* 打开我们的一个引导类DEX文件。依赖项集
* 将是不同的,因此优化的结果可能是不同的
* 不同,这意味着我们实际上需要有两个版本的
* 优化的DEX:只知道引导类的一部分的DEX
* 这条路,一条知道里面一切的路。后者可能会
* 基于稍后出现的类优化字段/方法访问
* 在类路径中。
*
* 我们不能让用户定义的类加载器打开它并开始使用
* 类,因为代码的优化形式跳过了一些
* 我们通常使用的方法和场分辨率,以及
* 我们会有错误的语义。
*
* 我们必须拒绝尝试从启动时手动打开DEX文件
* 类路径。最简单的方法是通过文件名,这很有效
* 由于名称的变化(例如“/system/framework//ext.jar”)而无法使用
* 结果我们命中了不同的dalvik缓存项。也很好
* 如果调用方指定了自己的输出文件。
*/
if (dvmClassPathContains(gDvm.bootClassPath, sourceName))
ALOGW("Refusing to reopen boot DEX '%s'", sourceName);
dvmThrowIOException(
"Re-opening BOOTCLASSPATH DEX files is not allowed");
free(sourceName);
free(outputName);
RETURN_VOID();
/*
* 如果名称以“.DEX”结尾,请尝试直接将其作为DEX打开。
* 如果失败了(或者一开始就没有尝试过),可以尝试一下
* 拉链里面有一个“classes.dex”。
*/
if (hasDexExtension(sourceName)
// 如果文件是以 .dex 结尾 , 则进入 dvmRawDexFileOpen 函数执行
&& dvmRawDexFileOpen(sourceName, outputName, &pRawDexFile, false) == 0)
ALOGV("Opening DEX file '%s' (DEX)", sourceName);
pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
pDexOrJar->isDex = true;
pDexOrJar->pRawDexFile = pRawDexFile;
pDexOrJar->pDexMemory = NULL;
else if (dvmJarFileOpen(sourceName, outputName, &pJarFile, false) == 0)
ALOGV("Opening DEX file '%s' (Jar)", sourceName);
pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
pDexOrJar->isDex = false;
pDexOrJar->pJarFile = pJarFile;
pDexOrJar->pDexMemory = NULL;
else
ALOGV("Unable to open DEX file '%s'", sourceName);
dvmThrowIOException("unable to open DEX file");
if (pDexOrJar != NULL)
pDexOrJar->fileName = sourceName;
addToDexFileTable(pDexOrJar);
else
free(sourceName);
free(outputName);
RETURN_PTR(pDexOrJar);
以上是关于Android 逆向整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 )(代的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 )
Android 逆向整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )(代码片
Android 逆向整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )
Android 逆向整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexFile loadDexFile 函数 | 构造函数 | openDexFile 函数 )(代码片
Android 逆向整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 中根据 File 加载 DexFile | loadDexFile 分析 )(代
Android 逆向整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 )(代