Android 逆向整体加固脱壳 ( 脱壳起点 : 整体加固脱壳 | Dalvik 脱壳机制 : 利用 DexClassLoader 加载过程进行脱壳 | 相关源码分析 )
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 逆向整体加固脱壳 ( 脱壳起点 : 整体加固脱壳 | Dalvik 脱壳机制 : 利用 DexClassLoader 加载过程进行脱壳 | 相关源码分析 )相关的知识,希望对你有一定的参考价值。
文章目录
一、脱壳起点 : 整体加固脱壳
一代壳 即 DEX 整体加固 , 所有类型的加固 , 都会在最外围加上一层 整体加固的 壳 , 即使进行了 VMP / Dex2C 高级防护 , 最后也会在高级加壳的外层基础上 , 进行 DEX 进行整体加固 ;
拿到应用后 , 先从内存中 , 将 dex 文件 dump 下来 , 拿到 dex 文件 , 然后进行进一步分析 ; 这个 dex 文件 可能是 Java 源码 , 也可能是使用了其它加壳技术 ;
拿到 dex 文件后 , 开始进行后续分析 , 分为以下几种情况 :
- 直接获取 Java 代码 : 如果该加壳只是一代壳 , 那么就可以看到 混淆后的 Java 代码 ;
- 函数抽取 脱壳 : 如果拿到 DEX 文件后 , 发现是空函数 , 则说明在 整体加固 的基础上 还进行了 函数抽取 加壳 ; 下一步针对 函数抽取 脱壳 ;
- VMP 或 Dex2C 脱壳 : 如果拿到 DEX 文件后 , 发现是 Native 函数 , 说明在 整体加固 的基础上进行了 VMP 或者 Dex2C 加壳 ; 下一步 针对 Native 化的函数脱壳 ;
二、Dalvik 脱壳机制 : 利用 DexClassLoader 加载过程进行脱壳
Dalvik 脱壳机制 : 在 Dalvik 下 , 使用自定义 DexClassLoader
加载 dex 字节码文件中的类 , 通过分析 DexClassLoader
源码 , 查找 hook 点 , 进而找到 dex 文件被 加载到内存 中的 起始地址 ;
下面分析 DexClassLoader
加载 dex 文件的流程 ;
1、DexClassLoader 源码
DexClassLoader
继承了 BaseDexClassLoader
类 , 类中没有实现任何业务逻辑 , 只是提供了一个构造函数 ;
DexClassLoader 源码 :
/**
* 从@code.jar和@code.apk文件加载类的类加载器
* 包含@code classes.dex项。这可用于执行未作为应用程序一部分安装的代码。
*
* <p>这个类加载器需要一个应用程序私有的可写目录来缓存优化的类。
* 使用@code Context.getCodeCacheDir()创建
* 这样一个目录:<pre>@code
* File dexOutputDir = context.getCodeCacheDir();
* </pre>
*
* <p><strong>不要在外部存储上缓存优化的类。</strong>
* 外部存储不提供保护您的计算机所需的访问控制
* 防止代码注入攻击的应用程序。
*/
public class DexClassLoader extends BaseDexClassLoader
/**
* 创建一个@code-DexClassLoader来查找解释的和本机的
* 密码解释类可以在包含的一组DEX文件中找到
* 在Jar或APK文件中。
*
* <p>使用指定的字符分隔路径列表
* @code path.separator系统属性,默认为@code:。
*
* @param dexPath 包含类和
* 资源,由@code File.pathSeparator分隔,其中
* android上的默认值为@code”:“
* @param optimizedDirectory 目录,其中包含优化的dex文件
* 应该是书面的;不能为@code null
* @param librarySearchPath 包含本机
* 库,由@code File.pathSeparator分隔;可能是
* @code null
* @param parent 父类加载器
*/
public DexClassLoader(String dexPath, String optimizedDirectory,
String librarySearchPath, ClassLoader parent)
super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);
源码路径 : /libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
2、DexClassLoader 加载 dex 字节码示例
在 【Android 逆向】类加载器 ClassLoader ( 使用 DexClassLoader 动态加载字节码文件 | 拷贝 DEX 文件到内置存储 | 加载并执行 DEX 字节码文件 ) 博客中 , 使用了 DexClassLoader 类加载器 , 加载了内置存储空间的 dex 文件 , 并成功执行了其中的方法 ;
主要的使用流程源码如下 :
/**
* 测试调用 Dex 字节码文件中的方法
* @param context
* @param dexFilePath
*/
private void testDex(Context context, String dexFilePath)
// 优化目录
File optFile = new File(getFilesDir(), "opt_dex");
// 依赖库目录 , 用于存放 so 文件
File libFile = new File(getFilesDir(), "lib_path");
// 初始化 DexClassLoader
DexClassLoader dexClassLoader = new DexClassLoader(
dexFilePath, // Dex 字节码文件路径
optFile.getAbsolutePath(), // 优化目录
libFile.getAbsolutePath(), // 依赖库目录
context.getClassLoader() // 父节点类加载器
);
// 加载 com.example.dex_demo.DexTest 类
// 该类中有可执行方法 test()
Class<?> clazz = null;
try
clazz = dexClassLoader.loadClass("com.example.dex_demo.DexTest");
catch (ClassNotFoundException e)
e.printStackTrace();
// 获取 com.example.dex_demo.DexTest 类 中的 test() 方法
if (clazz != null)
try
// 获取 test 方法
Method method = clazz.getDeclaredMethod("test");
// 获取 Object 对象
Object object = clazz.newInstance();
// 调用 test() 方法
method.invoke(object);
catch (NoSuchMethodException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
catch (InstantiationException e)
e.printStackTrace();
catch (InvocationTargetException e)
e.printStackTrace();
以上是关于Android 逆向整体加固脱壳 ( 脱壳起点 : 整体加固脱壳 | Dalvik 脱壳机制 : 利用 DexClassLoader 加载过程进行脱壳 | 相关源码分析 )的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )(代码片
Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 )
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 文件 )(代