常见Android文件格式

1 背景

重新开始学习Android真是有点难,之前好多知识都给忘了,通过翻阅相关资料并回顾自己的博客也拾起来不少东西。

接下来,就开始常见Android文件格式的历程吧🤭🤭🤭

Android系统中最常见的文件应属APK安装包。在开发与逆向分析APK程序时,会涉及APK安装包内部其他文件的结构。对开发人员而言,了解Android系统中与APK相关的文件格式,以及它们在系统中加载处理方面的细节,将有助于找到反调试和对抗逆向分析的保护方案;对安全研究人员而言,洞察文件格式的内幕,将有助于挖掘与文件格式相关的漏洞,分析恶意软件的运作原理及行为,找到软件应用逻辑中的潜在风险,为Android平台的软件安全保驾护航。

2 APK文件

APK(Android Package)是指Android系统的软件安装包文件,APK是Android软件的核心和Android软件开发的结果,需要重点关注。

2.1 APK文件结构

APK文件与其他系统中的软件包一样,都有自己的格式与组织结构。从Android诞生那天起,APK文件的格式和就没有发生过变化,始终使用zip作为其格式。在目录结构上,APK文件也没有发生过变化。

图1 APK文件结构

一个完整的APK文件包含如下内容:

  • AndroidManifest.xml:编译好的AXML二进制格式的文件。Android项目的系统清单文件夹,Android的四大组件(Activity、Service、BroadcastReceiver、ContentProvider)均在此文件中配置。
  • META-INF目录:用于保存APK的签名信息,以便于用来确保APK文件不会被人随意修改。
  • classes.dex:程序的可执行代码。如果当前方法数超过65535,进行了分包处理,就会开启MutliDex,会有多个DEX文件。
  • res目录:程序中使用的资源信息,包括图片资源、字符串资源、颜色资源、尺寸资源等,此目录下面的资源都会出现在资源清单文件R.java的索引中。针对不同分辨率的设备,可以使用不同的资源文件。
  • resources.arsc:编译好的二进制格式的资源信息。资源索引表,用来描述具有ID值的资源的配置信息。
  • lib目录:当前APP所需要的so文件,so文件就是利用底层的C、C++代码实现的。
  • assets目录:存放需要打包到Android应用程序的静态资源文件,例如图片资源文件、JSON配置文件、渠道配置文件、二进制数据文件、HTML 5离线资源文件等。与res/raw目录不同的是,assets目录支持任意深度的子目录,同时该目录下面的文件不会生成资源ID。

2.2 APK文件的生成流程

在ADT时代,Android官方发布了一幅完整的APK编译流程图,如图2所示。

图2 ADT时代的APK编译流程图

具体的编译流程如下所示:

  1. 使用aapt(Android Asset Packaging Tool)打包程序资源文件,处理项目中的AndroidManifest.xml文件和XML布局文件,并生成R.java文件resources.arsc文件
  2. 使用aidl工具将所有的aidl接口转化为对应的Java接口
    • 没使用aidl的工程可以跳过,工具aidl跟aapt在同一目录。
    • aidl是Android内部进程通信接口的描述语言,我们可以通过它定义进程间的通信接口。
  3. 所有的Java代码,包括R.java和Java接口都会被Java编译器javac编译成class文件
  4. 使用dx将所有的class文件与第三方library打包生成DEX文件
  5. 调用apkbuilder将第一步编译后的资源、第四步生成的.dex文件,以及一些其它资源打包到APK文件中;
  6. 对APK文件进行签名
  7. 使用zipalign工具对APK进行对齐操作,将APK包中资源文件距离文件的起始偏移修改为4字节的整数倍数,这样,在之后运行APP的时候,速度会比较快。

打包生成APK的整个过程都是基于ADT时代的编译工具集实现的。而到了Android Studio时代,编译流程的细节发生了一些变化,Android官方使用gradle作为APK的构建工具,但没有给出详细的新版APK打包流程,如图3所示。

图3 Android Studio时代的APK打包流程图

2.3 APK安装流程及路径

2.3.1 APK安装的路径

APK文件安装涉及到如下几个目录:

  • system/app:系统自带的应用程序,获得adb root权限才能删除。
  • data/app:用户程序安装的目录,安装时把APK文件复制到此目录。
  • data/data:存放应用程序的数据。
  • data/dalvik-cache:将APK中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始APK文件大小的四分之一)

2.3.2 APK安装的流程

  • 点击APK安装,会启动PackageInstallerActivity,再进入InstallInstalling这两个Activity显示应用信息
  • 点击页面上的安装,将APK信息存入PackageInstaller.Session传到PMS
  • PMS会做两件事,拷贝安装包装载代码
  • 在拷贝安装包过程中会开启Service来copyAPK、检查APK安装路径,包的状态
  • 拷贝完成以base.apk形式存在/data/app/包名
  • 装载代码过程中,会继续解析APK,把清单文件内容存放于PMS
  • 对APK进行签名校验
  • 安装成功后,更新应用设置权限,发送广播通知桌面显示APP图标,安装失败则删除安装包和各种缓存文件
  • 执行/system/bin/dex2oat优化

卸载过程是删除安装过程中在上述三个目录下创建的文件及目录。

3 META-INF目录

APK包中有一个名为META-INF的目录,存储了一些与APK签名有关的信息,如图4所示。

图4 APK签名相关文件

3.1 MANIFEST.MF

MANIFEST.MF是签名的清单文件,它是一个文本文件,计算APK内各文件的摘要,经过BASE64编码后记录,内容如图5所示。

图5 MANIFEST.MF文件信息

可以看出,打包该文件的工具是Android Gradle 7.1.3,下面的每一组信息都包括Name与SHA-256-Digest,表示APK文件中每个文件的路径与它的SHA-256散列值的Base64值

3.2 CERT.SF

CERT.SF是签名信息文件,也是一个文本文件,内容如图6所示。

图6 CERT.SF文件信息

乍看上去,记录的每一组信息也包括Name与SHA-256-Digest。但是,记录MANIFEST.MF的摘要的BASE64编码,并再次计算MANIFEST.MF内每个条目的摘要,经过BASE64编码后记录。

3.3 CERT.RSA

CERT.RSA文件中存放了APK的开发者证书签名信息签名算法。通过该文件可以识别开发者的身份,以及判断APK是否被篡改,执行图7中的命令可以查看CERT.RSA中开发者证书的内容。

图7 CERT.RSA文件信息

3.4 Android支持的签名方案

为了APP在不同Android版本上的兼容性,应按照v1v2v3的顺序依次对应用进行签名,验证的时候顺序相反,如图8所示。

图8 Android支持的签名方案

关于v1,v2,v3签名的简介如下所示:

  • v1:基于JAR签名
  • v2:Android 7.0中引入
  • v3:Android 9中引入

4 DEX文件

classes.dex文件中包含APK的可执行代码,是分析Android软件时最常见的目标,DEX文件的数据结构及说明如图9所示。

图9 DEX文件数据结构

在Android 5.0之前,主要使用的虚拟机是Dalvik。当APK首次安装,或者系统升级、重新启动时,为了提高DEX文件的执行效率,Dalvik会对APK中的DEX文件进行一定程度的优化。具体的做法是:/system/bin/dexopt解析DEX文件后会生成一个ODEX文件,将其存放在Android设备的/data/dalvik-cache目录下。以后再运行这个程序时,就不会读取APK中的DEX文件,而会直接加载这个优化过的ODEX文件,从而大大节省每次运行程序时在优化上耗费的时间

5 OAT文件

OAT文件是在Android 4.4中引入的。OAT是优化过的、用于ART虚拟机执行的DEX文件,类似于Dalvik的ODEX文件。系统在安装APK时,会调用/system/bin/dex2oat自动生成OAT文件。

OAT文件格式在设计之初就考虑到最终执行的程序是ELF格式的这一事实,为避免过多的文件格式设计所带来的麻烦,最终将OAT文件格式完全融入Android所特有的ELF格式。OAT文件格式图如图10所示,

图10 OAT文件格式图

一个OAT文件必须包含oatdataoatexecoatlastword三个符号。

  • oatdata符号指向的地址是OAT所在的.rodata字段,这里存放的是OAT文件头OATHeaderOAT的DEX文件头OATDexFile原始的DEX文件DexFileOAT的DEX类OatClass等信息。
  • oatexec符号指向的地址是OAT所在ELF的.text字段,这里存放的是编译生成的Native指令代码
  • oatlastword符号指向的地址是OAT文件结束处在ELF中的文件偏移,通过它可以确定OAT文件的内容在哪里结束。

6 ODEX和OAT文件的生成过程

图11 ODEX和OAT文件的生成过程

【注意】

  • 在Android 5.0之前,DEX文件是由/system/bin/dexopt优化后生成ODEX文件,Dalvik虚拟机直接加载ODEX文件来运行程序;
  • 在Android 5.0之后,DEX文件是由/system/bin/dex2oat优化后生成OAT文件,Dalvik虚拟机直接加载OAT文件来运行程序。

7 总结

在研究一个系统平台的软件安全机制时,首要工作通常是了解这个平台上的常见Android文件格式二进制程序的格式,分析其与其他平台上文件格式的异同,思考修改这些文件及加强对这些文件的保护方法。

8 参考文献

[1]丰生强. Android软件安全权威指南[M]. 电子工业出版社, 2019.


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。

×

喜欢就点赞,疼爱就打赏