android 脱壳 之 dvmDexFileOpenPartial断点脱壳原理分析
导语:
笔者主要研究方向是网络通信协议的加密解密, 对应用程序加固脱壳技术很少研究, 脱壳壳经历更是经历少之甚少。但是脱壳作为一个逆向工程师必备技能,怎能不会,于是找了几个脱壳的帖子,看别人是怎么剖壳,笔者看过阿里加固壳,360加固的壳,爱加密的壳都被脱壳,无一幸免。加固/剖壳技术其实与笔者研究通信协议加密解密时一样一样的。 我看到几个这些帖子, 给出自己的一下总结。
1.大部分壳都会反调试结合使用, 因为脱壳必然需要动态调试,然后dump dex 文件。为了防止动态调试,不部分的壳保护程序都会使用的反调试。 关于反调试笔者已经谈过,在这个就不谈了。
2. 大部分壳我们可以对int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)函数下断点。然后dump 地址:addr, 长度:len 到文件中。然后就算脱壳成功能, 有的壳,会对dvmDexFileOpenPartial 进行重写, 笔者分析的360的壳机重写啦。所以了解为什么脱壳需要对dvmDexFileOpenPartial 下断点,以及这个函数都干了些啥。
分析结论:
Android系统启动时会先启动init进程,init进程会启动zygote进程,该进程会为每个要启动的App进程孵化出一个Davlik虚拟机实例.Zygote 进程还会启动optdex进程,这个进程将要运行App的DEX文件映射到内存中,然后校验,优化,转成虚拟机能够操作的Dex对象DvmDex.
dvmDexFileOpenPartial的函数原型如下:int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
参数1:加载的DEX文件在内存中的基址.(也就是DEX.035)
参数2:加载的DEX文件的文件长度,
参数3:出参, DEX 文件转成DvmDex结构,里面包含Dex文件的类,字段,方法,字符串信息。Dalivk操作Dex文件的对象这是结构结构体
分析过程:
就提分析如下:dexopt对应源码在: /dalvik/dexopt/OptMain.cpp, 查看main函数
这里根据解析文件方式不同,选择不同方案进行选择方法,我们这里研究是dex文件,所以跟进函数fromDex函数。截取fromDex 函数的片段:
dvmPreForDexOpt函数的作用在对函数进行优化前,检测Dalivk虚拟机是否进入工作状态, 如果进入工作状态就会调用dvmContinueOptimization对Dex文件进行优化。 我们 进入dvmContinueOptimization跟进函数看看他是如何进行优化的。 截取代码片段分析
通过共享内存映射,将Dex文件映射到内存中。
发现这里会调用我们主角 dvmDexFileOpenPartial , 这个函数主要功能就是完成将内存中DexDile 转化成DilivikVM的Dex文件DvmDex。我们查看一下DvmDex文件的结构:
这里我们看到我们熟知的字符串对象,内对象,方法, 字符等等信息,根据这些信息,我们就可以运行我们的DexFile文件了。