1. 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 到四类产物的提取路径与各自的数据来源。
实操:一次完整的解包与信息提取
以下命令在 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 badging | package: name=、versionCode=、sdkVersion、targetSdkVersion | 确认包名与版本;targetSdk 过低(如 < 30)提示兼容性风险 |
aapt2 dump badging | uses-permission: 行 | 列出全部申请权限,为后续暴露面审计提供输入 |
aapt2 dump resources | type 与条目计数 | 资源条目异常少可能被裁剪或加固 |
unzip -l | classes*.dex 数量与大小 | 多 DEX 说明方法数超限;DEX 缺失说明可能被壳保护 |
keytool -printcert | SHA256: 指纹、Signature algorithm | 指纹用于比对是否为同一开发者;算法为 SHA1withRSA 提示签名较弱 |
apktool 反编译后
out_apktool/AndroidManifest.xml 是明文 XML,可直接用文本工具或脚本解析;而 aapt2 dump xmltree target.apk --file AndroidManifest.xml 可在不解包的情况下打印 AXML 树,适合流水线中快速取字段。基础信息清单(可直接填写)
把上面命令的输出整理成下面这张表,就是后续分析的工作底稿。示例值仅作格式演示,实际以目标 APK 输出为准。
| 项目 | 提取命令 | 示例值 |
|---|---|---|
| 包名 | aapt2 dump badging | com.example.app |
| versionCode / versionName | aapt2 dump badging | 102 / 1.0.2 |
| minSdk / targetSdk | aapt2 dump badging | 24 / 33 |
| 权限数量 | aapt2 dump badging | grep -c uses-permission | 12 |
| 资源条目数 | aapt2 dump resources | wc -l | 约 1800 行 |
| DEX 文件 | unzip -l | grep classes | classes.dex, classes2.dex |
| 签名方案 | apksigner verify -v | v2: true, v3: true |
| 证书 SHA-256 | keytool -printcert | AB:CD:…(40 字节十六进制) |
若
unzip -l 看不到 classes.dex,或 resources.arsc 缺失,说明 APK 可能经过加固/壳处理,此时 apktool 反编译会失败或产出空目录。遇到这种情况先记录现象,不要强行继续,后续案例会专门处理加固识别。验证解包是否成功
- 检查
out_apktool/AndroidManifest.xml是否为可读 XML(含<manifest标签),而非乱码。 - 检查
out_apktool/res/values/strings.xml是否存在且包含<string条目。 - 用
aapt2 dump badging的包名与 apktool 清单中的package=比对,两者应一致。 - 用
apksigner verify -v target.apk确认签名校验结果,记录 v1/v2/v3 各方案是否通过。
四项都通过,说明基础信息提取完整,可以进入下一阶段的组件暴露面审计。