【Android 安全】DEX 加密 ( Java 工具开发 | 加密解密算法 API | 编译代理 Application 依赖库 | 解压依赖库 aar 文件 )
参考博客 :
- 【Android 安全】DEX 加密 ( 常用 Android 反编译工具 | apktool | dex2jar | enjarify | jd-gui | jadx )
- 【Android 安全】DEX 加密 ( Proguard 简介 | Proguard 相关网址 | Proguard 混淆配置 )
- 【Android 安全】DEX 加密 ( Proguard 简介 | 默认 ProGuard 分析 )
- 【Android 安全】DEX 加密 ( Proguard keep 用法 | Proguard 默认混淆结果 | 保留类及成员混淆结果 | 保留注解以及被注解修饰的类/成员/方法 )
- 【Android 安全】DEX 加密 ( Proguard 混淆 | 混淆后的报错信息 | Proguard 混淆映射文件 mapping.txt )
- 【Android 安全】DEX 加密 ( Proguard 混淆 | 将混淆后的报错信息转为原始报错信息 | retrace.bat 命令执行目录 | 暴露更少信息 )
- 【Android 安全】DEX 加密 ( DEX 加密原理 | DEX 加密简介 | APK 文件分析 | DEX 分割 )
- 【Android 安全】DEX 加密 ( 多 DEX 加载 | 65535 方法数限制和 MultiDex 配置 | PathClassLoader 类加载源码分析 | DexPathList )
- 【Android 安全】DEX 加密 ( 不同 Android 版本的 DEX 加载 | Android 8.0 版本 DEX 加载分析 | Android 5.0 版本 DEX 加载分析 )
- 【Android 安全】DEX 加密 ( DEX 加密使用到的相关工具 | dx 工具 | zipalign 对齐工具 | apksigner 签名工具 )
- 【Android 安全】DEX 加密 ( 支持多 DEX 的 Android 工程结构 )
- 【Android 安全】DEX 加密 ( 代理 Application 开发 | multiple-dex-core 依赖库开发 | 配置元数据 | 获取 apk 文件并准备相关目录 )
- 【Android 安全】DEX 加密 ( 代理 Application 开发 | 解压 apk 文件 | 判定是否是第一次启动 | 递归删除文件操作 | 解压 Zip 文件操作 )
- 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 反射获取系统的 Element[] dexElements )
- 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 使用反射获取方法创建本应用的 dexElements | 各版本创建 dex 数组源码对比 )
- 【Android 安全】DEX 加密 ( Java 加密工具开发 | 加密解密算法 API | 编译代理 Application 依赖库 | 解压依赖库 aar 文件 ) )
在 【Android 安全】DEX 加密 ( 支持多 DEX 的 Android 工程结构 ) 博客中介绍了 DEX 加密工程的基本结构 ,
app 是主应用 , 其 Module 类型是 “Phone & Tablet Module” ,
multiple-dex-core 是 Android 依赖库 , 其作用是解密并加载多 DEX 文件 , 其 Module 类型是 “Android Library” ,
multiple-dex-tools 是 Java 依赖库 , 其类型是 “Java or Kotlin Library” , 其作用是用于生成主 DEX ( 主 DEX 的作用就是用于解密与加载多 DEX ) , 并且还要为修改后的 APK 进行签名 ;
在 【Android 安全】DEX 加密 ( 代理 Application 开发 | multiple-dex-core 依赖库开发 | 配置元数据 | 获取 apk 文件并准备相关目录 ) 博客中讲解了 multiple-dex-core 依赖库开发 , 每次启动都要解密与加载 dex 文件 , 在该博客中讲解到了 获取 apk 文件 , 并准备解压目录 ;
在 【Android 安全】DEX 加密 ( 代理 Application 开发 | 解压 apk 文件 | 判定是否是第一次启动 | 递归删除文件操作 | 解压 Zip 文件操作 ) 博客中讲解了 apk 文件解压操作 ;
在 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 反射获取系统的 Element[] dexElements )博客中讲解了 dex 文件加载第一阶段 , 获取系统中的 Element[] dexElements ;
在 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 使用反射获取方法创建本应用的 dexElements | 各版本创建 dex 数组源码对比 ) 博客中讲解了讲解 dex 文件加载操作 第二阶段 , 创建本应用的 dex 文件数组 Element[] dexElements ;
在 【Android 安全】DEX 加密 ( 代理 Application 开发 | 加载 dex 文件 | 将系统的 dexElements 与 应用的 dexElements 合并 | 替换操作 ) 博客中讲解了剩余的两个操作 :
- 将 系统加载的 Element[] dexElements 数组 与 我们 自己的 Element[] dexElements 数组 进行合并操作 ;
- 替换 ClassLoader 加载过程中的 Element[] dexElements 数组 ( 封装在 DexPathList 中 )
本博客中介绍 加密解密算法 API , 编译代理 Application 依赖库 , 解压依赖库 aar 文件 ;
一、加密解密算法 API
先写一个加密解密算法 , 该算法用于 dex 文件的 加密 / 解密 操作 ;
初始化 加密 / 解密 算法 : 根据算法类型 , 初始化 加密 / 解密 算法 ;
/**
* 加密解密算法类型
*/
val algorithm = "AES/ECB/PKCS5Padding"
// 初始化加密算法
encryptCipher = Cipher.getInstance(algorithm)
设置密钥 : 获取密钥的 Byte 数组类型 , 并创建 AES 密钥 ;
// 将密钥字符串转为字节数组
var keyByte = pwd.toByteArray()
// 创建密钥
val key = SecretKeySpec(keyByte, "AES")
设置算法类型及密钥 : 加密算法 , 传入 Cipher.ENCRYPT_MODE 参数 , 解密算法 , 传入 Cipher.DECRYPT_MODE 参数 ;
// 设置算法类型, 及密钥
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
// 设置算法类型, 及密钥
decryptCipher.init(Cipher.DECRYPT_MODE, key);
完整代码示例 :
class AES {
/**
* 加密密钥, 16 字节
*/
val DEFAULT_PWD = "kimhslmultiplede"
/**
* 加密解密算法类型
*/
val algorithm = "AES/ECB/PKCS5Padding"
/**
* 加密算法, 目前本应用中只需要加密, 不需要解密
*/
lateinit var encryptCipher: Cipher;
/**
* 解密算法
*/
lateinit var decryptCipher: Cipher;
@ExperimentalStdlibApi
constructor(pwd: String){
// 初始化加密算法
encryptCipher = Cipher.getInstance(algorithm)
// 初始化解密算法
decryptCipher = Cipher.getInstance(algorithm)
// 将密钥字符串转为字节数组
var keyByte = pwd.toByteArray()
// 创建密钥
val key = SecretKeySpec(keyByte, "AES")
// 初始化加密算法
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
// 初始化解密算法
decryptCipher.init(Cipher.DECRYPT_MODE, key);
}
/**
* 加密操作
*/
fun encrypt(contet : ByteArray) : ByteArray{
var result : ByteArray = encryptCipher.doFinal(contet)
return result
}
/**
* 解密操作
*/
fun decrypt(contet : ByteArray) : ByteArray{
var result : ByteArray = decryptCipher.doFinal(contet)
return result
}
}
二、编译代理 Application 依赖库
生成 dex 文件 , 该 dex 文件中只包含解密 其它 dex 的功能
编译配置 : 在 菜单栏 / File / Setting / Build, Execution, Deployment / Compiler 设置界面中 ,
勾选 Compile independent modules in parallel (may require larger ) 选项 ;
编译工程 : 编译工程时会生成 Android 依赖库的 aar 文件 , 生成目录是 module/build/outputs/aar/ 目录下
获取 multiple-dex-core-debug.aar 文件的另外一种方法 : 运行 Gradle 任务中的 Tasks/other/assembleDebug 任务 , 即可生成 multiple-dex-core-debug.aar 文件 ;
解压获取文件 ( 仅做参考 ) : 将
D:\002_Project\002_Android_Learn\DexEncryption\multiple-dex-core\build\outputs\aar
路径下的 multiple-dex-core-debug.aar 文件后缀修改为 .zip
解压上述文件 , 拿到 classes.jar 文件即可 ;
该 classes.jar 就是 multiple-dex-core 的 Android 依赖库中的 ProxyApplication.kt Kotlin 文件 编译出的 jar 包 ;
上述 解压文件仅做 参考 , 实际使用时 , 在程序中使用代码解压 ;
三、解压代理 Application 依赖库 aar 文件
获取 multiple-dex-core-debug.aar 文件对象
// 获取 multiple-dex-core-debug.aar 文件对象
var aarFile = File("multiple-dex-core/build/outputs/aar/multiple-dex-core-debug.aar")
解压上述 multiple-dex-core-debug.aar 文件到 aarUnzip 目录中 , 先创建解压目录 ;
// 解压上述 multiple-dex-core-debug.aar 文件到 aarUnzip 目录中
// 创建解压目录
var aarUnzip = File("multiple-dex-tools/aarUnzip")
正式解压 , unZipAar 方法在下面完整代码中 ;
// 解压操作
unZipAar(aarFile, aarUnzip)
拿到 multiple-dex-core-debug.aar 中解压出来的 classes.jar 文件
// 拿到 multiple-dex-core-debug.aar 中解压出来的 classes.jar 文件
var classesJarFile = File(aarUnzip, "classes.jar")
完整代码示例 :
fun main() {
/*
1 . 生成 dex 文件 , 该 dex 文件中只包含解密 其它 dex 的功能
编译工程
会生成 Android 依赖库的 aar 文件
生成目录是 module/build/outputs/aar/ 目录下
前提是需要在 菜单栏 / File / Setting / Build, Execution, Deployment / Compiler
设置界面中 , 勾选 Compile independent modules in parallel (may require larger )
将 D:\002_Project\002_Android_Learn\DexEncryption\multiple-dex-core\build\outputs\aar
路径下的 multiple-dex-core-debug.aar 文件后缀修改为 .zip
解压上述文件
拿到 classes.jar 文件即可 ;
*/
// 获取 multiple-dex-core-debug.aar 文件对象
var aarFile = File("multiple-dex-core/build/outputs/aar/multiple-dex-core-debug.aar")
// 解压上述 multiple-dex-core-debug.aar 文件到 aarUnzip 目录中
// 创建解压目录
var aarUnzip = File("multiple-dex-tools/aarUnzip")
// 解压操作
unZipAar(aarFile, aarUnzip)
// 拿到 multiple-dex-core-debug.aar 中解压出来的 classes.jar 文件
var classesJarFile = File(aarUnzip, "classes.jar")
}
/**
* 删除文件, 如果有目录, 则递归删除
*/
private fun deleteFile(file: File) {
if (file.isDirectory) {
val files = file.listFiles()
for (f in files) {
deleteFile(f)
}
} else {
file.delete()
}
}
/**
* 解压文件
* @param zip 被解压的压缩包文件
* @param dir 解压后的文件存放目录
*/
fun unZipAar(zip: File, dir: File) {
try {
// 如果存放文件目录存在, 删除该目录
deleteFile(dir)
// 获取 zip 压缩包文件
val zipFile = ZipFile(zip)
// 获取 zip 压缩包中每一个文件条目
val entries = zipFile.entries()
// 遍历压缩包中的文件
while (entries.hasMoreElements()) {
val zipEntry = entries.nextElement()
// zip 压缩包中的文件名称 或 目录名称
val name = zipEntry.name
// 如果 apk 压缩包中含有以下文件 , 这些文件是 V1 签名文件保存目录 , 不需要解压 , 跳过即可
if (name == "META-INF/CERT.RSA" || name == "META-INF/CERT.SF" || (name
== "META-INF/MANIFEST.MF")
) {
continue
}
// 如果该文件条目 , 不是目录 , 说明就是文件
if (!zipEntry.isDirectory) {
val file = File(dir, name)
// 创建目录
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
}
// 向刚才创建的目录中写出文件
val fileOutputStream = FileOutputStream(file)
val inputStream = zipFile.getInputStream(zipEntry)
val buffer = ByteArray(1024)
var len: Int
while (inputStream.read(buffer).also { len = it } != -1) {
fileOutputStream.write(buffer, 0, len)
}
inputStream.close()
fileOutputStream.close()
}
}
// 关闭 zip 文件
zipFile.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
相关文章
- 【Android】Android中WIFI开发总结(一)
- [android]android5大基础组件深入分析
- Android手机打造你的Python&Java开发工具!
- Android开发中这些小技巧
- java泛型操作复习,以及讲解在android中使用的场景
- android:keytool签名查看md5指纹(java 15)
- Atitit.提升软件Web应用程序 app性能的方法原理 h5 js java c# php python android .net
- Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
- Android Java编写布局
- Android的createNewFile()报错提示:java.io.IOException: No such file or directory
- Android 11.0 飞行模式下禁用NFC功能
- 【Android 安全】DEX 加密 ( Java 工具开发 | 解压 apk 文件 | 加密生成 dex 文件 | 打包未签名 apk 文件 | 文件解压缩相关代码 )
- Android java时间戳转年月日时分秒(三十七)
- Android获取Java类名/文件名/方法名/行号(四十)
- 导入Eclipse工程 到 Android Studio
- 最新Android音视频开发进阶指北,音视频入门必备
- 书籍精品Android篇,拿好赶紧收藏
- Android kotlin 编译的报错提示:java.io.FileNotFoundException: db/xxx.db
- Android的java代码(下边红波浪线)中带的箭头(“->”)怎么取消
- Unity 调用Android中的java代码