简介:这份资源面向Android刷机爱好者与系统开发者,提供针对MIUI等定制系统中system.new.dat与system.new.dat.br两种系统镜像文件的解包工具集,帮助解决系统分区内容查看、修改与备份的实际需求。压缩包共32个文件,约5.15MB,以pyd、dll、exe等Python运行库与可执行程序为主,辅以cmd批处理脚本、py源码及cfg配置,另含brotli.exe与sdat2img相关组件,覆盖从Brotli解压到镜像转换的完整链路。目前已有2702人学习下载。通过解包dat与解包br两套脚本,读者可将压缩或未压缩的系统镜像还原为可读目录结构,进而分析bin二进制与extract提取内容,完成系统应用替换、图标修改或设置调整等操作,并理解Brotli压缩在Android 8.1至9.0升级中的技术演进,是深入定制与优化Android系统的实用工具参考。
1. 从一次刷机卡白米聊起:system.new.dat.br 到底是什么
手里拿到一个 Android 卡刷包,解压后看到system.new.dat.br、system.new.dat、system.transfer.list三个文件,很多人第一反应是懵的——这不是一个能直接双击打开的镜像,而是一套「压缩 + 分块 + 映射」的组合拳。system.new.dat.br是 Brotli 压缩后的数据块,system.new.dat是解压后的原始稀疏数据,system.transfer.list则记录了每个数据块写到镜像哪个偏移。三者缺一不可,单独拿出任何一个都还原不出完整的 system 分区。
这套格式从 Android 5.0 开始大规模使用,MIUI、类原生、第三方 ROM 的卡刷包基本都走这条路。它的好处是刷机时增量写入、节省空间,坏处是对做 ROM 定制、提取系统应用、移植框架的从业者来说,多了一层「黑匣子」。你想改一个 build.prop、替换一个系统 APK、精简掉预装应用,都得先把这套格式拆回可挂载的 ext4 镜像。这篇笔记就把我实际拆包时用的工具链、参数和踩过的坑一次讲清楚,适合做 Android 刷机包定制、系统精简、ROM 移植的从业者照着复现。
2. 解包工具链选型:sdat2img、brotli 与 img2simg 怎么配
2.1 三个工具各管一段,别指望一个命令通吃
先把职责分清楚。system.new.dat.br到system.new.dat是 Brotli 解压,常用brotli命令行工具;system.new.dat+system.transfer.list到system.img是稀疏镜像还原,靠sdat2img.py;如果还原出来的镜像是 sparse 格式、需要转成 raw 才能挂载,还要simg2img。这三步是流水线,顺序不能乱。
我一般会建一个工作目录,把卡刷包里system.new.dat.br、system.transfer.list拷进去,原始 zip 留着不动,避免改坏了没后悔药。工具版本上,sdat2img.py建议用较新的 Python 3 版本,老版本对 transfer.list 的版本号(比如 2、3、4)兼容性差,遇到新 ROM 直接报unexpected version。
# 建工作目录,只拷贝需要的三个文件 mkdir -p ~/rom_work && cd ~/rom_work cp /path/to/rom/system.new.dat.br . cp /path/to/rom/system.transfer.list . cp /path/to/rom/system.patch.dat . 2>/dev/null || true # 确认文件完整性,br 文件通常几百 MB ls -lh system.new.dat.br system.transfer.list这段命令的逻辑很简单:把易变的操作隔离在独立目录,原始包保持只读。system.patch.dat是增量 OTA 才用到的,全量包一般没有,拷不到也不影响。参数上没什么可调的,关键是确认transfer.list和dat.br是同一个包里的,混用不同版本会直接导致镜像错位。
2.2 Brotli 解压:版本和参数决定成败
Brotli 解压本身不复杂,但工具来源有讲究。系统自带的brotli可能版本偏老,解压大文件时内存占用高甚至中断。我习惯用较新的静态编译版本,命令如下:
# 解压 br 得到 new.dat,-d 表示 decompress brotli -d system.new.dat.br -o system.new.dat # 校验解压结果大小,正常应比 br 大 2~4 倍 ls -lh system.new.dat-d是解压模式,-o指定输出文件名。这里有个容易翻车的点:如果brotli报corrupt input,八成是 br 文件本身下载不完整,或者被别的工具二次压缩过。先核对原始 zip 的 MD5,再重试。解压出来的system.new.dat大小应该明显大于 br,如果只大一点点,说明解压没走完,后面 sdat2img 必然失败。
2.3 sdat2img 还原镜像:transfer.list 是地图
真正把数据写成 ext4 镜像的是sdat2img.py。它的输入是 transfer.list 和 new.dat,输出是 system.img。
# 基本用法:transfer.list 在前,new.dat 在后,输出 system.img python3 sdat2img.py system.transfer.list system.new.dat system.img # 如果提示权限或编码问题,显式指定 Python3 python3 --version逻辑说明:sdat2img.py会逐行读 transfer.list,里面每条形如erase、new、zero的指令告诉它「从 dat 里取多少字节、写到镜像的哪个块」。参数顺序千万别反,反了会报ValueError: not enough values to unpack。输出system.img的大小由 transfer.list 里的块总数决定,通常 2~4 GB。如果输出只有几十 MB,说明 transfer.list 读错了或者 dat 没解压完整。
2.4 镜像格式转换:sparse 转 raw 才能挂载
有些 ROM 还原出来的system.img是 Android sparse 格式,file system.img会显示Android sparse image。这种镜像不能直接mount,要先转 raw:
# sparse 转 raw,输出 raw.img simg2img system.img system_raw.img # 确认格式,raw 会显示 Linux rev 0.0 ext4 filesystem data file system_raw.imgsimg2img的参数就是输入输出,没有多余选项。转完用file确认是 ext4 才能进下一步。如果本来就是 raw,这步可以跳过,但建议还是跑一次file确认,避免挂载时报wrong fs type。
3. 挂载与提取:把 system.img 变成可读目录
3.1 loop 挂载:只读挂载最安全
镜像转成 raw 后,用 loop 设备挂载到本地目录。我强烈建议只读挂载,防止误删系统文件。
# 建挂载点,只读挂载 sudo mkdir -p /mnt/system_img sudo mount -o ro,loop system_raw.img /mnt/system_img # 查看目录结构 ls /mnt/system_img-o ro,loop里ro是只读,loop表示用 loop 设备。挂载后就能看到app、priv-app、framework、build.prop等标准结构。如果报mount: wrong fs type,回到上一步确认是不是 raw ext4;如果报failed to setup loop device,可能是 loop 模块没加载,sudo modprobe loop一下。
3.2 提取与回写:改完要重新打包
提取文件直接cp就行,比如拿 build.prop 或某个 APK:
# 提取 build.prop 到工作目录 cp /mnt/system_img/build.prop ~/rom_work/build.prop.bak # 改完想回写,需要可写挂载或重新制作镜像 sudo umount /mnt/system_img注意:只读挂载下不能直接改。要修改系统文件,常见做法是把整个目录cp -a到本地,改完再用mkuserimg或make_ext4fs重新打包成镜像,然后按卡刷包格式反向生成system.new.dat和 transfer.list。反向打包工具链更复杂,img2sdat是常用选择,但版本匹配要求高,后面章节会讲。
3.3 反向打包:img2sdat 的参数与版本坑
改完目录要回写成卡刷包能识别的格式,用img2sdat:
# 把 raw 镜像转回 new.dat 和 transfer.list python3 img2sdat.py system_raw.img -o outdir -v 4 # -v 指定 transfer.list 版本,要和原包一致 ls outdir-o是输出目录,-v是 transfer.list 版本号。这个版本号必须和原 ROM 一致,原包是 3 你就写 3,是 4 就写 4,写错刷机时直接报错。img2sdat对 Python 版本和依赖敏感,建议在干净虚拟环境里跑。生成后再用brotli压缩成.br,整个反向流程才算闭环。
4. 避坑与排查:拆包时最容易翻车的五个点
4.1 现象:sdat2img 报unexpected version→ 原因:transfer.list 版本不匹配 → 解决:换新版脚本或核对 ROM 版本
老版sdat2img.py只认版本 1、2,遇到版本 3、4 直接退出。先head -1 system.transfer.list看版本号,再去工具仓库找支持该版本的分支。别硬改脚本里的版本判断,容易写出错位镜像。
4.2 现象:挂载报wrong fs type→ 原因:镜像还是 sparse 格式 → 解决:先 simg2img 转 raw
file system.img如果显示Android sparse image,说明没转 raw。补跑simg2img再挂载。这个坑我见过太多次,尤其是从某些第三方工具直接导出的镜像。
4.3 现象:解压 br 报corrupt input→ 原因:br 文件不完整或被二次压缩 → 解决:核对原始包 MD5,重新提取
有些下载工具会对文件做额外处理,导致 br 头损坏。用md5sum和原始包比对,确认无误再解压。如果原始包就是坏的,换来源。
4.4 现象:反向打包后刷机卡第一屏 → 原因:transfer.list 版本或块大小不一致 → 解决:严格对齐原包参数
反向打包时-v版本、块大小、镜像尺寸都要和原包一致。差一个参数,刷机时校验就过不去。建议先拿原包做一次「解包→不改→回包」的闭环测试,确认工具链没问题再动内容。
4.5 现象:挂载后目录为空 → 原因:挂载点被覆盖或镜像本身为空 → 解决:换挂载点,检查镜像大小
如果system_raw.img只有几 MB,说明 sdat2img 没读到有效数据。回头检查 transfer.list 和 new.dat 是否配套,以及 new.dat 是否解压完整。
5. 进阶技巧:用脚本把整条流水线串起来
拆多了就会发现,每次手敲五六条命令既慢又容易漏。我后来写了一个 shell 脚本,把「解压 br → sdat2img → simg2img → 挂载」串成一条龙,只在关键节点做校验。核心思路是每步之后用file和ls -lh确认产物,任何一步失败就exit 1,不带着错误往下跑。
#!/bin/bash set -e # 任何一步失败立即退出 WORK=~/rom_work cd "$WORK" # 1. 解压 br brotli -d system.new.dat.br -o system.new.dat [ -s system.new.dat ] || { echo "dat 为空"; exit 1; } # 2. 还原镜像 python3 sdat2img.py system.transfer.list system.new.dat system.img # 3. 判断是否 sparse,是则转 raw if file system.img | grep -q "Android sparse"; then simg2img system.img system_raw.img else cp system.img system_raw.img fi # 4. 只读挂载 sudo mkdir -p /mnt/system_img sudo mount -o ro,loop system_raw.img /mnt/system_img echo "挂载完成:/mnt/system_img"set -e是灵魂,避免中间失败还继续跑。[ -s file ]判断文件非空。file | grep自动识别 sparse 格式,省得手动判断。这个脚本我用了很久,唯一要注意的是挂载需要 sudo,跑之前确认有权限。
验证方法上,我习惯在挂载后立刻cat /mnt/system_img/build.prop | head,能看到内容说明整条链路通了。如果要做批量处理,把 ROM 路径做成参数传入,循环调用即可。从那以后我每次拆新包,都先跑一遍这个脚本确认工具链正常,再动具体文件——这个习惯帮我省掉了无数次「改了半天发现是解包就错了」的返工。希望帮到你。
本文还有配套的精品资源,点击获取