最近做一些项目需要用到对于APK的重打包,下面来具体记录一些步骤方便日后使用
对于重打包,我们肯定需要先对APK进行解包,我这里使用的工具是apktool
。这个工具的安装十分简单,只需要使用Ubuntu自带的包管理工具即可
$ sudo apt install apktool
我们以一个APK为例子,对其进行解包
$ apktool d -f -o ./result/ ./com.gaurav.avnc_12.apk
I: Using Apktool 2.6.1 on com.gaurav.avnc_12.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /home/syc/.local/share/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
I: Copying META-INF/services directory
我们可以获得如下的目录结构
total 48
drwxr-xr-x 10 syc syc 4096 Jul 16 17:10 .
drwxr-xr-x 3 syc syc 4096 Jul 16 17:10 ..
-rw-r--r-- 1 syc syc 2728 Jul 16 17:10 AndroidManifest.xml
drwxr-xr-x 3 syc syc 4096 Jul 16 17:10 META-INF
-rw-r--r-- 1 syc syc 949 Jul 16 17:10 apktool.yml
drwxr-xr-x 3 syc syc 4096 Jul 16 17:10 assets
drwxr-xr-x 8 syc syc 4096 Jul 16 17:10 kotlin
drwxr-xr-x 6 syc syc 4096 Jul 16 17:10 lib
drwxr-xr-x 3 syc syc 4096 Jul 16 17:10 original
drwxr-xr-x 163 syc syc 4096 Jul 16 17:10 res
drwxr-xr-x 8 syc syc 4096 Jul 16 17:10 smali
drwxr-xr-x 3 syc syc 4096 Jul 16 17:10 unknown
其中,res
文件夹下存放的是反编译出来的所有资源,smali
文件夹下存放的是反编译出来的所有代码,AndroidManifest.xml
则是经过反编译还原后的manifest
文件
这里值得一提的是smali
文件夹,如果你进入到这个文件夹中你会发现它的目录结构和我们源码中src
的目录结构是几乎一样的,主要的区别就是所有的java文件都变成了smali文件。smali文件其实也是真正的源代码,只不过它的语法和java完全不同,它有点类似于汇编的语法,是Android虚拟机所使用的寄存器语言
我们现在来把反编译后的Decompile文件夹重新打包成APK吧,其实非常简单,只需要执行命令
$ apktool b ./result
I: Using Apktool 2.6.1
I: Checking whether sources has changed...
I: Checking whether resources has changed...
I: Building apk file...
I: Copying unknown files/dir...
I: Built apk...
其中b是build的意思,表示我们要将result
文件夹打包成APK文件
编译成功后,会在result
文件夹下生成两个新的文件夹,build
和dist
,其中dist
下存放的就是新生成的APK文件
total 5756
drwxr-xr-x 2 syc syc 4096 Jul 16 17:15 .
drwxr-xr-x 12 syc syc 4096 Jul 16 17:15 ..
-rw-r--r-- 1 syc syc 5882018 Jul 16 17:15 com.gaurav.avnc_12.apk
其实重打包后的APK是没有签名的,需要进行签名,签名后才能够在Android终端上进行安装
每个发布的应用都有自己的一个唯一合法的ID,这个就是应用自身的签名,签名可以保证你软件升级的一致性,使用相同签名的应用可以实现覆盖安装,而不一致的签名将无法共享使用数据,也即是无法覆盖安装,这样可以防止别人篡改,盗用开发者的应用,造成对开发者利益的损害
对于APK的签名我们需要分为两步走:
创建key,需要用到keytool工具,这个我们直接使用包管理工具安装就行。使用产生的key对apk签名用到的是jarsigner,同上安装的方法
$ sudo apt install keytool jarsigner
一个生成key的示例命令如下:
keytool -genkey -alias watson.keystore -keyalg RSA -validity 40000 -keystore watson.keystore
说明:
这里alias和keystore命名相同,其实完全可以不同的
total 5760
drwxr-xr-x 2 syc syc 4096 Jul 16 17:30 .
drwxr-xr-x 12 syc syc 4096 Jul 16 17:15 ..
-rw-r--r-- 1 syc syc 5882018 Jul 16 17:15 com.gaurav.avnc_12.apk
-rw-r--r-- 1 syc syc 2253 Jul 16 17:30 watson.keystore
签名命令格式如下
jarsigner -verbose -keystore watson.keystore -signedjar signed.apk com.gaurav.avnc_12.apk watson.keystore
说明:
verbose:输出签名的详细信息
keystore watson.keystore:使用key的绝对路径,就是在第一步中生成的key
signedjar Decompile_signed.apk Decompile.apk watson.keystore:正式签名,三个参数中依次为签名后产生的APK文件signed.apk,要签名的APK com.gaurav.avnc_12.apk和密钥库(也就是我们上面的alias)watson.keystore
...
>>> Signer
X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
[trusted certificate]
jar signed.
Warning:
The signer's certificate is self-signed.
签名之后的APK文件现在已经可以安装到手机上了,不过在此之前Android还极度建议我们对签名后的APK文件进行一次对齐操作,因为这样可以使得我们的程序在Android系统中运行得更快。对齐操作使用的是zipalign工具
我们直接使用包管理器安装即可
$ sudo apt install zipalign
命令格式如下:
zipalign -v 4 signed.apk aligned.apk
这样,zipalign能够使apk文件中未压缩的数据在4个字节边界上对齐(一般4个字节是一个性能很好的值),这样android系统就可以使用mmap()
函数读取文件,可以在读取资源上获得较高的性能
在4个字节边界上对齐的意思就是指编译器把4个字节作为一个单位来进行读取的数据资源,因此,CPU能够对变量进行较之前不对齐更高效、快速的访问
对齐的根源:android系统中的Davlik虚拟机使用自己专有的格式DEX,DEX的结构是紧凑的,为了让运行时的性能更好,可以进一步用”对齐”进一步优化,但是大小一般会有所增加
对齐操作完成,在相同目录下会生成对齐后的APK文件
total 17384
drwxr-xr-x 2 syc syc 4096 Jul 16 18:04 .
drwxr-xr-x 12 syc syc 4096 Jul 16 17:15 ..
-rw-r--r-- 1 syc syc 5950698 Jul 16 18:04 aligned.apk
-rw-r--r-- 1 syc syc 5882018 Jul 16 17:15 com.gaurav.avnc_12.apk
-rw-r--r-- 1 syc syc 5950401 Jul 16 18:01 signed.apk
-rw-r--r-- 1 syc syc 2253 Jul 16 17:30 watson.keystore