Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >dex文件打开

dex文件打开

作者头像
全栈程序员站长
发布于 2022-09-14 08:16:45
发布于 2022-09-14 08:16:45
3.6K0
举报

大家好,又见面了,我是你们的朋友全栈君。

我们知道,要读取一个类代码,或读取类里的方法代码,都需要打开Dex文件,然后按前面介绍的格式去分析,并且读取出相应的内容,才可以给虚拟机进行解释执行。现在,我们就来学习和分析Dex文件的读取相关的代码。如下:

/*

*Open the specified file read-only. We memory-map the entire thingand

*parse the contents.

*

*This will be called on non-Zip files, especially during VM startup,so

*we don’t want to be too noisy about certain types of failure. (Do

*we want a “quiet” flag?)

*

*On success, we fill out the contents of “pArchive” andreturn 0.

*/

intdexZipOpenArchive(const char* fileName, ZipArchive* pArchive)

{

上面这段代码输入文件名称,输出文件内容对象。

int fd, err;

LOGV(“Opening archive ‘%s’ %p\n”,fileName, pArchive);

memset(pArchive, 0, sizeof(ZipArchive));

上面这行代码清空Dex文件对象。

fd = open(fileName, O_RDONLY, 0);

if (fd < 0) {

err = errno ? errno : -1;

LOGV(“Unable to open ‘%s’: %s\n”,fileName, strerror(err));

return err;

}

这段代码调用函数open来打开文件,如果不成功就输出出错提示。

return dexZipPrepArchive(fd, fileName,pArchive);

这行代码调用函数dexZipPrepArchive来生成dex文件对象。

}

在上面这个函数里,主要输入两个参数:fileName和pArchive。其中fileName是输入要打开的dex文件名称,当然它是包括文件路径的;pArchive是打开这个文件后用来表达dex文件内容的对象。代码具体过程是先调用函数memset来清空pArchive文件对象,然后调用函数open打开文件,把文件句柄传送给函数dexZipPrepArchive进

行文件分析,并把相应内容设置给文件对象pArchive。

下面来看一下pArchive对象的结构,如下:

typedefstruct ZipArchive {

/* open Zip archive */

int mFd;

这个zip文件的文件句柄,也就是上面调用open函数打开成功后句柄。

/* mapped file */

MemMapping mMap;

这个是把zip文件映射到内存,加快文件读取,提高文件读取效率。

/* number of entries in the Zip archive */

int mNumEntries;

这个是保存zip文件的入口。

/*

* We know how many entries are in the Ziparchive, so we can have a

* fixed-size hash table. We probe oncollisions.

*/

int mHashTableSize;

ZipHashEntry* mHashTable;

这里是通过hash的方法来提高读取文件速度。

}ZipArchive;

ZipArchive结构保存zip文件的句柄、文件内容映射内存地址、zip入口个数和入口地址(使用hash表达)。

这一段代码实现打开Dex文件,由于Dex文件采用zip压缩,所以需要先从zip文件里解压出来,才可以恢复到Dex原始数据。

下面来分析这个函数代码,如下:

intdexZipPrepArchive(int fd, const char* debugFileName, ZipArchive*pArchive)

{

这个函数输入文件句柄、文件名称、压缩文件对象。

MemMapping map;

int err;

map.addr = NULL;

memset(pArchive, 0, sizeof(*pArchive));

pArchive->mFd = fd;

这行代码是保存文件句柄。

if (sysMapFileInShmem(pArchive->mFd,&map) != 0) {

err = -1;

LOGW(“Map of ‘%s’ failed\n”,debugFileName);

goto bail;

}

if (map.length < kEOCDLen) {

err = -1;

LOGV(“File ‘%s’ too small to be zip(%zd)\n”, debugFileName,map.length);

goto bail;

}

这段代码映射文件数据到内存。

if (!parseZipArchive(pArchive, &map)) {

err = -1;

LOGV(“Parsing ‘%s’ failed\n”,debugFileName);

goto bail;

}

这段代码是分析zip文件。

/* success */

err = 0;

sysCopyMap(&pArchive->mMap, &map);

map.addr = NULL;

这段代码拷贝到映射位置。

bail:

if (err != 0)

dexZipCloseArchive(pArchive);

if (map.addr != NULL)

sysReleaseShmem(&map);

return err;

}

函数dexZipPrepArchive的处理,主要就是先保存文件句柄,然后创建文件内存映射,调用parseZipArchive函数来分析zip的所有入口点,并记录到相应的hash表里,最后调用sysCopyMap函数来保存到zip文件对象结构里。

由上面分析可知,dex文件是压缩成zip文件,这样可以减少占用空间。dex文件在系统里是怎么样打开的过程呢?其它经过下面的过程:

1)系统初始化虚拟机时,会初始化原始方法gDvmNativeMethodSet集合。

2)在原始方法集合里有一个函数集合dvm_dalvik_system_DexFile,注册它为Ldalvik/system/DexFile串,当虚拟机调用DexFile相关函数时,就会调用这些函数来处理Dex文件。

3)在处理Dex文件时,会调用函数集合:dvm_dalvik_system_DexFile,这个函数集合里,主要有如下函数:

constDalvikNativeMethod dvm_dalvik_system_DexFile[] = {

{“openDexFile”, “(Ljava/lang/String;Ljava/lang/String;I)I”,

Dalvik_dalvik_system_DexFile_openDexFile},

{“closeDexFile”, “(I)V”,

Dalvik_dalvik_system_DexFile_closeDexFile},

{“defineClass”, “(Ljava/lang/String;Ljava/lang/ClassLoader;ILjava/security/ProtectionDomain;)Ljava/lang/Class;”,

Dalvik_dalvik_system_DexFile_defineClass},

{“getClassNameList”, “(I)[Ljava/lang/String;”,

Dalvik_dalvik_system_DexFile_getClassNameList},

{“isDexOptNeeded”, “(Ljava/lang/String;)Z”,

Dalvik_dalvik_system_DexFile_isDexOptNeeded},

{NULL, NULL, NULL },

};

openDexFile方法对应的原始函数是Dalvik_dalvik_system_DexFile_openDexFile,它是打开Dex文件函数。

closeDexFile方法对应的原始函数是Dalvik_dalvik_system_DexFile_closeDexFile,它是关闭已经打开的Dex文件函数。

4)在Dalvik_dalvik_system_DexFile_openDexFile函数里,调用函数dvmJarFileOpen打开JAR或者ZIP压缩的文件。

5)在dvmJarFileOpen函数里,调用dexZipOpenArchive来处理ZIP文件,调用dexZipFindEntry函数读取ZIP解压的文件,调用dvmDexFileOpenFromFd函数读取相应的类数据到内存,并返回给虚拟机。

从上面可知调用函数Dalvik_dalvik_system_DexFile_openDexFile来打开Dex文件,这个函数的源码如下:

staticvoid Dalvik_dalvik_system_DexFile_openDexFile(const u4* args,

JValue* pResult)

{

StringObject* sourceNameObj =(StringObject*) args[0];

这行是输入的Jar或Dex文件名参数。

StringObject* outputNameObj =(StringObject*) args[1];

这行是输出的文件名参数。

int flags = args[2];

这行是处理的标示。

DexOrJar* pDexOrJar = NULL;

JarFile* pJarFile;

RawDexFile* pRawDexFile;

char* sourceName;

char* outputName;

if (sourceNameObj == NULL) {

dvmThrowException(“Ljava/lang/NullPointerException;”,NULL);

RETURN_VOID();

}

这段代码是当输入文件名称为空对象时,就抛出异常。

sourceName =dvmCreateCstrFromString(sourceNameObj);

这行代码调用函数dvmCreateCstrFromString把java字符串转换C字符串,由于Java对象表示的字符串并不能立即就使用到C语言里,所以需要转换才能使用。

if (outputNameObj != NULL)

outputName =dvmCreateCstrFromString(outputNameObj);

else

outputName = NULL;

这段代码是同样把输出字符串转换C字符串。

/*

* We have to deal with the possibility thatsomebody might try to

* open one of our bootstrap class DEXfiles. The set of dependencies

* will be different, and hence the resultsof optimization might be

* different, which means we’d actually needto have two versions of

* the optimized DEX: one that only knowsabout part of the boot class

* path, and one that knows about everythingin it. The latter might

* optimize field/method accesses based on aclass that appeared later

* in the class path.

*

* We can’t let the user-defined classloader open it and start using

* the classes, since the optimized form ofthe code skips some of

* the method and field resolution that wewould ordinarily do, and

* we’d have the wrong semantics.

*

* We have to reject attempts to manuallyopen a DEX file from the boot

* class path. The easiest way to do thisis by filename, which works

* out because variations in name (e.g.”/system/framework/./ext.jar”)

* result in us hitting a differentdalvik-cache entry. It’s also fine

* if the caller specifies their own outputfile.

*/

if(dvmClassPathContains(gDvm.bootClassPath, sourceName)) {

LOGW(“Refusing to reopen boot DEX’%s’\n”, sourceName);

dvmThrowException(“Ljava/io/IOException;”,

“Re-opening BOOTCLASSPATH DEXfiles is not allowed”);

free(sourceName);

RETURN_VOID();

}

这段代码是判断用户是否加载系统目录下面的Dex文件,如果加载就要拒绝这样的操作,因为系统启动时已经加载了一份这样的优化代码,没有必要再次加载一次。

/*

* Try to open it directly as a DEX. Ifthat fails, try it as a Zip

* with a “classes.dex” inside.

*/

if (dvmRawDexFileOpen(sourceName,outputName, &pRawDexFile, false) == 0) {

LOGV(“Opening DEX file ‘%s'(DEX)\n”, sourceName);

pDexOrJar = (DexOrJar*)malloc(sizeof(DexOrJar));

pDexOrJar->isDex = true;

pDexOrJar->pRawDexFile = pRawDexFile;

这段代码是尝试加载Dex文件,但基本不存在直接加Dex文件的情况,因此在函数dvmRawDexFileOpen还是空函数,没有实际的内容。

}else if (dvmJarFileOpen(sourceName, outputName, &pJarFile, false)== 0) {

LOGV(“Opening DEX file ‘%s'(Jar)\n”, sourceName);

pDexOrJar = (DexOrJar*)malloc(sizeof(DexOrJar));

pDexOrJar->isDex = false;

pDexOrJar->pJarFile = pJarFile;

这段代码是加载Jar文件,就是从这里加载Dex文件到缓存里。

}else {

LOGV(“Unable to open DEX file’%s’\n”, sourceName);

dvmThrowException(“Ljava/io/IOException;”,”unable to open DEX file”);

}

if (pDexOrJar != NULL) {

pDexOrJar->fileName = sourceName;

这行代码保存文件名称到Dex文件对象里。

/* add to hash table */

u4 hash = dvmComputeUtf8Hash(sourceName);

这行代码通过文件名称计算HASH串,加速对文件的查找速度。

void* result;

dvmHashTableLock(gDvm.userDexFiles);

result =dvmHashTableLookup(gDvm.userDexFiles, hash, pDexOrJar,

hashcmpDexOrJar, true);

dvmHashTableUnlock(gDvm.userDexFiles);

这段代码添加HASH表里,以便后面查找使用。

if (result != pDexOrJar) {

LOGE(“Pointer has already beenadded?\n”);

dvmAbort();

}

pDexOrJar->okayToFree = true;

}else

free(sourceName);

RETURN_PTR(pDexOrJar);

这行代码返回打开的文件对象。

}

这个函数是通过JAVA调用时输入Dex文件名称,然后加载Dex文件,最后把这个文件名称放到HASH表里,然后返回打开的对象。

在上面的函数里,提到使用dvmJarFileOpen函数找到classes.dex文件,并加载到内存里,然后提供后面的函数使用。现在就来分析这个函数的代码,如下:

intdvmJarFileOpen(const char* fileName, const char* odexOutputName,

JarFile** ppJarFile, bool isBootstrap)

{

在这里提供四个参数,第一个参数fileName是输入的Jar的文件名称;第二个参数odexOutputName是进行优化后的Dex输出文件;第三个参数ppJarFile是已经打开并缓存到内存里的文件对象;第四个参数isBootstrap是指示是否系统里Dex文件。

ZipArchive archive;

DvmDex* pDvmDex = NULL;

char* cachedName = NULL;

bool archiveOpen = false;

bool locked = false;

int fd = -1;

int result = -1;

/* Even if we’re not going to look at thearchive, we need to

* open it so we can stuff it intoppJarFile.

*/

if (dexZipOpenArchive(fileName, &archive)!= 0)

goto bail;

archiveOpen = true;

这段代码是调用前面介绍的函数dexZipOpenArchive来打开Zip文件,并缓存到系统内存里。

/* If we fork/exec into dexopt, don’t letit inherit the archive’s fd.

*/

dvmSetCloseOnExec(dexZipGetArchiveFd(&archive));

这行代码设置当执行完成后,关闭这个文件句柄。

/* First, look for a “.odex”alongside the jar file. It will

* have the same name/path except for theextension.

*/

fd = openAlternateSuffix(fileName, “odex”,O_RDONLY, &cachedName);

if (fd >= 0) {

这里优先处理优化的Dex文件。

LOGV(“Using alternate file (odex)for %s …\n”, fileName);

if (!dvmCheckOptHeaderAndDependencies(fd,false, 0, 0, true, true)) {

LOGE(“%s odex has staledependencies\n”, fileName);

free(cachedName);

close(fd);

fd = -1;

goto tryArchive;

} else {

LOGV(“%s odex has gooddependencies\n”, fileName);

//TODO: make sure that the .odexactually corresponds

// to the classes.dex inside thearchive (if present).

// For typical use there will beno classes.dex.

}

}else {

ZipEntry entry;

tryArchive:

/*

* Pre-created .odex absent or stale. Look inside the jar for a

* “classes.dex”.

*/

entry = dexZipFindEntry(&archive,kDexInJarName);

这行代码是从压缩包里找到Dex文件,然后打开这个文件。

if (entry != NULL) {

bool newFile = false;

/*

* We’ve found the one we want. Seeif there’s an up-to-date copy

* in the cache.

*

* On return, “fd” will beseeked just past the “opt” header.

*

* If a stale .odex file is presentand classes.dex exists in

* the archive, this will *not*return an fd pointing to the

* .odex file; the fd will point intodalvik-cache like any

* other jar.

*/

if (odexOutputName == NULL) {

cachedName =dexOptGenerateCacheFileName(fileName,

kDexInJarName);

if (cachedName == NULL)

goto bail;

这段代码是把Dex文件进行优化处理,并输出到指定的文件。

} else {

cachedName =strdup(odexOutputName);

}

LOGV(“dvmDexCacheStatus:Checking cache for %s (%s)\n”,

fileName, cachedName);

fd = dvmOpenCachedDexFile(fileName,cachedName,

dexGetZipEntryModTime(&archive,entry),

dexGetZipEntryCrc32(&archive,entry),

isBootstrap, &newFile,/*createIfMissing=*/true);

这段代码创建缓存的优化文件。

if (fd < 0) {

LOGI(“Unable to open orcreate cache for %s (%s)\n”,

fileName, cachedName);

goto bail;

}

locked = true;

/*

* If fd points to a new file(because there was no cached version,

* or the cached version was stale),generate the optimized DEX.

* The file descriptor returned isstill locked, and is positioned

* just past the optimization header.

*/

if (newFile) {

u8 startWhen, extractWhen,endWhen;

bool result;

off_t dexOffset, fileLen;

dexOffset = lseek(fd, 0,SEEK_CUR);

result = (dexOffset > 0);

if (result) {

startWhen =dvmGetRelativeTimeUsec();

result =dexZipExtractEntryToFile(&archive, entry, fd);

extractWhen =dvmGetRelativeTimeUsec();

这段代码调用函数dexZipExtractEntryToFile从压缩包里解压文件出来。

}

if (result) {

result =dvmOptimizeDexFile(fd, dexOffset,

dexGetZipEntryUncompLen(&archive,entry),

fileName,

dexGetZipEntryModTime(&archive,entry),

dexGetZipEntryCrc32(&archive,entry),

isBootstrap);

这段代码调用函数dvmOptimizeDexFile对Dex文件进行优化处理。

}

if (!result) {

LOGE(“Unable toextract+optimize DEX from ‘%s’\n”,

fileName);

goto bail;

}

endWhen =dvmGetRelativeTimeUsec();

LOGD(“DEX prep ‘%s’: unzipin %dms, rewrite %dms\n”,

fileName,

(int) (extractWhen -startWhen) / 1000,

(int) (endWhen – extractWhen)/ 1000);

}

} else {

LOGI(“Zip is good, but no %sinside, and no valid .odex “

“file in the samedirectory\n”, kDexInJarName);

goto bail;

}

}

/*

* Map the cached version. This immediatelyrewinds the fd, so it

* doesn’t have to be seeked anywhere inparticular.

*/

if (dvmDexFileOpenFromFd(fd, &pDvmDex)!= 0) {

LOGI(“Unable to map %s in %s\n”,kDexInJarName, fileName);

goto bail;

}

这段代码是调用函数dvmDexFileOpenFromFd来缓存Dex文件,并分析文件的内容。比如标记是否优化的文件,通过签名检查Dex文件是否合法。

if (locked) {

/* unlock the fd */

if (!dvmUnlockCachedDexFile(fd)) {

/* uh oh — this process needs toexit or we’ll wedge the system */

LOGE(“Unable to unlock DEXfile\n”);

goto bail;

}

locked = false;

}

这段代码是保存文件到缓存里,标记这个文件句柄已经保存到缓存。

LOGV(“Successfully opened ‘%s’ in’%s’\n”, kDexInJarName, fileName);

*ppJarFile = (JarFile*) calloc(1,sizeof(JarFile));

(*ppJarFile)->archive = archive;

(*ppJarFile)->cacheFileName =cachedName;

(*ppJarFile)->pDvmDex = pDvmDex;

cachedName = NULL; // don’t free itbelow

result = 0;

这段代码已经成功打开压缩包,并读取Dex文件到内存缓存,这里只是设置一些相关信息返回前面的函数处理。

bail:

/* clean up, closing the open file */

if (archiveOpen && result != 0)

dexZipCloseArchive(&archive);

free(cachedName);

if (fd >= 0) {

if (locked)

(void) dvmUnlockCachedDexFile(fd);

close(fd);

}

return result;

}

本函数主要流程是打开压缩文件,然后找到Dex文件,读取出来,并进行分析,然后拷贝到缓存里,再返回给调用函数

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/153520.html原文链接:https://javaforall.cn

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

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

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Android动态加载入坑指南
曾几何时,国内各大公司掀起了一股研究Android动态加载的技术,两年多过去了,动态加载技术俨然成了Android开发中必须掌握的技术。那么动态加载技术是什么呢,这里谈谈我的个人看法,如有雷同,纯属偶然。 什么是动态加载技术 对于动态加载的概念,没有一个权威的定义,参考网上的解释,我们举一个例子,动态加载代码就是通过在运行时加载外部代码(磁盘,网络等)改变程序行为的技术(感觉有点像装饰者模式)。主要目的是为了达到让用户不用重新安装APK就能升级应用的功能。 为了加深大家对这种概念的理解,我们结合pc端来说说
xiangzhihong
2018/02/05
2.3K0
Android动态加载入坑指南
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexFile loadDexFile 函数 | 构造函数 | openDexFile 函数 )
上一篇博客 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 中根据 File 加载 DexFile | loadDexFile 分析 ) 中 , 介绍了 DexPathList 中通过 File 生成 DexFile 的源码 , 在 makeDexElements 中调用了 loadDexFile 方法 , 在 loadDexFile 又有调用了 DexFile.loadDexFile 函数 , 用于生成 DexFile 实例对象 ;
韩曙亮
2023/03/30
5140
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 )
上一篇博客 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexFile loadDexFile 函数 | 构造函数 | openDexFile 函数 ) 中 , 介绍了 DexFile 中加载 Dex 文件的流程 , 入口函数是 DexFile 的 loadDexFile 函数 , 然后在该函数中调用了 DexFile 的构造函数 , 之后再构造函数中调用了 openDexFile 函数 , 最终调用了 openDexFileNative 方法 ;
韩曙亮
2023/03/30
5260
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 )
Android类加载之PathClassLoader和DexClassLoader
任何结论在没有经过实际检验之前都不能够确定一定没问题。三年前写的文章回过头来发现有些部分内容是有问题的(PS:这的确比较尴尬),再次对结果进行验证之后重新修改了之前的结论。幸亏文章阅读量不是很多,希望被误导的同学能够在其他地方得到正确结论。
静默加载
2020/05/29
2.6K0
【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )
上一篇博客 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 ) 中 , 分析了 DexPrepare.cpp 中 dvmContinueOptimizati() 方法 , 在其中调用了 rewriteDex() 方法 , 重写 DEX 文件 ;
韩曙亮
2023/03/30
4050
【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | oat_file_assistant.cc 中涉及的 oat 文件生成流程 )
在上一篇博客 【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 ) 中 , 分析了 ART 虚拟机下 DexClassLoader 类加载器加载 dex 文件的 Java 层流程 , 与 Dalvik 虚拟机下基本一致 , 从 native 层开始不一致 , 本篇博客开始分析 native 层的类加载流程 ;
韩曙亮
2023/03/30
8500
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 )
上一篇博客 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 ) 中 , dalvik_system_DexFile.cpp 的 Dalvik_dalvik_system_DexFile_openDexFileNative() 方法中 , 调用了 RawDexFile.cpp 中的 dvmRawDexFileOpen() 方法 ;
韩曙亮
2023/03/30
3150
【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )
上一篇博客 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 ) 中 , 在 RawDexFile.cpp 中的 dvmRawDexFileOpen() 方法中 , 调用了 DexPrepare.cpp 的 dvmOptimizeDexFile() 函数 , 对 DEX 文件进行了优化 ;
韩曙亮
2023/03/30
6150
【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )
Android 2.3中的LinearAlloc
在2.3版本Apk安装时 , 会进行Dexopt , 如果单个Dex中的class过大/method过多 , 就会导致LinearAlloc为Class/Method的内存分配不足 , 从而让Dexopt进程挂掉.
None_Ling
2020/12/03
7120
Android 2.3中的LinearAlloc
【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 )
上一篇博客 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 ) 中 , DexPrepare.cpp 中的 dvmOptimizeDexFile() 方法是用于优化 dex 文件的 , 其中调用了 /bin/dexopt 可执行程序优化 dex 文件 ; 在 /dalvik/dexopt/OptMain.cpp 源码中的 main 函数的 dex 优化分支中 , 调用了 fromDex() 函数 , 在该函数中 , 又调用了 DexPrepare.cpp 中的 dvmContinueOptimizati() 方法 , 执行真正的 dex 优化操作 ;
韩曙亮
2023/03/30
3080
【胖虎的逆向之路】04——脱壳(一代壳)原理&脱壳相关概念详解
在上文中,我们讲解了关于Android脱壳的基本办法和实际操作,现在我们来针对脱壳(一代壳)的原理和脱壳相关的基础知识介绍,由于作者能力有限,会尽力的详细描述 一代壳脱壳 的流程及原理,如本文中有任何错误,烦请指正,感谢~
胖虎哥
2023/05/10
9190
【胖虎的逆向之路】04——脱壳(一代壳)原理&脱壳相关概念详解
Dalvik,ART与ODEX简析
如果你有这样的问题: 1.Dalvik和ART的区别 2.DEX在Dalvik转化为ODEX和ART中转化为ODEX的过程有上面区别 3.multidex在dalvik上起作用,ART上使用的也是multidex么(如果不是的话在application中写入multidex.install会对apk启动造成影响么)
Anymarvel
2018/10/22
1.6K0
Dalvik,ART与ODEX简析
【Android 逆向】整体加固脱壳 ( 脱壳点简介 | 修改系统源码进行脱壳 )
在上一篇博客 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 rewriteDex 函数分析 | 脱壳点 | 获取 dex 文件在内存中的首地址 ) 中 , 提到了
韩曙亮
2023/03/30
1.6K0
dex文件解析(第三篇)「建议收藏」
dex文件是Android系统中的一种文件,是一种特殊的数据格式,和APK、jar 等格式文件类似。 能够被DVM识别,加载并执行的文件格式。 简单说就是优化后的android版.exe。每个apk安装包里都有。包含应用程序的全部操作指令以及运行时数据。 相对于PC上的java虚拟机能运行.class;android上的Davlik虚拟机能运行.dex。
全栈程序员站长
2022/08/03
1.7K0
dex文件解析(第三篇)「建议收藏」
Android逆向笔记 —— DEX 文件格式解析
系列第一篇文章就分析过 Class 文件格式,我们都知道 .java 源文件经过编译器编译会生成 JVM 可识别的 .class 文件。在 Android 中,不管是 Dalvik 还是 Art,和 JVM 的区别还是很大的。Android 系统并不直接使用 Class 文件,而是将所有的 Class 文件聚合打包成 DEX 文件,DEX 文件相比单个单个的 Class 文件更加紧凑,可以直接在 Android Runtime 下执行。
路遥TM
2021/08/31
1.5K0
一个一年没解决的ClassNotFoundException|类加载机制探索
在一开始写Android的时候经常碰到一些ClassNotFoundException,大部分情况下是少导入了什么包导致的。我碰到一个困扰了一年之久的ClassNotFoundException,终于在这两天我解决了这个问题,下面让我给大家表演一下真正的技术。
逮虾户
2020/10/15
2.2K0
一个一年没解决的ClassNotFoundException|类加载机制探索
Android中dex文件的加载与优化流程
逻辑上,可以把dex文件分成3个区,头文件、索引区和数据区。索引区的ids后缀为identifiers的缩写。
全栈程序员站长
2022/09/14
3.1K0
Android中dex文件的加载与优化流程
【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | ART 虚拟机下 DexClassLoader 类加载器脱壳点总结 )
从 /art/runtime/dex_file.cc#DexFile::Open 函数开始分析脱壳点位置 ;
韩曙亮
2023/03/30
8290
模仿手写andfix的实现原理
当公司的项目出现问题了,早期的老套路子是解决bug,重新发新版本apk,但是随着技术不断的更新,线上项目出现严重问题,可以通过进行热修复,在不需要发布新版本的情形下进行问题处理。常见的热修复:阿里家的andfix和sophix, 腾讯家的tinker和QQ空间补丁技术...等等。
包子388321
2020/06/19
6630
模仿手写andfix的实现原理
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 中根据 File 加载 DexFile | loadDexFile 分析 )
上一篇博客 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 ) 中 , 介绍了在 DexPathList 构造函数中调用了 makeDexElements 方法 , 在 makeDexElements 方法中执行了加载 dex 文件的操作 , 将加载后的 dex 文件封装在了 Element 实例对象中 , 并生成了 Element[] 数组 , 每个 dex 文件都对应 Element[] 数组 中的一个元素 ;
韩曙亮
2023/03/30
4620
推荐阅读
Android动态加载入坑指南
2.3K0
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexFile loadDexFile 函数 | 构造函数 | openDexFile 函数 )
5140
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 )
5260
Android类加载之PathClassLoader和DexClassLoader
2.6K0
【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )
4050
【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | oat_file_assistant.cc 中涉及的 oat 文件生成流程 )
8500
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 )
3150
【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )
6150
Android 2.3中的LinearAlloc
7120
【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 )
3080
【胖虎的逆向之路】04——脱壳(一代壳)原理&脱壳相关概念详解
9190
Dalvik,ART与ODEX简析
1.6K0
【Android 逆向】整体加固脱壳 ( 脱壳点简介 | 修改系统源码进行脱壳 )
1.6K0
dex文件解析(第三篇)「建议收藏」
1.7K0
Android逆向笔记 —— DEX 文件格式解析
1.5K0
一个一年没解决的ClassNotFoundException|类加载机制探索
2.2K0
Android中dex文件的加载与优化流程
3.1K0
【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | ART 虚拟机下 DexClassLoader 类加载器脱壳点总结 )
8290
模仿手写andfix的实现原理
6630
【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 中根据 File 加载 DexFile | loadDexFile 分析 )
4620
相关推荐
Android动态加载入坑指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档