完整教程:【apktool】Android apk安装包反编译、apk 签名

在这里插入图片描述

一、apk 文件结构

首先是 apk,即安卓程序的安装包。Apk 是一种类似于 Symbian SisSisx 的文件格式。通过将 APK 文件直接传到 Android 模拟器或 Android 手机中执行即可安装。
apk 文件实际上就是一个 MIMEZIP 的压缩包,只不过后缀名进行了更改。

我们可以直接把 .apk 后缀的文件修改成 .zip 后缀的压缩包格式,然后解压后就可以看到内部的文件结构,就像下面这样:
在这里插入图片描述

文件夹结构说明:

  • assets 文件夹: 保存一些额外的资源文件,如游戏的声音文件,字体文件、图片等等,在代码中可以用 AssetManager 获取 assets 文件夹的资源。
  • lib 文件夹: 存放用 C/C++ 编写的,用 NDK 编译生成的 so 文件,供 java 端调用。
  • META-INF 文件夹: 存放 apk 签名信息,用来保证 apk 包的完整性和系统的安全。在 IDE 编译生成一个 apk 包时,会对里面所有的文件做一个校验计算,并把计算结果存放在 META-INF 文件夹内, apk 在安装的时候,系统会按照同样的算法对 apk 包里面的文件做校验,如果结果与 META-INF 里面的值不一样,系统就不会安装这个 apk,这就保证了 apk 包里的文件不能被随意修改和替换。比如拿到一个 apk 包后,如果想要替换里面的一幅图片,一段代码, 或一段版权信息,想直接解压缩、替换再重新打包,基本是不可能的。如此一来就给病毒感染和恶意修改增加了难度,有助于保护系统的安全。
  • res文件夹: 存放资源文件,包括 iconxml 布局文件
  • AndroidManifest.xml文件: 应用程序的清单文件,每个应用都必须定义和包含的,它描述了应用的名字、版本、权限、引用的库文件等信息。
  • classes.dex文件: 传统 Class 文件是由一个 Java 源码文件生成的 .Class 文件,而 Android 是把所有 Class 文件进行合并优化,然后生成一个最终的 class.dex 文件。它包含 APK 的可执行代码,是分析 Android 软件时最常见的目标。由于 dex 文件很难看懂,可通过 apktool 反编译得到 .smali 文件,smali 文件是对 Dalvik 虚拟机字节码的一种解释(也可以说是翻译),并非一种官方标准语言。通过对 smali 文件的解读可以获取源码的信息。当然 你也可以通过 dex2jar 工具将 classes.dex 文件转化为 jar 包,然后再通过 jadx 或者 jd-gui 可以查看 jar 包里面的代码。一般软件开发者会对 classes.dex 进行加固,防止别人轻易反编译
  • resources.arsc文件: 二进制资源文件,如:字符串常量就会存放在 strings.xml 中。
  • smali: smali 是将 Android 字节码用可阅读的字符串形式表现出来的一种语言,可以称之为 Android 字节码的反汇编语言。利用 apktool 或者 Android Killer,反编 classes.dex 文件,就可以得到以 smali 为后缀的文件,这些 smali 文件就是 Dalvik 的寄存器语言。
    简单的说,smali 就是 Dalvik VM 内部执行的核心代码, andorid 逆向分析的关键点。

二、下载 apktool

可在下面两种下载中选择一种方式下载:

  1. apktool github发下页面
  2. apktool 下载

(我这里使用的是 apktool_2.9.1.jar 版本)

三、使用 apktool 反编译 apk

apk 安装包和下载的 apktool 放在同一目录。

前置条件:安装 java8 环境

假如我的安装包叫 base.apk ,我想把它反编译到 test 文件夹下,反编译命令如下:

java -jar apktool_2.9.1.jar d base.apk -o test

该命令将会自动新建一个 test 文件夹, 反编译后的所有文件都将被放到里面。

说明:与 jadx 不同,apktool 反编译 apk 后,你在反编译后的 AndroidManifest.xml 里是找不到 versionCode 内部版本号 和 versionName 版本名称 的,因为 apktool 把它放到了 apktool.yml 文件里,如果你要修改 versionCodeversionName ,可以在 apktool.yml 文件里修改。

四、编译为apk

假如你修改了 test 文件夹里的代码 或者 修改了versionCode 、versionName 等其他内容,可用下面的命令将 test 文件夹编译为 apk

java -jar apktool_2.9.1.jar b test -o test.apk

该命令将 test 文件夹编译为 test.apk

到这里你已经得到了一个修改后的 apk,但是这个编译后的 apk 还无法安装到手机上,因为修改了文件,在安装时手机会对安装包里的签名进行比对签名,如果签名对不上说明apk被篡改了,就不会进行安装。

所以,如果现在要对修改后的 apk 重新进行签名,才能安装。

五、apk 签名

  • V1签名(JAR签名)基于JAR文件格式兼容性好,但安全性相对较低
  • V2签名(APK签名方案)Android 7.0 引入对整个APK进行签名,安全性更高,验证速度更快
  • V3签名(APK签名方案v3)Android 9.0 引入,支持密钥轮转,无需应用数据丢失-
  • V4签名(APK签名方案v4)Android 11 引入,基于 fs-verity ,提供更快的安装验证

1.生成密钥库

使用如下命令生成 keystore 格式的密钥库:

keytool -genkey -alias new.keystore -keyalg RSA -validity 20000 -keystore new.keystore

输入两次密钥口令,一直回车,最后输入 y

2.使用 v1 签名

使用如下命令进行签名:

jarsigner -verbose -keystore new.keystore -signedjar D:\fanbiany\sign1.apk D:\fanbiany\test.apk new.keystore

说明:该命令使用上面生成的 new.keystore 密钥库对 D:\fanbiany\test.apk 进行签名,最后生成 D:\fanbiany\sign1.apk

3.使用 v2 签名

先找到你的 apksigner.jar 所在路径,我的是在 C:\Users\kingdee\AppData\Local\Android\Sdk\build-tools\33.0.2\lib\apksigner.jar

执行如下命令进行 v2 签名:

java -jar C:\Users\kingdee\AppData\Local\Android\Sdk\build-tools\33.0.2\lib\apksigner.jar sign --ks new.keystore --out sign2.apk  sign1.apk

说明:使用 apksigner.jar 然后用 new.keystore 密钥库对 sign1.apk 进行签名,最后生成 sign2.apk

六、Dex 加解密原理

一般 apk 都会进行加固,即对 Dex 加密,Dex 就是格式的文件里是 apk 的代码,加密后反编译是看不到项目主要代码的,从而保证了 apk 的安全性。

posted @ 2025-12-25 11:15  clnchanpin  阅读(1392)  评论(0)    收藏  举报