简介:本资源是一套面向Android逆向分析初学者与开发者的APK资源提取工具包,专为macOS平台设计,解决开发者在无源码情况下快速反编译、查看及修改APK资源(如布局、字符串、图片等)的核心需求。压缩包共3个文件,包含核心可执行jar包(apktool.jar)、macOS适配的启动脚本(apktool.sh)以及详尽的中文使用说明文档(MD格式),覆盖环境配置、基础命令、常见问题排错等实操要点,开箱即用。资源包大小为10.25MB,轻量易下载,结构精炼无冗余。目前已有2829人学习下载,适合刚接触APK逆向、需快速上手资源解析的移动端安全入门者或安卓开发调试人员。
1. Apktool 不是万能钥匙,但没它你连 APK 的门都推不开
某开发者在做安卓应用资源复用时,直接把一个 .apk 文件后缀改成 .zip 解压——结果发现 res/ 目录里全是乱码文件名,AndroidManifest.xml 打开是二进制垃圾,strings.xml 里的中文全变成 \uXXXX。他以为是编码问题,折腾了三天改 iconv、换 JDK 版本、重装 Android SDK,最后才意识到:APK 不是普通压缩包,它的资源表、XML、签名结构全被 AOSP 自研的 aapt2 编译器深度打包和二进制化了。Apktool 就是专治这种“看似能解压、实则打不开”的黑匣子工具。它不破解签名,不绕过加固,但能把绝大多数未加固 APK 反编译成可读的 smali 汇编 + 可编辑的 XML + 原始资源目录,再重新打包回能安装的 APK(需重签)。适合安卓逆向初学者、UI 资源提取、汉化补丁制作、旧版 App 功能复用等真实场景。注意:它对 V2/V3 签名、多 dex、字符串加密、so 层加固类 APK 支持有限,别指望它一键搞定某金融类 App——那是另一套工程。
2. 下载与环境准备:Java 版本比你想象中更关键
Apktool 是 Java 写的命令行工具,但它不是“装个 JDK 就能跑”。它的行为高度依赖 Java 运行时版本,尤其在处理 Android 12+(API 31)及以上编译的 APK 时,JDK 8 会直接报Unsupported class file major version;而 JDK 17 又可能因字节码校验变严,导致某些老版本 Apktool 解包失败。这不是玄学,是 aapt2 生成的 resources.arsc 和 AndroidManifest.xml 的二进制格式随 Android SDK 迭代持续演进,Apktool 必须用匹配的 Java 版本加载对应解析逻辑。
2.1 确认并安装兼容的 JDK
官方文档明确要求:Apktool 2.9.0+ 推荐 JDK 11 或 JDK 17;2.8.x 及更早版本建议用 JDK 8 或 JDK 11。我们以当前最新稳定版Apktool 2.9.3(2024 年 6 月发布)为准,统一使用JDK 17——它能覆盖从 Android 4.1(API 16)到 Android 14(API 34)的绝大多数 APK,且避免 JDK 8 的 TLS 1.3 兼容性问题。
验证 Java 版本:
java -version输出应类似:
openjdk version "17.0.8" 2023-07-18 OpenJDK Runtime Environment (build 17.0.8+7-Ubuntu-122.04) OpenJDK 64-Bit Server VM (build 17.0.8+7-Ubuntu-122.04, mixed mode, sharing)提示:Ubuntu/Debian 用户推荐用
apt install openjdk-17-jdk;macOS 用户用brew install openjdk@17;Windows 用户请从 Adoptium 下载 Temurin 17 LTS 版本,务必选 x64 架构(ARM64 如 M1/M2 Mac 需单独确认 Apktool 是否已适配,目前 2.9.3 官方未提供原生 aarch64 jar,仍建议 Rosetta 运行 x64 版本)。
2.2 下载 Apktool 本体:只认官方 jar,拒绝第三方打包版
Apktool 没有安装程序,只有一个可执行 jar 包(apktool.jar),外加一个 shell/bat 封装脚本(用于自动调用 java 命令)。必须从官方 GitHub Release 页面下载,不要用 pip、brew cask 或国内镜像站打包的“集成版”——那些常混入旧版 aapt、错误签名密钥或删减了 framework-res.apk 依赖,导致brut.androlib.AndrolibException: Could not load resources.arsc类错误频发。
正确下载方式(Linux/macOS):
# 创建工具目录 mkdir -p ~/bin/apktool cd ~/bin/apktool # 下载最新 apktool.jar(以 2.9.3 为例) curl -O https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool curl -O https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar # 重命名 jar 文件为标准名 mv apktool_2.9.3.jar apktool.jar # 赋予脚本执行权限 chmod +x apktoolWindows 用户请手动访问:
👉 https://github.com/iBotPeaches/Apktool/releases/tag/v2.9.3
下载apktool_2.9.3.jar和apktool.bat两个文件,放入同一目录(如C:\tools\apktool\),不要双击运行 bat 文件——它只是启动脚本,真正干活的是 jar。
2.3 初始化 framework:没有 framework-res.apk,你就只能解包,不能回编译
Apktool 解包时能直接读取 APK 内部资源,但重新打包(apktool b)时必须知道系统框架资源定义,否则会报错:
brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [/tmp/aapt, p, -F, /tmp/resources.ap_, -I, /home/user/.local/share/apktool/framework/1.apk, ...]这个/home/user/.local/share/apktool/framework/1.apk就是 framework-res.apk,它来自你本地 Android 系统镜像或 SDK 中的platforms/android-XX/data/res/。Apktool 默认不会自带,需要你主动下载并注册。
执行一次空命令触发自动下载(推荐):
# 此命令会自动下载 framework-res.apk 到 ~/.local/share/apktool/framework/ apktool --version若失败(如网络超时),手动下载:
# 下载对应 Android 版本的 framework(以 Android 13 为例) curl -O https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/framework/android-33.zip unzip android-33.zip -d ~/.local/share/apktool/framework/注意:
1.apk是默认 framework ID,如果你反编译的是 Android 14 设备上的 APK,建议显式指定 framework:apktool if framework-res-android-34.apk -t 34
-t 34表示注册为 ID 34 的 framework,后续解包时用-t 34指定。
3. 基础使用三步走:解包 → 修改 → 回编译
Apktool 的核心价值不在“能看”,而在“能改能回”。很多教程只教d(decode)就结束,但真正落地要闭环:改完 XML、替换图片、增删权限,最终打出一个能安装的 APK。这三步每一步都有参数陷阱。
3.1 解包(decode):别跳过-r和-s,它们决定你能改什么
命令模板:
apktool d app-release.apk -o app-src -r -sapp-release.apk:待处理的原始 APK 文件路径-o app-src:输出目录,建议用-src后缀区分源码目录-r:skip decompiling resources(跳过资源反编译)-s:skip decompiling sources(跳过 smali 反编译)
为什么常用
-r -s?因为多数人只需要提取资源(图标、布局、字符串),不需要碰 Java 逻辑。加上这两个参数后:
res/目录下是原始resources.arsc(二进制)、AndroidManifest.xml(已还原为明文 XML)、res/values/strings.xml(中文可读);- 不生成
smali/目录,省下 80% 时间和磁盘空间;- 避免因 smali 语法升级(如 2.9.0 后默认用
invoke-static/range替代invoke-static)导致的 recompile 失败。
若你确实要分析逻辑,去掉-s即可,但务必确认 Apktool 版本与目标 APK 的 dex 格式兼容(Android 13+ 默认用compact-dex,Apktool 2.9.3 已支持,2.8.x 会失败)。
3.2 修改资源:XML 和 res/ 是安全区,AndroidManifest.xml 是高频修改点
解包后进入app-src/目录,你会看到:
app-src/ ├── AndroidManifest.xml ← 明文,可直接改 <application android:debuggable="true"> ├── apktool.yml ← Apktool 元数据,记录编译参数,勿手动改 ├── res/ ← 资源目录,可自由增删改(注意命名规范) │ ├── values/ │ │ └── strings.xml ← 中文在此,改完记得保留 `translatable="false"` 属性 │ ├── drawable-hdpi/ │ └── layout/ ├── unknown/ ← assets/ 和其他 raw 文件在此安全修改原则:
- ✅
res/values/strings.xml:改文案、加新 string,ID 会自动注册进public.xml; - ✅
res/drawable-*/ic_launcher.png:替换启动图标,尺寸必须匹配对应 dpi 目录(hdpi/mdpi/xhdpi 等); - ✅
AndroidManifest.xml:增删<uses-permission>、改android:targetSdkVersion、加android:exported="true"(Android 12+ 强制要求); - ❌ 不要手动改
resources.arsc(二进制)、public.xml(Apktool 自动生成)、apktool.yml(版本/架构信息); - ⚠️
res/layout/*.xml中引用的@string/xxx必须在strings.xml中存在,否则 recompile 报error: No resource identifier found for attribute。
3.3 回编译(build):-a参数是重签开关,也是新手最大误区
命令模板:
apktool b app-src -o app-modified.apk -a-a:use aapt2 for building(强制用 aapt2 编译)这是 Apktool 2.9.0+ 的重大变更。旧版默认用 aapt(已废弃),新版默认用 aapt2。但 aapt2 对资源格式更严格:
res/values/strings.xml中不能有未闭合的<string>标签;res/drawable/下不能有.jpg(只认.png,.webp,.xml);AndroidManifest.xml中android:exported必须显式声明(Android 12+)。
加-a可提前暴露这些问题,比默认模式更可靠。
-o app-modified.apk:输出 APK 路径,注意:此 APK 未签名,无法安装!
提示:若编译报错
Error: Failed to generate resource table,大概率是res/values/public.xml被你误删或改坏。此时删掉整个app-src/res/values/public.xml,让 Apktool 重建即可(它只依赖strings.xml等内容自动生成)。
4. 常见问题排查:那些让你怀疑人生的报错,其实都有固定解法
Apktool 的报错信息向来以“精准但晦涩”著称。下面 5 条是我在模拟项目 X 和某跨平台系统逆向中反复踩过的坑,按出现频率排序,每条附现场复现方式和一招止血法。
4.1 现象:W: Could not decode attr+brut.androlib.err.UndefinedResObject
原因:APK 使用了自定义属性(如app:layout_constraintTop_toTopOf),但你的 framework-res.apk 版本太低,未定义该属性。常见于使用 ConstraintLayout 2.0+ 或 Material Components 的新 APK。
解决:升级 framework。先查 APK 的targetSdkVersion(看AndroidManifest.xml),再下载对应 Android 版本的 framework:
# 查 targetSdkVersion grep "targetSdkVersion" app-src/AndroidManifest.xml # 若为 33,则下载并注册 Android 13 framework apktool if framework-res-android-33.apk -t 33 # 解包时指定 apktool d app-release.apk -t 33 -o app-src4.2 现象:brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 134)
原因:JVM 内存溢出。aapt2 编译大 APK(>50MB)或资源极多的项目时,Java 默认堆内存(-Xmx256m)不够。
解决:增大 JVM 内存。编辑apktool脚本(Linux/macOS)或apktool.bat(Windows),找到java命令行,在-jar前插入:
# Linux/macOS 脚本中修改这一行: java -Xmx2g -jar "$APP_HOME/apktool.jar" "$@" # Windows bat 中修改: java -Xmx2g -jar "%~dp0apktool.jar" %*-Xmx2g表示最大堆内存 2GB,可根据机器内存调整(建议不低于 1.5G)。
4.3 现象:ERROR: Unable to open 'xxx.png' as a bitmap
原因:PNG 文件损坏或非标准格式。某些 PNG 经过 TinyPNG 压缩或 Photoshop 保存时启用了“交错”(interlaced),aapt2 拒绝加载。
解决:批量转为标准 PNG。用 ImageMagick 一行修复:
# Ubuntu/Debian sudo apt install imagemagick mogrify -interlace none -alpha on res/drawable-*/icon_*.png # macOS brew install imagemagick mogrify -interlace none -alpha on res/drawable-*/icon_*.png注意:
-alpha on确保透明通道保留,-interlace none关闭交错扫描。
4.4 现象:AndroidManifest.xml:23: error: No resource identifier found for attribute 'exported'
原因:你在AndroidManifest.xml中加了android:exported="true",但使用的 framework(如 Android 10 对应的 29.apk)不支持该属性(它是 Android 12 新增)。
解决:两种方案任选其一:
- ✅推荐:升级 framework 到 Android 12+(ID 31 或更高),并确保解包/编译全程指定
-t 31; - ⚠️ 临时绕过:删掉
android:exported属性,但仅限测试——正式安装到 Android 12+ 设备会崩溃。
4.5 现象:回编译后安装报INSTALL_PARSE_FAILED_NO_CERTIFICATES
原因:你用了-a参数编译,但忘了重签名。Apktool build 输出的是未签名 APK,adb install会拒绝。
解决:用apksigner签名(Android SDK 28+ 自带):
# 生成 debug keystore(首次运行) keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 # 签名 apksigner sign --ks debug.keystore --ks-pass pass:android app-modified.apk # 验证 apksigner verify app-modified.apk注意:
debug.keystore是标准调试密钥,密码固定为android,别用生产密钥!
5. 验证是否真正跑通:三步真机验证法,比apktool --version有用十倍
装完工具、跑通命令、甚至成功编译出 APK,都不代表你真的“会用 Apktool”。真正的验证,必须落到设备上——因为 APK 的生命周期终点是 Dalvik/ART 虚拟机,不是你的终端。我给自己定了一套铁律:任何 Apktool 操作,不经过以下三步验证,一律视为未完成。
5.1 第一步:ADB 安装 + 启动 Activity,确认基础结构无损
这是最底线验证。编译后的 APK 必须能通过adb install安装,并能拉起主 Activity。
# 安装(-r 覆盖安装,-t 允许测试 APK) adb install -r -t app-modified.apk # 查看 APK 的启动 Activity(从 AndroidManifest.xml 中找 intent-filter) aapt dump badging app-modified.apk | grep "launchable-activity" # 启动(替换 com.example.app/.MainActivity 为实际值) adb shell am start -n "com.example.app/.MainActivity"如果卡在安装阶段,检查INSTALL_FAILED_UPDATE_INCOMPATIBLE(签名冲突)或INSTALL_FAILED_DEXOPT(dex 优化失败,通常是--min-sdk-version设置过低);如果启动后闪退,用adb logcat抓FATAL EXCEPTION,90% 是AndroidManifest.xml权限缺失或exported错误。
5.2 第二步:资源一致性快照比对,揪出静默篡改
Apktool 在解包/回编译过程中,会对资源做标准化处理:比如把res/values/strings.xml中的\n自动转为\\n,把drawable/下的 SVG 转为 PNG,甚至重排public.xml中的资源 ID 顺序。这些改动肉眼不可见,但可能导致 UI 错位或字符串截断。
我的做法是:用 sha256sum 对比关键资源哈希。
# 解包前,先备份原始 APK 的资源哈希 unzip -p app-release.apk res/values/strings.xml | sha256sum > original_strings.hash # 解包后修改前,检查是否一致 unzip -p app-src/dist/app-modified.apk res/values/strings.xml | sha256sum > rebuilt_strings.hash diff original_strings.hash rebuilt_strings.hash # 若不同,说明 Apktool 重写了 XML。此时对比内容: diff <(unzip -p app-release.apk res/values/strings.xml) <(unzip -p app-src/dist/app-modified.apk res/values/strings.xml)重点看:
- 是否多了
tools:ignore="MissingTranslation"; - 是否把
<![CDATA[...]]>拆成了多行; - 是否把
'自动转为'。
这些都不是 bug,是 Apktool 的设计行为,但你要心里有数——改字符串时,别依赖原始 CDATA 结构。
5.3 第三步:反编译验证闭环,确认修改已固化
最硬核的验证:把刚编译签名的app-modified.apk再次用 Apktool 解包,检查你的修改是否还在。
# 二次解包(跳过资源和代码,只看 manifest 和 strings) apktool d app-modified.apk -o app-verify -r -s # 检查 AndroidManifest.xml 是否保留了你加的权限 grep "<uses-permission" app-verify/AndroidManifest.xml # 检查 strings.xml 是否包含你新增的 string grep "<string name=\"my_new_key\"" app-verify/res/values/strings.xml如果这里找不到,说明你的修改没进apktool b流程——常见原因是:
- 改了
app-src/res/values/strings.xml,但app-src/res/values/public.xml没同步(删掉 public.xml 让 Apktool 重建); - 改了
app-src/AndroidManifest.xml,但app-src/apktool.yml中isFrameworkApk: false被误改为true(会导致 manifest 被忽略)。
从那以后我每次修改完资源,都强制走一遍「解包 → 改 → 编译 → 二次解包验证」闭环,哪怕只是换一张图标。因为 Apktool 不是文本编辑器,它是资源管道,输入和输出之间永远隔着一层二进制翻译。希望帮到你。
本文还有配套的精品资源,点击获取