ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

三星I9000系统APK与ODEX合并:反编译回推完整环境搭建指南

三星I9000系统APK与ODEX合并:反编译回推完整环境搭建指南

简介:这份文档面向需要深度定制三星等闭源 Android 系统应用的中高级玩家与 ROM 爱好者,聚焦 APK 与 ODEX 的合并处理,解决系统应用在缺少源码、签名受限条件下难以反编译、修改与回编的痛点。压缩包共 1 个 docx 文件,约 23KB,以图文笔记形式记录工具准备、系统应用提取、反编译与打包、签名替换及汉化修改等环节的实操思路,并针对三星自定义 framework、语言包删减报错等典型问题给出迂回方案。目前已有 334 人学习,适合希望理解系统应用结构、掌握 apk manager 工作流并积累排错经验的读者参考,也可作为汉化与布局修改的入门指引。

1. 三星 I9000 系统 APK 与 ODEX 合并:从反编译到回推的完整环境搭建

手里这台 I9000 是前阵子从二手市场收来的,FROYO 2.2 系统,三星那套闭源 framework 把 /system/app 里的系统应用全做了 odex 化。想改个 TouchWiz 启动器的字符串,或者把 launcher2 换成姜饼风格,直接反编译 APK 会发现 classes.dex 根本不在包里——代码全在旁边的 .odex 文件里。这就是 apk 和 odex 合并要解决的问题:把优化过的 Dalvik 字节码还原成可编辑的 classes.dex,塞回 APK,再推回系统。装不好这套环境,apktool 反编译出来只有资源没有代码,改布局改语言包全是白费功夫。这篇记录的是我在 Windows 和 Linux 双环境下反复折腾 apk manager 4.9、smali/baksmali、adb 这一套工具链的完整过程,适合手里有老三星机器、想动系统应用但被 odex 卡住的人。

2. 环境准备:JDK、SDK 与 apk manager 4.9 的版本取舍

2.1 JDK 版本别追新,8 是这条工具链的舒适区

apk manager 4.9 和 baksmali/smali 这套工具是 Dalvik 时代的产物,跑在 JDK 8 上最稳。我试过 JDK 11 跑 script.bat,apktool 那层偶尔报Unsupported class file major version,虽然改JAVA_HOME能绕,但没必要给自己找事。Windows 下装 JDK 8u202 或更新的 8u 系列都行,Linux 用包管理器装 openjdk-8-jdk 即可。

装完验证:

java -version # 期望输出类似: # java version "1.8.0_202" # Java(TM) SE Runtime Environment (build 1.8.0_202-b08)

java -version输出里版本号必须是 1.8.x。如果系统里同时有多个 JDK,Windows 下检查JAVA_HOME指向 8 的安装目录,Linux 下用update-alternatives --config java切过去。这一步不确认,后面 baksmali 跑起来报UnsupportedClassVersionError你还得回头查。

2.2 Android SDK:只要 platform-tools 里的 adb

不需要装完整的 Android Studio。下载 SDK 的 command line tools,用 sdkmanager 只拉 platform-tools:

sdkmanager "platform-tools" # 装完后把 platform-tools 目录加进 PATH export PATH=$PATH:/path/to/android-sdk/platform-tools adb version # 期望输出 Android Debug Bridge version 1.0.xx

apk manager 的 script.bat 启动时会检测 adb 是否存在。如果你不想配环境变量,直接把 platform-tools 下的adb.exe(Windows)或adb(Linux)拷到 apk manager 主目录,脚本同样能识别。我一般倾向配 PATH,因为后面adb pull、adb push要反复用,拷来拷去容易版本混乱。

2.3 apk manager 4.9 的目录结构与首次运行

apk manager 4.9 解压后有几个关键目录,先认清楚再动手:

目录/文件用途
place-apk-here-for-modding放待反编译的 APK
place-apk-here-for-signing放待签名 APK(本流程基本不用)
projects反编译输出目录
keep打包时保持原样的文件
script.bat/script.sh主交互脚本
lib/apktool 等底层 jar

Windows 下双击script.bat,Linux 下chmod +x script.sh && ./script.sh。首次运行如果提示找不到 adb,按 2.2 的办法处理。脚本菜单里 9 是 Decompile,11 是 Compile,12 是 Sign,这几个编号记牢,后面反复用。

提示:apk manager 4.9 自带的 apktool 版本较老,反编译 FROYO 时代的 APK 够用。如果你拿它去碰 Android 5.0 以上的包,aapt 会直接报错,别怀疑环境,是工具代差。

3. 提取与反编译:从 /system/app 拿到可编辑的工程

3.1 两种提取方式:adb pull 与刷机包挂载

机器已 root 的情况下,最直接的是 adb 拉整个 system 目录:

adb root adb remount adb pull /system/app ./system_app adb pull /system/framework ./system_framework

adb root让 adbd 以 root 跑,adb remount把 /system 重新挂成可写。有些三星官方 ROM 的 adbd 不支持 root 重启,那就只能走第二条路:解压官方刷机包里的factoryfs.rfs,Linux 下 loop 挂载:

mkdir -p /mnt/factoryfs mount -o loop,rw factoryfs.rfs /mnt/factoryfs cp -r /mnt/factoryfs/app ./system_app cp -r /mnt/factoryfs/framework ./system_framework umount /mnt/factoryfs

-o loop把普通文件当块设备挂,rw是可写挂载,虽然我们只读拷贝,但有些 rfs 镜像只读挂会报错,加 rw 省事。Windows 下没有 loop 挂载,用 7-Zip 直接解 rfs 也行,或者干脆走 adb pull。

3.2 先装 framework:twframework-res.apk 是三星的命门

三星和 AOSP 最大的区别就在/system/framework/twframework-res.apk。反编译任何三星系统应用之前,必须先把这两个 framework 装进 apktool 的资源表:

apktool if twframework-res.apk apktool if framework-res.apk

apktool if是 install-framework 的缩写,把 framework 的资源 ID 映射写进~/apktool/framework/下。不装的话,反编译 TouchWiz30Launcher 时所有@com.sec.android...开头的资源引用都会解析失败,输出一堆Could not find resource警告,改出来的布局推回机器直接 FC。顺序上先 twframework 后 framework-res,我试过反过来,偶尔资源 ID 冲突,先 tw 更稳。

3.3 反编译 APK:apk manager 的 9 号选项与 odex 的处理时机

把目标 APK 拷进place-apk-here-for-modding,运行 script,选 9。反编译输出在projects/<apk名>/下。这时候打开res/能看到布局和 values,但smali/目录要么不存在要么是空的——因为代码在 odex 里。

关于 odex 和 apk 是否要先合并,原文说得很清楚:如果你不打算做可安装包(三星系统签名对不上,做了也装不上),反编译阶段合不合并无所谓。因为我们的路线是「反编译资源 → 改 → 打包 → 把改动的文件拖回原始 APK → 推回系统」,全程不需要重新签名,也就不需要完整的 classes.dex 参与打包。只有当你需要改 smali 代码逻辑时,才必须先把 odex 合进来。

4. APK 与 ODEX 合并:baksmali/smali 手工链路

4.1 为什么没有一键工具:批处理脚本底下就是这两条命令

市面上所谓「odex 合并工具」基本都是把 baksmali 和 smali 包了一层批处理。原理就两步:baksmali 把 odex 拆成 smali 文件,smali 再把 smali 汇编回 classes.dex。手工跑一遍反而清楚每一步在干什么,出错也知道看哪。

先准备 BOOTCLASSPATH 依赖的 jar。AOSP 通用的是这几个:

core.jar ext.jar framework.jar android.policy.jar services.jar

三星 I9000 还要额外加:

com.samsung.device.jar seccamera.jar sechardware.jar twframework.jar javax.obex.jar com.google.android.maps.jar

这些 jar 从system_framework目录里拷到 smali 工作目录,或者用-d参数指定目录。我一般直接拷过去,省得路径写错。

4.2 baksmali 拆 odex:-x 参数与依赖目录

java -jar baksmali.jar -x TouchWiz30Launcher.odex -d ./framework_jars -o ./out

-x表示输入是 odex 文件(不是 dex),-d指定 BOOTCLASSPATH 依赖 jar 所在目录,-o是输出目录。跑完out/下就是按包名分目录的.smali文件。如果报Could not find class之类的错,九成是-d目录里缺了某个三星专有 jar,对照 4.1 的清单补齐。

4.3 smali 汇编回 dex:-Xmx512M 不是随便写的

java -Xmx512M -jar smali.jar ./out -o classes.dex

-Xmx512M把 JVM 最大堆设到 512MB。TouchWiz 这类系统应用的 smali 文件数量大,默认堆容易 OOM,512M 是原文给的保守值,机器内存富裕可以给到 1G。./out是 baksmali 的输出目录,-o指定生成的 dex 文件名。成功后当前目录出现classes.dex,把它拷进反编译工程的根目录(和res/同级),再走 apk manager 的 11 号打包,代码改动才会进新包。

注意:合并后的 classes.dex 如果和原始 odex 对应的 APK 版本不一致(比如你拿 A 版本 APK 配 B 版本 odex),smali 汇编能过,推回机器大概率 bootloop。动手前确认 APK 和 odex 来自同一次刷机。

5. 打包与回推:keep 目录、资源替换和 adb push

5.1 11 号打包:系统文件选 y,keep 目录决定哪些文件保持原样

反编译改完后,script 选 11。提示是否系统文件时选y,接着提示是否复制原始文件选y,然后脚本停在「按任意键继续」——这里不要动,先去keep目录处理。

keep里放的是原始 APK 中不参与重新编译的文件。规则是:你改了什么类型的资源,就从 keep 里删掉对应的旧文件,让新编译的版本生效。

  • 改了values-xx语言包 → 删keep/resources.arsc
  • 改了layout/或xml/下的 xml → 删 keep 里对应的旧 xml
  • 改了图片 → 删 keep 里对应图片

删完回终端按任意键,place-apk-here-for-modding下生成带unsigned前缀的新 APK。

5.2 不重签名的迂回方案:拖文件覆盖原始 APK

三星签名拿不到,新包直接推回系统会因签名不一致被拒。做法是用 WinRAR 或 7-Zip 同时打开 unsigned 包和原始 APK,把 unsigned 包里改动过的文件拖进原始包覆盖。因为只替换了资源文件,签名块不受影响,系统认原始签名。

adb push modified.apk /system/app/TouchWiz30Launcher.apk adb shell chmod 644 /system/app/TouchWiz30Launcher.apk adb reboot

chmod 644别漏,权限不对系统应用加载会失败。推之前建议adb pull一份原始 APK 存电脑,FC 了能推回去。

5.3 汉化实操:values-zh-rCN 的建立与 arrays.xml 的坑

以 TouchWiz30Launcher 为例,反编译后进res/,建values-zh-rCN目录,把values/下的strings.xml和arrays.xml拷进去翻译。strings.xml里<string name="xxx">的文本直接翻;arrays.xml里带_values后缀的<string-array>是程序逻辑用的值,不能翻,只翻显示用的那个数组。

删语言包后打包报错是常态:某些 string 是该语言独享、values/strings.xml里没有,删了语言包 public.xml 里还留着引用。处理办法是看 apk manager 主目录的 log,它会告诉你 public.xml 第几行的资源不存在,打开 public.xml 删掉对应行——删的时候保留行号占位,不然下面所有行号错位,log 就对不上了。原文那句话我深以为然:不看 log 用 apk manager,等于没入门。

6. 避坑与排查:五条血泪记录

6.1 反编译成功但 smali 目录为空

现象:apk manager 选 9 跑完,projects/下只有res/和AndroidManifest.xml,没有smali/。原因:APK 是 odex 化的,classes.dex 不在包里,apktool 自然拆不出 smali。解决:按第 4 章走 baksmali/smali 合并出 classes.dex 放进工程根目录,或者确认你这次只改资源、不需要代码,那就忽略空 smali 直接打包。

6.2 打包报 public.xml 资源不存在

现象:删了values-it等语言包后,11 号打包报错,log 指向 public.xml 某行。原因:被删语言包里有values/strings.xml未定义的独享 string,public.xml 仍引用。解决:按 log 行号删 public.xml 对应条目,保留行号占位,重新打包。反复几次直到 log 干净。

6.3 推回系统后无限重启

现象:adb push 完 reboot,卡在开机动画。原因:多半是 APK 和 odex 版本不匹配,或 keep 目录该删的旧资源没删导致资源 ID 错乱。解决:进 recovery 用备份还原,或 adb push 回原始 APK。动手前adb pull原始文件是唯一后悔药。

6.4 baksmali 报 Could not find class

现象:java -jar baksmali.jar -x xxx.odex报找不到某个类。原因:-d指定的依赖目录缺三星专有 jar。解决:对照 4.1 清单,把com.samsung.device.jar、twframework.jar等从 system_framework 拷进依赖目录。

6.5 framework-res 改完语言选项没变

现象:改了 framework-res.apk 只留英简繁,推回后设置里语言列表没变。原因:三星还有 twframework-res.apk 参与资源解析,只改 framework-res 不够。解决:twframework-res 同样处理,删raw-xx只留raw、raw-zh-rCN、raw-zh-rTW,values 同理保留values-land、values-port、values-hdpi和中文目录。改完先做成刷机包备份,FC 了 recovery 还原再调。

7. 装完怎么验证:三步确认这套环境真的跑通了

环境搭完别急着改大东西,先用一个无关紧要的系统 APK 走一遍全链路验证。我一般拿TouchWiz30Launcher.apk开刀,因为它资源多、odex 也在,能同时验证反编译、合并、打包、回推四个环节。

第一步,验证反编译和 framework 安装是否到位。选 9 反编译后,进projects/TouchWiz30Launcher/res/看有没有values-zh-rCN之外的语言目录,再打开res/layout/随便一个 xml,确认里面@drawable/引用能对应到res/drawable-hdpi/下的实际文件。如果全是@null或报资源找不到,回 3.2 重装 twframework。

第二步,验证 odex 合并链路。按第 4 章跑 baksmali 和 smali,确认out/下 smali 文件数量在几百到上千量级,classes.dex生成后大小和原始 odex 同数量级(差太多说明依赖没找全)。用unzip -l classes.dex看不了 dex,直接看文件大小即可,TouchWiz 这类应用一般 2MB 上下。

第三步,验证回推和签名迂回。改一个strings.xml里的显示文本,打包、拖文件覆盖原始 APK、push、reboot,看桌面启动器上那个文本有没有变。变了说明整条链路通;FC 了说明 keep 目录处理或资源 ID 有问题,回 5.1 复查。

验证项通过标准失败回查
framework 安装反编译无资源找不到警告3.2 重装 twframework
odex 合并classes.dex 大小与 odex 同量级4.1 补依赖 jar
打包回推改动文本在机器上生效且不 FC5.1 keep 目录清理

从那以后我每次动系统 APK 之前,都强制先adb pull一份原始文件到电脑、再拿一个无关紧要的应用走一遍上面三步,确认工具链没坏才碰真正要改的包。这套环境不复杂,但版本和依赖的坑一个接一个,走通一遍验证流程比看十篇教程都管用。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进