ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Android SYSTEM.IMG解包打包全攻略:从ext4到erofs

Android SYSTEM.IMG解包打包全攻略:从ext4到erofs 简介这是一款面向 Android 系统底层定制与 ROM 开发场景的 SYSTEM.IMG 解包/打包工具主要服务于需要修改系统应用、权限配置或内核组件的开发者与高级用户。资源包共 245 个文件压缩后约 78.72MB文件以 XML 配置、EXE 可执行程序、DLL 动态库为主另含 shell 脚本、JAR 工具、busybox 及 update-binary 等组件便于在 Windows 或类 Unix 环境中完成镜像解包、内容修改与重新打包。已有 504 人浏览学习。借助该工具用户可提取 SYSTEM.IMG 内部结构对系统 App、服务或脚本进行替换和调优再重新生成镜像并刷入设备适合用于制作自定义 ROM、精简预装应用或修复系统问题。资源同时附带必要的运行库与脚本说明可降低环境配置门槛但需具备基本命令行和 Android 分区知识操作前建议备份原镜像以避免设备异常。1. SYSTEM.IMG到底是什么先搞懂你手里拿的是什么东西做ROM定制、系统精简或者固件逆向的人对SYSTEM.IMG这个名字应该都不陌生。它是Android系统分区镜像里最关键的一个系统应用、框架服务、系统库全部装在里面相当于整个操作系统的C盘。刷机包里那一大堆IMG文件system、boot、vendor、product各管一摊而SYSTEM.IMG就是最常被折腾的那一个。解包和打包SYSTEM.IMG说白了就是把这个镜像文件拆开改里面的东西再重新封装回去。常见的需求无非这么几类精简系统预装应用、替换系统字体和壁纸、注入Root或Magisk模块、定制开机动画、把一个ROM从A设备移植到B设备。折腾过刷机的人应该都有体会有时候Google官方镜像或者第三方ROM包里的系统分区有我们不需要的App直接删掉能省不少空间也能让系统跑得更清爽。还有一类人做移植需要把另一个型号设备的驱动和系统文件搬进来不改SYSTEM.IMG根本没法干活。但这里有个容易劝退新手的点SYSTEM.IMG不是一种固定格式的文件。不同厂商、不同Android版本、不同打包方式出来的镜像格式可能完全不同。常见的有raw ext4镜像、sparse稀疏镜像、erofs只读压缩镜像还有Android 10开始Google强推的动态分区格式super.img里套着system。格式不对工具用错轻则解不出来重则解包后打包回去刷进去直接变砖。所以第一个建议是拿到一个SYSTEM.IMG先别急着找工具乱解花一分钟搞清楚它的格式。怎么判断Linux下直接执行file system.imgWindows下用Hex编辑器看文件头。raw ext4的镜像开头是0x53 0xEFext4超级块的魔数sparse镜像开头是0x3A 0xFF 0x26 0xEDAndroid sparse magicerofs的开头特征则是0xE2 0xE1 0xF5 0xE0。格式识别对了后面的操作基本就顺了。识别错了解出来一堆乱码数据打包回去刷进去无限重启那才叫真的头疼。这篇文章我就把你需要知道的SYSTEM.IMG解包、打包完整流程捋一遍从环境准备、工具选择、实操命令到各种坑尽量一次说透。2. 环境准备Linux才是玩镜像的主场有了上面的基础接下来第一步就是准备一个可用的操作环境。这一步看起来基础但其实很多人卡在这里。实话实说解包和打包SYSTEM.IMG这件事主战场是Linux其次是macOSWindows只能算勉强能用。不是Windows不能做而是各种工具链交叉编译、权限管理、文件系统支持在Windows上都是麻烦事光一个make_ext4fs在Windows下就够你折腾半天的。如果你手上只有Windows电脑我建议两条路选一条装个WSL2Windows Subsystem for Linux或者直接VirtualBox装一个Ubuntu 22.04 LTS。我个人更推荐WSL2理由很简单文件系统互通方便镜像文件放在Windows目录下WSL里直接/mnt/c/就能访问不用来回拷贝。实测下来我在WSL2 Ubuntu下做了大量解包打包操作性能损失完全可以忽略对于1~2GB的system.img来说读写速度非常理想。不过需要留意的是WSL2在访问Windows NTFS路径时性能明显偏低建议把镜像实际放在WSL2的ext4文件系统内比如~目录收到Windows侧目录下先拷贝过去再操作。主流的工具链有这么几个按用途分类simg2img / img2simgAndroid自带工具转换sparse镜像和raw镜像属于Android源码system/core/libsparse的一部分网上能找到编译好的独立二进制。make_ext4fs / mkfs.ext4打包ext4格式的system镜像。前者是Android老牌打包工具后者是Linux原生工具两者可以互相替代但使用上有细微差别。erofs-utils处理erofs镜像的工具包包含mkfs.erofs和fsck.erofs。新机型Android 12大量使用erofs分区这套工具必须要装。Android SDK的ext4magic、debugfs用于在ext4镜像内部操作文件、恢复已删除文件也可以用来读取镜像内容。7-Zip、WinRAR解包某些厂商定制格式的分区镜像不过这只是临时办法。如果你是新手我建议直接从Ubuntu apt源安装基础工具然后去GitHub下载几个独立工具。比如在Ubuntu下执行sudo apt update sudo apt install android-sdk-libsparse-utils erofs-utils e2fsprogs这条命令装完simg2img、mkfs.erofs、fsck.ext4基本上就齐了剩下的就是找个顺手的地方放工具脚本。还有一个高频工具需要单独获取make_ext4fs在较新版本的Ubuntu仓库里不太好找需要从GitHub上找编译好的release或者从Magisk的仓库里拿Magisk自己附带了一个编译好的二进制。我常用的是GitHub上multipath项目下的prebuilt版本具体不细说了搜make_ext4fs prebuilt就能找到。环境准备好之后最好先快速验证一下工具是否能正常运行simg2img 21 | head -5 mkfs.erofs -V看到版本信息或者帮助输出说明链路OK就可以正式开始解包了。3. 解包实战从raw到文件的全流程前面的准备工作完成后就进入正题了。解包这个动作分两种情况拿到的是raw ext4镜像或者拿到的是sparse镜像。还有目前新机型越来越常见的erofs。3.1 先处理sparse镜像很多从官方刷机包特别是Pixel的factory image、小米的线刷包里解压出来的system.img其实是sparse格式。判断方法很简单文件头是3A FF 26 ED就是sparse。为什么厂商要打包成sparse格式因为raw的ext4镜像里有很多空洞没有数据的分区块打包成sparse可以跳过大段全零数据体积缩小不少刷机的时候传输也快。sparse镜像不能直接挂载或者解包要先转换成raw格式。命令非常简单simg2img system.img system_raw.img如果你的system.img本身就是raw格式simg2img也能正常处理它会原样输出不会报错。所以保险起见不管什么格式先跑一遍simg2img再说。转换成功后用file system_raw.img确认一下已经是Linux rev 1.0 ext4 filesystem data就可以下一步了。3.2 挂载ext4镜像直接读取Raw ext4镜像最方便的处理方式就是loop挂载不需要额外解包工具直接把镜像当作一块磁盘挂到系统上然后像操作普通文件夹一样访问里面的全部内容。mkdir -p /mnt/system sudo mount -o loop system_raw.img /mnt/system挂载后进入/mnt/system你就能看到完整的Android系统目录结构app、priv-app、framework、lib、media等。这里有一个重点如果你只是想读取文件比如提取某个APK挂载就够了到此为止不用继续往下了。但如果你要解包出来对文件做修改建议直接在当前挂载目录里面改改完再统一打包这个方案最不容易出错。那些先把所有文件复制出来、修改、再拷回去的搞法会引入文件权限和时间戳的混乱后期打包更容易翻车。注意部分镜像的selinux上下文和文件owner是特殊设置的。挂载时如果发现系统因为权限拒绝写入可以加-o rw,loop重新挂载如果有特殊文件比如只在Android环境下有效的符号链接检查一下链接目标是否完好。那如果挂载失败怎么办比如镜像损坏或者有特殊情况。这时候可以用debugfs来救命。debugfs是一种直接读取ext4文件系统结构的工具不需要内核挂载支持debugfs -R ls -l / system_raw.img也可以进入交互模式。这个工具在镜像无法挂载时特别好用至少能救回大部分文件不过操作体验一般适合应急。3.3 erofs镜像的解包方式如果你拿到的是新机型的SYSTEM.IMG且文件系统显示为erofs那挂载方式就不同了。Erofs是华为和OPPO、vivo等厂商从Android 12开始大量使用的一种只读压缩文件系统优点是体积小、读取性能好。它的存在越来越多不掌握erofs的处理方法你基本没法玩新机型。解包erofs镜像有两种主流思路第一种内核支持直接挂载。较新版本的Linux内核5.4默认开启了EROFS_FS支持可以直接挂载sudo mount -t erofs -o loop system.img /mnt/system如果报unknown filesystem type erofs说明当前内核没开erofs支持最常见场景是WSL2默认内核不带WSL2内核默认没有CONFIG_EROFS。看你的环境而定如果没开的话建议直接用第二种方式。第二种用erofs-fuse工具解包。GitHub上有erofs相关的fuse工具编译后通过用户态挂载erofsfuse system.img /mnt/system同时fsck.erofs也可以用来检查镜像是否完整。不过实测下来最直接的方式还是用extract.erofs这类的独立解包工具比如GitHub上erofs-utils新版本已经自带了dump.erofs可以把整个镜像导出为目录dump.erofs -i system.img -x /mnt/system这里-x参数就是把所有文件提取到指定目录里。这个方案非常稳我在几个不同厂商的镜像上都实测过没有任何问题。更老的方案是用extract.erofsPython脚本来解包但新版内核和erofs格式更新后那个脚本对某些特性支持不是很好不太推荐再用了。3.4 解包完成后的检查无论哪种方式解包出来我都建议先检查一下目录中的关键文件是否齐全。最核心的是看build.prop在/mnt/system或解包目录的system/下cat /mnt/system/system/build.prop | head -20正常情况下会输出一堆ro.开头的系统属性。如果这个文件存在说明解包过程基本没问题。再就是检查framework和app目录看看APK文件有没有完整解出来文件大小是否合理。到这一步解包工作就算完成了。接下来就是你要做的修改删APK、替换文件、改配置。这些操作就是普通的文件操作没什么好细说的。但是切记不要随意改变目录结构和原有文件的权限后面打包的时候会有影响。4. 打包回去重建一个能刷的SYSTEM.IMG如果说解包是开胃菜那打包才算正餐。很多人解包很顺利一打包就翻车刷进去开机卡在logo、无限重启、甚至直接变砖。为什么因为打包SYSTEM.IMG不是单纯把文件塞回一个镜像你得保证文件系统的结构、大小、SELinux上下文、inode数量等符合设备的需求。4.1 打包前的核心参数确认打包前要弄清楚几个关键参数目标文件系统格式、镜像大小、inode数量。这些参数不匹配轻则刷机校验失败重则开机后系统不认分区。镜像大小可以沿用原始镜像的大小也可以自行设定。如果你想精简后减小体积注意别比原始system分区还大那会直接报错。如果磁盘空间够大一点没太大关系系统挂载时会正常处理但如果你的镜像小到连原有内容都放不下打包就会直接失败。一般来说我建议保持原大小或者稍微加大5%左右留点余量。在解包前先记录原始文件大小ls -l system.imginode数量inode是文件系统索引节点的数量决定了这个分区最多能存放多少文件。如果你把原来系统里的几百个APK都解包出来再打包回去文件数量基本不变用默认值就行。但如果你打算额外往系统里塞很多新文件比如添加Google服务包、一组GApps就需要增加inode数量否则打包报No space left on device。分配公式很简单文件数再加15%~20%的余量就是合理的inode数。4.2 打包ext4镜像如果你解包出来的目录里有完整文件比如system/子目录打包ext4镜像用make_ext4fs下面是我常用的一套参数make_ext4fs -l 3000M -s -a system system_new.img /mnt/system/system解释一下-l镜像大小单位M或G写你需要的目标大小。-s生成sparse镜像如果要直接刷机或打包进zip这一步建议开启生成的镜像体积小很多。-a指定Android根目录挂载点最常见的是system。这个参数会关系到镜像内的文件属主和SELinux上下文的处理必须和原系统一致。最后一个参数是源目录路径。如果你用原生mkfs.ext4来做需要多一步先创建空镜像再挂载再拷贝文件再卸载。这种方式更方便塞文件也能更精确地控制参数但要额外注意文件权限。相比之下make_ext4fs一步到位很适合批量操作所以这个工具在定制ROM圈子里一直没被淘汰。一个容易踩的坑是make_ext4fs在文件较多时会比较慢并且它会自动把部分文件优化存放在连续区块导致最终镜像比实际文件总大小大很多这属于正常现象。但如果-l给的过大生成的镜像会膨胀到几个GB这时候要检查一下源文件是否正常排除有超大文件混进来的情况。4.3 打包erofs镜像如果你的机型用的是erofs文件系统打包工具就得换成mkfs.erofs。命令示例mkfs.erofs -zlz4hc,12 system_new.img /mnt/system/这里-z指定压缩算法。Erofs支持lz4、lz4hc等算法其中lz4hc压缩率更高代价是打包时间变长。根据机器性能不同一个2GB的镜像可能要跑几分钟。我在低配服务器上打包过CPU占满的情况下大约需要5~10分钟属于正常波动范围。打包erofs最关键的一点源目录必须是清理过的、状态干净的系统目录。不要在目录里留临时文件不要把挂载点本身当作源目录打包会打包进一堆挂载运行时的玩意儿。我每次都在一个独立的stage目录里做文件修改和整理最后再执行打包。4.4 重新打包成刷机包zip如果你手里的是Magisk模块、Recovery刷机包update.zip那打包成镜像后还需要重新打包成zip并做签名。这里有个常用的打包命令zip -r rom_update.zip META-INF/ boot.img system_new.img注意刷机脚本META-INF/com/google/android/updater-script里如果写死了package_extract_file(system.img, /dev/block/...)你替换同名文件就行如果改了文件名updater-script也得同步改。不过现代TWRP一般也会自动检测分区类型不一定要求SPARSE格式具体看你选的包结构。刷入后如果只是替换系统镜像理论上不用wipe data。但如果你是改了系统框架级别的文件比如framework、服务jar包强烈建议刷完后wipe cache/dalvik否则可能出现各种神奇的小问题比如设置闪退、桌面异常、偶发应用崩溃。这问题不是镜像打包错误是旧的ART缓存还保留着跟你新镜像里的代码不匹配。5. 实操中的常见问题与排坑实录镜像我前前后后处理了几十次踩过的坑不少。挑几个最典型的写出来你如果遇到类似情况直接照着排查能省下大半天时间。5.1 打包后刷入无限重启这是出现频率最高的问题。绝大多数情况下是SELinux上下文file_contexts没有正确处理。厂商固件在发布时每个文件都带有一个security.selinux属性比如u:object_r:system_file:s0如果你换成make_ext4fs重新打包它的-a system参数会自动帮你设置通用上下文但如果你用了mkfs.ext4这个属性会被清空。解决方法是打包前用ls -Z看下原解包目录的文件上下文然后在打包脚本里显式处理。另一个原因是文件权限变了。比如原来的系统文件很多是0644目录是0755如果你解包时用了Windows工具比如在Windows里解压权限位会被改成0777这种情况下打包后系统挂载检查文件许可时就会拒绝执行关键服务造成滚屏重启。我的习惯是解包后不经过Windows中转全程在Linux下操作这样权限会保持得很干净万一不得不在Windows弄打包前用chmod和chown统一修复。5.2 打包时报No space left on device镜像大小不够或者inode耗尽两者都会报这个错。如果你加了好几个大文件先确认-l给的大小是不是够。检查源目录总大小du -sh /mnt/system/再对比你设置的镜像大小留出至少15%余量。如果你塞了大量小文件报错信息里会提示inode相关这时候把-i参数加上手动指定inode数量make_ext4fs -i 1048576 -l 3000M -s -a system system_new.img /mnt/system-i的单位是字节表示每隔多少字节分配一个inode。这个值越小能容纳的文件数越多但相应文件系统元数据占用的空间也越大。一般一个系统分区有30万~50万inode就够用了具体按文件总数来估算。5.3 sparse镜像直接被recovery拒绝有些Recovery不认raw格式有些刷机包脚本又要求sparse格式。如果make_ext4fs没加-s生成的就是raw镜像。刷入时如果报invalid sparse file format或者failed to execute updater script说明格式不匹配。用img2simg转换成sparseimg2simg system_raw.img system_sparse.img转换后文件会明显变小这是正常的是文件镜像是稀疏存储刷机流程就能顺利走完。5.4 镜像挂载后看不到app目录有人解包后挂载镜像进入/mnt/system后发现app目录是空的或者直接看ls -l权限都是?。这种情况极可能是镜像本身是个加密的、或者厂商魔改了文件系统结构。比如早期EMUI的system镜像有特殊的分区表直接挂载会得到不可读的内容。遇到这种情况就不要再尝试硬挂载了直接用debugfs、7-Zip这类能按文件系统结构读取的工具走一遍确认是不是真的加密。如果是加密镜像里面文件多半是厂商签名过的解密本身超出本文范围不过这场景在日常刷机里已经很罕见了。5.5 打包后签名问题很多人改了system后会重新签名整个刷机包但忘了老设备的bootloader有签名校验。如果设备已经解锁unlocked bootloader签名校验通常可以绕过你不用太担心。如果你的设备没解锁改了system之后直接刷大概率直接被bootloader拒收。说实话不解锁bootloader的情况下做系统分区修改基本等于白忙活所以动手前先确认设备bootloader状态这是个老生常谈但永远有人踩的坑。5.6 不同大小镜像对刷机工具的影响ODIN、Fastboot、厂商专用工具对system.img的体积都很敏感。有的工具要求镜像必须小于等于分区大小有的工具还要求按block对齐比如4096字节。如果你的镜像加了一堆东西导致体积膨胀刷机工具可能报错。建议打包完成后用blockdev --getsize64确认下分区实际大小镜像别顶着上限走留点余量总归是好的。6. 一些进阶用法和我的心得体会除了常规的解包、修改、打包SYSTEM.IMG这块还有很多进阶玩法。这里分享几个我自己试过且验证可行的思路制作多卡刷包Multi-ROMAndroid 10之后动态分区是大趋势直接把system、vendor、product做成一个super.img再刷入需要用到lpmake工具Android dynamic partition工具链。这个玩法复杂度高一些需要把三个子分区镜像合并成super还要保证生成的super.img能被设备识别。我做过一次过程比较繁琐但刷完后的灵活性是传统方式比不了的。系统瘦身的最优解与其手动删APK不如用debloat.list策略。把不需要的包名列成清单写脚本批量删除。这个方式的好处是可追溯、可复用重新刷机后再次执行即可。脚本本身也很简单while read pkg; do rm -rf /mnt/system/system/app/$pkg rm -rf /mnt/system/system/priv-app/$pkg done debloat-list.txt分区镜像备份恢复刷机之前建议把原系统的system、boot、vendor分区全部备份下来打包成tar.gz存好。万一折腾坏了恢复原厂镜像比重新下载整个刷机包快得多而且还能保证是原厂没破坏过的干净环境。我个人实际操作中最大的体会是解包打包SYSTEM.IMG这件事本质上比的是耐性和细致不是技术难度。每次动手前先梳理清楚自己改了什么改了哪些文件原始的备份放在哪里。一旦出了问题至少能知道怎么往回退。像我就吃过亏解包完顺手把原始镜像删了改坏了之后只能重新下刷机包那感觉真心酸爽。最后再分享一个小技巧如果你只是想改改系统里的某个APK不需要完整打包整个system镜像可以考虑直接把APK提取出来用apktool解包、修改、重打包、签名然后用adb remount和adb push直接推到设备上。这样省去了整个镜像打包刷机的过程调试效率提高不少。只有当你需要批量修改或者做定制ROM时才需要走完整的镜像解包打包流程明确自己的目标再选工具往往事半功倍。本文还有配套的精品资源点击获取
返回列表