Android第一代落地DEX加固总结
字数 1354 2025-08-22 12:23:00

Android第一代DEX落地加固技术详解

一、DEX加固基础理论

1.1 DEX文件关键字段

DEX加固主要涉及DEX头部的三个关键字段:

  1. checksum:文件校验码,使用alder32算法校验文件除去magic、checksum外余下的所有文件区域
  2. signature:使用SHA-1算法hash除去magic、checksum和signature外余下的所有文件区域
  3. file_size:DEX文件的大小

1.2 加固基本原理

DEX加固的核心是一个拼接过程:

成品 = 待加固app(加密后) + 解密dex

加固后需要手动修改上述三个字段以保证DEX文件的合法性。

二、加固流程

2.1 加密源APP流程

  1. 加密源APP
  2. 将加密后的源APP放在壳(classes.dex)后面,最后4个字节填充源APP大小
  3. 修改壳的checksum、signature和file_size

2.2 解壳流程

  1. 主动读取classes.dex末端的加密数据
  2. 调用本APK的解密方法进行解密
  3. 动态加载解密之后的APK

三、关键技术实现

3.1 动态加载解密APK

使用DexClassLoader加载解密后的APK,并替换LoadedApk中的mClassLoader字段:

RefInvoke.setFieldOjbect("android.app.LoadedApk","mClassLoader",
    weakReference.get(), DexClassLoader);

3.2 加密和组装实现

public static void main(String[] args) {
    try {
        // 读取源APK和壳DEX
        File payloadSrcFile = new File("原apk路径");
        File unShellDexFile = new File("壳dex路径");
        
        // 加密源APK(此处使用异或加密示例)
        byte[] payloadArray = encrpt(readFileBytes(payloadSrcFile), 0x66);
        byte[] unShellDexArray = readFileBytes(unShellDexFile);
        
        int payloadLen = payloadArray.length;
        int unShellDexLen = unShellDexArray.length;
        int totalLen = payloadLen + unShellDexLen + 4; // 最后4字节存储源APP大小
        
        byte[] newdex = new byte[totalLen];
        
        // 组装新DEX
        System.arraycopy(unShellDexArray, 0, newdex, 0, unShellDexLen);
        System.arraycopy(payloadArray, 0, newdex, unShellDexLen, payloadLen);
        System.arraycopy(intToByte(payloadLen), 0, newdex, totalLen-4, 4);
        
        // 修正DEX头
        fixFileSizeHeader(newdex);
        fixSHA1Header(newdex);
        fixCheckSumHeader(newdex);
        
        // 保存新DEX
        File file = new File("输出路径");
        if (!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream localFileOutputStream = new FileOutputStream(file);
        localFileOutputStream.write(newdex);
        localFileOutputStream.flush();
        localFileOutputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

3.3 System.arraycopy方法详解

方法原型:

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

参数说明:

  • src: 源数组
  • srcPos: 源数组开始复制的位置
  • dest: 目标数组
  • destPos: 目标数组开始粘贴的位置
  • length: 要复制的元素数量

四、解壳APK实现要点

4.1 AndroidManifest.xml配置

解壳APP不需要启动界面,直接配置主启动Activity为待加固APP的入口:

<activity android:name="待加固APP的主Activity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

4.2 Application类配置

在解壳APP的AndroidManifest.xml中添加描述信息:

<meta-data 
    android:name="APPLICATION_CLASS_NAME" 
    android:value="com.android.sourceapp.XApplication"/>

其中com.android.sourceapp.XApplication是源APP的一个简单Application类:

package com.android.sourceapp;

import android.app.Application;

public class XApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
    }
}

五、实践注意事项

  1. 加固后处理:生成加密后的dex后,直接替换原APP的classes.dex,无需重新签名
  2. 首次运行:第一次运行会进行解密操作,后续运行直接使用解密后的APK(落地加载特性)
  3. 测试环境:建议在Android 9环境(如雷电模拟器9)进行测试

六、参考实现

  1. DEX头修改函数

    • fixFileSizeHeader():修正DEX文件大小
    • fixSHA1Header():重新计算SHA1签名
    • fixCheckSumHeader():重新计算校验和
  2. 辅助函数

    • readFileBytes():读取文件为字节数组
    • intToByte():整型转字节数组
    • encrpt():加密函数(示例中使用简单异或加密)

七、常见问题解决

  1. Application替换失败:确保meta-data中的APPLICATION_CLASS_NAME指向源APP的正确Application类
  2. 类加载问题:检查DexClassLoader的路径设置和权限
  3. 签名验证:某些APP可能有签名校验,需要在源APP中处理或绕过

通过以上步骤和注意事项,可以实现Android第一代DEX落地加固方案,有效保护APK中的代码安全。

Android第一代DEX落地加固技术详解 一、DEX加固基础理论 1.1 DEX文件关键字段 DEX加固主要涉及DEX头部的三个关键字段: checksum :文件校验码,使用alder32算法校验文件除去magic、checksum外余下的所有文件区域 signature :使用SHA-1算法hash除去magic、checksum和signature外余下的所有文件区域 file_ size :DEX文件的大小 1.2 加固基本原理 DEX加固的核心是一个拼接过程: 加固后需要手动修改上述三个字段以保证DEX文件的合法性。 二、加固流程 2.1 加密源APP流程 加密源APP 将加密后的源APP放在壳(classes.dex)后面,最后4个字节填充源APP大小 修改壳的checksum、signature和file_ size 2.2 解壳流程 主动读取classes.dex末端的加密数据 调用本APK的解密方法进行解密 动态加载解密之后的APK 三、关键技术实现 3.1 动态加载解密APK 使用DexClassLoader加载解密后的APK,并替换LoadedApk中的mClassLoader字段: 3.2 加密和组装实现 3.3 System.arraycopy方法详解 方法原型: 参数说明: src: 源数组 srcPos: 源数组开始复制的位置 dest: 目标数组 destPos: 目标数组开始粘贴的位置 length: 要复制的元素数量 四、解壳APK实现要点 4.1 AndroidManifest.xml配置 解壳APP不需要启动界面,直接配置主启动Activity为待加固APP的入口: 4.2 Application类配置 在解壳APP的AndroidManifest.xml中添加描述信息: 其中 com.android.sourceapp.XApplication 是源APP的一个简单Application类: 五、实践注意事项 加固后处理 :生成加密后的dex后,直接替换原APP的classes.dex,无需重新签名 首次运行 :第一次运行会进行解密操作,后续运行直接使用解密后的APK(落地加载特性) 测试环境 :建议在Android 9环境(如雷电模拟器9)进行测试 六、参考实现 DEX头修改函数 : fixFileSizeHeader() :修正DEX文件大小 fixSHA1Header() :重新计算SHA1签名 fixCheckSumHeader() :重新计算校验和 辅助函数 : readFileBytes() :读取文件为字节数组 intToByte() :整型转字节数组 encrpt() :加密函数(示例中使用简单异或加密) 七、常见问题解决 Application替换失败 :确保meta-data中的APPLICATION_ CLASS_ NAME指向源APP的正确Application类 类加载问题 :检查DexClassLoader的路径设置和权限 签名验证 :某些APP可能有签名校验,需要在源APP中处理或绕过 通过以上步骤和注意事项,可以实现Android第一代DEX落地加固方案,有效保护APK中的代码安全。