【Android 安全】DEX 加密 ( 代理 Application 开发 | 解压 apk 文件 | 判定是否是第一次启动 | 递归删除文件操作 | 解压 Zip 文件操作 )

简介: 【Android 安全】DEX 加密 ( 代理 Application 开发 | 解压 apk 文件 | 判定是否是第一次启动 | 递归删除文件操作 | 解压 Zip 文件操作 )

文章目录

一、判定是否是第一次启动

二、递归删除文件操作

三、解压 Zip 文件操作

四、解压操作相关代码



参考博客 :


【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 加密 ( 支持多 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 文件 , 并准备解压目录 ;


本博客中主要讲解 解压 dex 文件操作 ;






一、判定是否是第一次启动


应用启动后 , 获取 apk 文件 , 解压该文件 , 并 解密其中的 dex 文件 , 然后进行 加载 ;


应用每次启动前 , 都要执行上述操作 ;



现在讨论解压文件的细节操作 ;


如果应用是 第一次启动 , 则需要解压该 apk 文件 , 并进行解密 ;


如果应用 不是第一次启动 , 则直接获取之前已经 解压 apk 并解密好的 dex 文件即可 ;



先获取 dexDir 目录中的文件 , 该目录的作用是存 解压后 并 解密 的 dex 文件 ;


 

// app 中存放的是解压后的所有的 apk 文件
        // app 下创建 dexDir 目录 , 将所有的 dex 目录移动到该 deDir 目录中
        // dexDir 目录存放应用的所有 dex 文件
        // 这些 dex 文件都需要进行解密
        var dexDir : File = File(appDir, "dexDir")
        // 遍历解压后的 apk 文件 , 将需要加载的 dex 放入如下集合中
        var dexFiles : ArrayList<File> = ArrayList<File>()



如果该 dexDir 目录不存在 , 并且获取的目录子元素数组大小为 0 00 , 说明这是第一次启动 ;


 

// 如果该 dexDir 存在 , 并且该目录不为空 , 并进行 MD5 文件校验
        if( !dexDir.exists() || dexDir.list().size == 0){
            // 将 apk 中的文件解压到了 appDir 目录
        }else{
            // 已经解密完成, 此时不需要解密, 直接获取 dexDir 中的文件即可
        }
    }






二、递归删除文件操作


解压的目标目录 , 如果存在 , 则闪出去该目录 , 注意 递归删除 其 子目录 中的文件 ; ( 该方法一般情况下不会调用 )


 

/**
     * 删除文件, 如果有目录, 则递归删除
     */
    private fun deleteFile(file: File) {
        if (file.isDirectory) {
            val files = file.listFiles()
            for (f in files) {
                deleteFile(f)
            }
        } else {
            file.delete()
        }
    }






三、解压 Zip 文件操作


解压操作主要使用 java.util.zip 包下的 api ;



首先 创建 zip 文件 , 获取 zip 文件中的条目 ;


在最后解压完毕后 , 关闭该 zip 文件 ;


       

// 获取 zip 压缩包文件
            val zipFile = ZipFile(zip)
            // 获取 zip 压缩包中每一个文件条目
            val entries = zipFile.entries()
    ...
            // 关闭 zip 文件
            zipFile.close()



遍历压缩包中的文件 ,


如果 apk 压缩包中含有以下文件 , 这些文件是 V1 签名文件保存目录 , 不需要解压 , 跳过即可 ,


如果该文件条目 , 不是目录 , 说明就是文件 ,


向刚才创建的目录中写出文件 ;


       

// 遍历压缩包中的文件
            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()
                }
            }






四、解压操作相关代码


 

/**
     * 解压文件
     * @param zip 被解压的压缩包文件
     * @param dir 解压后的文件存放目录
     */
    fun unZipApk(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()
                }
            }
            zipFile.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    /**
     * 删除文件, 如果有目录, 则递归删除
     */
    private fun deleteFile(file: File) {
        if (file.isDirectory) {
            val files = file.listFiles()
            for (f in files) {
                deleteFile(f)
            }
        } else {
            file.delete()
        }
    }




目录
相关文章
|
12月前
|
移动开发 安全 Java
Android历史版本与APK文件结构
通过以上内容,您可以全面了解Android的历史版本及其主要特性,同时掌握APK文件的结构和各部分的作用。这些知识对于理解Android应用的开发和发布过程非常重要,也有助于在实际开发中进行高效的应用管理和优化。希望这些内容对您的学习和工作有所帮助。
1269 83
|
11月前
|
安全 算法 小程序
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
757 28
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
|
前端开发 Java 编译器
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
368 36
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
431 1
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
12月前
|
算法 安全 Java
即时通讯安全篇(一):正确地理解和使用Android端加密算法
本文主要讨论针对Android这样的移动端应用开发时,如何正确的理解目前常用的加密算法,为诸如即时通讯应用的实战开发,如何在合适的场景下选择适合的算法,提供一些参考。
380 0
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点讲解了如何使用 Kotlin 实现 AES-256 的加密和解密,并提供了详细的代码示例。通过生成密钥、加密和解密数据等步骤,展示了如何在 Kotlin 项目中实现数据的安全加密。
998 1
|
12月前
|
云安全 安全 数据建模
《数字证书:互联网世界的"身份证"与"防盗门"》 ——揭秘网络安全背后的加密江湖
在2023年某深夜,上海陆家嘴金融公司机房遭遇黑客攻击,神秘青铜大门与九大掌门封印的玉牌突现,阻止了入侵。此门象征数字证书,保障网络安全。数字证书如验钞机识别假币,保护用户数据。它通过SSL/TLS加密、CA认证和非对称加密,构建安全通信。证书分为DV、OV、EV三类,分别适合不同场景。忽视证书安全可能导致巨额损失。阿里云提供一站式证书服务,助力企业部署SSL证书,迎接未来量子计算和物联网挑战。
|
安全 算法 网络协议
【网络原理】——图解HTTPS如何加密(通俗简单易懂)
HTTPS加密过程,明文,密文,密钥,对称加密,非对称加密,公钥和私钥,证书加密
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将从网络安全漏洞、加密技术和安全意识三个方面进行探讨,旨在提高读者对网络安全的认识和防范能力。通过分析常见的网络安全漏洞,介绍加密技术的基本原理和应用,以及强调安全意识的重要性,帮助读者更好地保护自己的网络信息安全。
257 10
|
存储 SQL 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将介绍网络安全的重要性,分析常见的网络安全漏洞及其危害,探讨加密技术在保障网络安全中的作用,并强调提高安全意识的必要性。通过本文的学习,读者将了解网络安全的基本概念和应对策略,提升个人和组织的网络安全防护能力。