1. APK 文件结构与静态信息提取

APK 文件结构与静态信息提取 学习卡片

APK 的本质:一个带约定的 ZIP 容器

APK 不是黑盒,它就是一个 ZIP 归档,只是内部文件名和目录布局被 Android 构建工具链固定下来。用 unzip -l 就能先看到骨架,再决定用 apktool 还是 aapt2 深入。一个典型 APK 的关键成员如下:

  • AndroidManifest.xml:二进制 XML(AXML),声明组件、权限、SDK 版本。
  • classes.dex(可能多个 classes2.dex…):Dalvik 字节码,方法数超 65536 时拆分为多 DEX。
  • resources.arsc:编译后的资源表,字符串池 + 资源 ID 映射。
  • res/:编译后的资源文件(图片、布局等)。
  • META-INF/:签名文件(MANIFEST.MF、CERT.SF、CERT.RSA)。
  • assets/:原样打包的资产,不参与资源 ID 分配。

两条解包路线的分工

apktool 和 aapt2 不是替代关系,而是互补:

  • apktool d:把 AXML 反编译成可读的明文 AndroidManifest.xml,把 resources.arsc 解码成 res/values/strings.xml 等,同时保留 smali 反汇编目录。适合需要“读内容、改内容、再回编”的场景。
  • aapt2 dump:不落地文件,直接把资源表、清单、权限、配置以文本形式打印到终端。适合快速提取元数据、做脚本化流水线。

本例的产出是一份基础信息清单:清单摘要、资源表统计、签名信息、DEX 列表。下面这张图给出从 APK 到四类产物的提取路径与各自的数据来源。

target.apk ZIP 容器 AndroidManifest.xml classes.dex / classes2.dex resources.arsc META-INF/ (签名) res/ · assets/ apktool d 反编译 / 可回编 aapt2 dump 只读 / 脚本友好 ① AndroidManifest.xml(明文) package · versionCode · minSdk/targetSdk · 组件 ② 资源表 resources.arsc 资源条目数 · 字符串池 · 配置维度 ③ 签名信息 META-INF/ v1/v2/v3 方案 · 证书指纹 · 签名算法 ④ DEX 文件列表 classes*.dex 数量 · 各文件大小 · 方法数线索 META-INF/ 直接读取(keytool / apksigner) 实线:工具提取路径 虚线:签名信息独立读取路径

实操:一次完整的解包与信息提取

以下命令在 Linux/macOS 终端执行,Windows 下把路径分隔符换成反斜杠即可。假设待分析文件为 target.apk。

# 0. 先看 ZIP 骨架,确认关键成员是否存在
unzip -l target.apk | grep -E "AndroidManifest|classes.*dex|resources.arsc|META-INF"

# 1. apktool 反编译,输出到 out_apktool/
apktool d -f -o out_apktool target.apk

# 2. 查看反编译后的明文清单
head -40 out_apktool/AndroidManifest.xml

# 3. aapt2 直接 dump 清单元数据(不落地文件)
aapt2 dump badging target.apk

# 4. aapt2 dump 资源表统计
aapt2 dump resources target.apk | head -30

# 5. 列出 DEX 文件及大小
unzip -l target.apk | grep -E "classes[0-9]*\.dex"

# 6. 提取签名证书指纹
unzip -o target.apk "META-INF/*" -d sig_tmp
keytool -printcert -file sig_tmp/META-INF/CERT.RSA

关键输出怎么读

命令关注字段判断依据
aapt2 dump badgingpackage: name=、versionCode=、sdkVersion、targetSdkVersion确认包名与版本;targetSdk 过低(如 < 30)提示兼容性风险
aapt2 dump badginguses-permission: 行列出全部申请权限,为后续暴露面审计提供输入
aapt2 dump resourcestype 与条目计数资源条目异常少可能被裁剪或加固
unzip -lclasses*.dex 数量与大小多 DEX 说明方法数超限;DEX 缺失说明可能被壳保护
keytool -printcertSHA256: 指纹、Signature algorithm指纹用于比对是否为同一开发者;算法为 SHA1withRSA 提示签名较弱
apktool 反编译后 out_apktool/AndroidManifest.xml 是明文 XML,可直接用文本工具或脚本解析;而 aapt2 dump xmltree target.apk --file AndroidManifest.xml 可在不解包的情况下打印 AXML 树,适合流水线中快速取字段。

基础信息清单(可直接填写)

把上面命令的输出整理成下面这张表,就是后续分析的工作底稿。示例值仅作格式演示,实际以目标 APK 输出为准。

项目提取命令示例值
包名aapt2 dump badgingcom.example.app
versionCode / versionNameaapt2 dump badging102 / 1.0.2
minSdk / targetSdkaapt2 dump badging24 / 33
权限数量aapt2 dump badging | grep -c uses-permission12
资源条目数aapt2 dump resources | wc -l约 1800 行
DEX 文件unzip -l | grep classesclasses.dex, classes2.dex
签名方案apksigner verify -vv2: true, v3: true
证书 SHA-256keytool -printcertAB:CD:…(40 字节十六进制)
若 unzip -l 看不到 classes.dex,或 resources.arsc 缺失,说明 APK 可能经过加固/壳处理,此时 apktool 反编译会失败或产出空目录。遇到这种情况先记录现象,不要强行继续,后续案例会专门处理加固识别。

验证解包是否成功

  1. 检查 out_apktool/AndroidManifest.xml 是否为可读 XML(含 <manifest 标签),而非乱码。
  2. 检查 out_apktool/res/values/strings.xml 是否存在且包含 <string 条目。
  3. 用 aapt2 dump badging 的包名与 apktool 清单中的 package= 比对,两者应一致。
  4. 用 apksigner verify -v target.apk 确认签名校验结果,记录 v1/v2/v3 各方案是否通过。

四项都通过,说明基础信息提取完整,可以进入下一阶段的组件暴露面审计。