一、APK 结构
Android 应用的 APK(Android Package)安装文件是一个包含所有代码和资源文件的压缩包
AndroidManifest.xml
是Android应用程序的配置文件,是一个用来描述Android应用“整体资讯”的设定文件,简单来说,相当于Android应用向Android系统“自我介绍”的配置文件,Android系统可以根据这个“自我介绍”完整地了解APK应用程序的资讯,每个Android应用程序都必须包含一个AndroidManifest.xml文件,且它的名字是固定的,不能修改。程序打包时,会把AndroidManifest.xml进行简单的编译,便于Android系统识别,编译之后的格式是AXML格式
Assets
用来存放需要打包到 Android 应用程序的静态资源文件,例如图片资源文件、JSON 配置文件、渠道配置文件、二进制数据文件、HTML5离线资源文件等。与res/raw 目录不同的是,assets 目录支持任意深度的子目录,同时该目录下面的文件不会生成资源ID。
lib
这里存放应用程序依赖的native库文件,一般是用C/C++编写,这里的lib库可能包含4中不同类型,根据CPU型号的不同,大体可以分为ARM,ARM-v7a,MIPS,X86,分别对应着ARM架构,ARM-V7架构,MIPS架构和X86架构,不同的CPU架构对应着不同的目录,每个目录中可以放很多对应版本的so库,且这个目录的结构固定,用户只能按照这个目录存放自己的so库。目前市场上使用的移动终端大多是基于ARM或者ARM-V7a架构的,X86和MIPS架构的移动智能终端比较少,所以有些应用程序lib目录下只包含armeabi目录或者armeabi-v7a目录,也就是说,这四个目录要根据CPU的架构来选,而市面上ARM架构的手机占大多数,所以一般的APK只包含ARM和ARM-V7a的so。
res
res是resource的缩写,这个目录存放资源文件,存在这个文件夹下的所有文件都会映射到Android工程的.R文件中,生成对应的ID,访问的时候直接使用资源ID即R.id.filename,res文件夹下可以包含多个文件夹,其中anim存放动画文件;drawable目录存放图像资源;layout目录存放布局文件;values目录存放一些特征值,colors.xml存放color颜色值,dimens.xml定义尺寸值,string.xml定义字符串的值,styles.xml定义样式对象;xml文件夹存放任意xml文件,在运行时可以通过Resources.getXML()读取;raw是可以直接复制到设备中的任意文件,他们无需编译
classes.dex
传统的Java程序,首先先把Java文件编译成class文件,字节码都保存在了class文件中,Java虚拟机可以通过解释执行这些class文件。而Dalvik虚拟机是在Java虚拟机进行了优化,执行的是Dalvik字节码,而这些Dalvik字节码是由Java字节码转换而来,一般情况下,Android应用在打包时通过AndroidSDK中的dx工具将Java字节码转换为Dalvik字节码。dx工具可以对多个class文件进行合并,重组,优化,可以达到减小体积,缩短运行时间的目的
resources.arsc
用来记录资源文件和资源ID之间的映射关系,用来根据资源ID寻找资源。Android的开发是分模块的,res目录专门用来存放资源文件,当在代码中需要调用资源文件时,只需要调用findviewbyId()就可以得到资源文件,每当在res文件夹下放一个文件,aapt就会自动生成对应的ID保存在.R文件,我们调用这个ID就可以,但是只有这个ID还不够,.R文件只是保证编译程序不报错,实际上在程序运行时,系统要根据ID去寻找对应的资源路径,而resources.arsc文件就是用来记录这些ID和资源文件位置对应关系的文件。
备注:
1.两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。
*res/raw和assets的不同点:
1.res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。
2.res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹
META-INF
该目录存放的是签名相关的信息,用于验证 APK 包的完整性以及保证系统的安全。主要包含三个文件:
① MANIFEST.MF:主要存放 APK 包中每个文件的名字及每个文件的 SHA1 哈希值。
② CERT.SF:通常每个 APP 会有一个特定的名字,例如 BDMOBILE.SF、NETDISK_.SF等, 它保存的是 MANIFEST.MF 的哈希值以及 MANIFEST.MF 文件中每一个哈希项的哈希值。
③ CERT.RSA:这个文件保存了 APK 包的签名和证书的公钥信息
二、APK生成过程
AAPT
一句话解释:Android Asset Packaging Tool,即Android资源打包工具
常见API:
Method:压缩方法,Deflate及Stored两种,即该Zip目录采用的算法是压缩模式还是存储模式;
可以看出resources.arsc、*.png采用压缩模式,而其它采用压缩模式。
Ratio:压缩率
设置debbug
//www.greatytc.com/p/8d691b6bf8b4
三、反编译:
3.1、java、class、dex、smali之间的转化
工具 | 作用 | 资源 |
---|---|---|
javac | java------>class | |
dx | class------>dex | |
baksmali | dex------>smali | https://bitbucket.org/JesusFreke/smali/downloads/ |
smali | smali------>dex | https://bitbucket.org/JesusFreke/smali/downloads/ |
dex2jar | dex------>jar(class的压缩包) | https://sourceforge.net/projects/dex2jar/files/ |
apktool | apk------>smali | https://ibotpeaches.github.io/Apktool/install/ |
3.1.1、定义
java
文件即普通文本文件
class
class文件是一种能够被JVM识别,加载并且执行的文件格式,
记录一个类文件的所有信息.
//生成class
javac -target 1.6 -source 1.6 hello.java
//执行class
java **
dex
dex文件的作用是记录整个工程(通常是一个Android工程)的所有类文件的信息
java -jar dx.jar --dex --output Hello.dex Hello.class
class文件与dex文件的比较
本质上都是一样的,都是二进制流文件格式,dex文件是从class文件演变而来的,class文件存在冗余信息,dex文件则去掉了冗余,并且整合了整个工程的类信息。
3.2、dex 的使用
dex -> jar
3.3、Jar的使用
生成Jar
jar cvfm name.jar 清单文件 class名|文件夹
jar命令生成的压缩文件会包含它后边出的目录。我们应该进入到指定目录再执行jar命令
清单文件
Manifest-Version: 1.0
Created-By: 1.8.0_131 (Oracle Corporation)
Class-Path: . //主类路径、可以写当前Jar包名 或者 .
Main-Class: Hello //注明名称
查看jar
java tvf **.jar
jar命令格式:jar {c t x u f }[ v m e 0 M i ][-C 目录]文件名...
-c 创建一个jar包
-t 显示jar中的内容列表
-x 解压jar包
-u 添加文件到jar包中
-f 指定jar包的文件名
-v 生成详细的报造,并输出至标准设备
-m 指定manifest.mf文件.(manifest.mf文件中可以对jar包及其中的内容作一些一设置)
-0 产生jar包时不对其中的内容进行压缩处理
-M 不产生所有文件的清单文件(Manifest.mf)。这个参数与忽略掉-m参数的设置
-i 为指定的jar文件创建索引文件 jar i hello.jar
-C 表示转到相应的目录下执行jar命令,相当于cd到那个目录,然后不带-C执行jar命令
3.3、APKTool
可以查看APK 的原始 资源文件,同时将dex 转化为smali 文件。
3.3.1、decode
apktool d -o dir demo.apk
3.3.2、build
apktool b -o new.pak dir
3.3.3、jarsinger
jarsigner -verbose -digestalg SHA1 -sigalg SHA1withRSA -keystore key文件路径 -storepass password -keypass aliasPassWord pkg alias
四、APK修改
Java2Smali插件:https://github.com/ollide/intellij-java2smali
4.1、smali
smali是将Android字节码用可阅读的字符串形式表现出来的一种语言,可以称之为Android字节码的反汇编语言。使用baksmali或apktool可以将Android应用程序包(apk或jar)反编译为smali代码
4.1.1、smali基础语法
1、基本数据类型
//www.greatytc.com/p/04c3c8566ee1
4.1.2、smali文件修改
1、找到对应文件位置
2、根据带修改位置的方法参数,编写Java 文件
3、生成smali 文件
4、替换相关方法
5、apktool重新打包
6、签名生成新包
五、APK签名
5.1、签名文件的生成
1、MANIFEST.MF
打开待签名的apk文件(由于apk其实是一个用zip压缩的文件,其实就是用zip解压整个apk文件),逐一遍历里面的所有条目,如果是目录就跳过,如果是一个文件,就用SHA1(或者SHA256)消息摘要算法提取出该文件的摘要然后进行BASE64编码后,作为“SHA1-Digest”属性的值写入到MANIFEST.MF文件中的一个块中。该块有一个“Name”属性,其值就是该文件在apk包中的路径。
2、CERT.SF
计算这个MANIFEST.MF文件的整体SHA1值,再经过BASE64编码后,记录在CERT.SF主属性块(在文件头上)的“SHA1-Digest-Manifest”属性值值下;然后,再逐条计算MANIFEST.MF文件中每一个块的SHA1,并经过BASE64编码后,记录在CERT.SF中的同名块中,属性的名字是“SHA1-Digest”。
3、CERT.RSA
把之前生成的 CERT.SF文件, 用私钥计算出签名, 然后将签名以及包含公钥信息的数字证书一同写入 CERT.RSA 中保存。CERT.RSA是一个满足PKCS7格式的文件,可以通过openssl工具来查看签名证书的信息。
//查看签名证书信息
openssl pkcs7 -inform DER -in CERT.RSA -text -print_certs
相关链接://www.greatytc.com/p/a27783a713f2
5.2、签名的校验
https://blog.csdn.net/qq_27419187/article/details/76339326
六、界面化
jadx:https://github.com/skylot/jadx