首页 技术杂谈 正文
  • 本文约2412字,阅读需12分钟
  • 94
  • 0

常见的Android文件格式 - APK

摘要

APK的生成流程 APK 的生成是 代码编译、资源处理、打包签名 的流水线式过程 Java/Kotlin 代码 资源文件 ↓ ↓ 编译为字节码 资源编译(AAPT2) ↓ ↓ .class → DEX 生成 resources.arsc ↘ ↓ ...

APK的生成流程

APK 的生成是 代码编译、资源处理、打包签名 的流水线式过程

Java/Kotlin 代码      资源文件
      ↓                 ↓
  编译为字节码      资源编译(AAPT2)
      ↓                 ↓
  .class → DEX      生成 resources.arsc
          ↘          ↓         ↙
            APK 打包(zip 格式)
                 ↓
             签名(Jarsigner/APK Signer)
                 ↓
             最终 APK/ZIP 对齐优化(zipalign)

Java/Kotlin代码编译

  • 输入:.java/.kt文件、依赖库(AAR/JAR)
  • 工具:javac(Java)、kotlinc(Kotlin)
  • 输出: .class字节码文件
  • 关键过程:
    • Java -> .class(JVM字节码)
    • Kotlin -> .class(通过Kotlin编译器)

DEX转换

  • 工具:D8或R8(取代旧版DX)
  • 输入: 所有.class文件
  • 输出: 单个/多个class.dex文件
  • 作用: 将JVM字节码转为Android设备可执行的DEX格式
    d8 --output ./out/ app.jar library.jar

资源处理阶段

资源编译与打包

  • 工具:AAPT2

  • 输入: /res/*(图片、XML布局) , AndroidManifest.xml.

  • 输出:

    • resources.arsc(二进制资源索引表),res/转换为二进制格式(如 layout.xml -> layout.bin)
  • 作用:

    • 资源ID分配
    • 优化资源加载速度
# 示例:AAPT2 编译资源
aapt2 compile -o out/ res/layout/activity_main.xml
aapt2 link -o base.apk --manifest AndroidManifest.xml -I android.jar

APK打包阶段

  • 工具:zip格式打包(通过Gradle或apkbuilder)
  • 输入: DEX、资源文件、原生库(.so)、AndroidManifest.xml
  • 输出: 未签名的APK(包含所有组件)
  • 文件结构
    APK
    ├── AndroidManifest.xml  # 二进制格式
    ├── classes.dex          # 可执行代码
    ├── res/                 # 二进制资源
    ├── resources.arsc       # 资源索引
    └── lib/                 # .so 原生库(可选)

APK签名阶段

  • 目的:确保APK的完整性和开发者身份认证
  • 工具:
    • jarsigner(传统工具)
    • apksigner(官方推荐,支持v2/v3签名方案)
  • 流程:
    1. 生成Keystore(密钥库)
      keytool -genkey -v -keystore my.keystore -alias mykey -keyalg RSA -validity 1000
    2. 对APK签名
      apksigner sign --ks my.keystore --ks-key-alias mykey app-unsigned.apk

ZIP对齐优化

  • 工具:zipalign
  • 作用:调整APK中文件的对齐方式,以优化内存访问效率
  • 命令:
    zipalign -v 4 input.apk output-aligned.apk

APK安装流程

  • 用户触发安装APK->系统启动PackageInstaller界面。
  • 复制APK到临时目录(如/data/app/vmdlxxx.tmp)。
  • 解析APK信息(包名、权限等)-> 验证签名和兼容性。
  • 分配应用专属目录(如/data/app/<包名>-XXXX/) -> 复制APK到该目录。
  • DEX优化(由dexopt转换为OAT文件)。
  • 更新系统数据库(packages.xml) -> 注册应用信息。
  • 广播通知安装完成->应用状态生效。

详解内部运作机制

触发安装:前端交互

  • 用户场景:用户打开APK文件,系统调用PackageInstaller应用。

    • PackageManagerService(PMS)
      • 功能:管理应用安装、卸载、权限授予。
      • 启动时机:系统启动时由 SystemServer 初始化。
    • 核心方法
      public void installPackageAsUser(String apkPath, int flags, int userId);
  • 系统行文:

    • Intent.ACTION_VIEW → 交由 PackageInstallerActivity 处理。
    • 权限检查:校验安装来源(如 Settings.Secure.INSTALL_NON_MARKET_APPS)

复制到临时目录

  • 临时存储路径:/data/app/vmdlXXXXXX.tmp(由系统生成唯一文件名)
  • 关键服务:PackageManagerService(PMS)的 installPackageAsUser 方法

APK解析与验证

  • 解析内容:
    • 提取 AndroidManifest.xml(转为二进制后解析)
    • 读取包名、版本号、权限列表(uses-permission)、SDK 要求等
  • 签名验证:
    • 检查签名证书的合法性(防止篡改)
    • 对比现有签名(更新应用时需一致)

应用目录分配

  • 目标路径:/data/app/<包名>-XXXX/(存储 APK 和私有数据)。
    • 示例:/data/app/com.example.app-1a2b3c/
  • lib 目录:.so 文件解压到子目录 /lib/abi/(如 armeabi-v7a)
  • 文件权限:设置 -rw-r--r--(用户私有,其他应用不可读)

DEX 优化(关键步骤)

  • 流程:
    • 原始 DEX 转换为 OAT 格式(ART 虚拟机优化)
    • 输出至 /data/dalvik-cache/arm64/
  • 工具链:
    • dex2oat(编译器,将 DEX 转为机器码)
    • 优化级别:speed(完全编译)或 quicken(快速优化)

数据库更新

  • 关键文件:
    • /data/system/packages.xml:存储包名、UID、权限、签名等信息。
    • /data/system/packages.list:记录包名与数据目录的映射。
  • 权限授权:将 uses-permission 声明的权限写入 PMS 内存映射。

广播通知安装结果

  • 发送广播:Intent.ACTION_PACKAGE_ADDED → 通知系统和其他应用。
  • 回调处理:系统服务更新状态(如 Launcher 刷新应用列表)
标签:Android逆向
评论