上周帮一个做 Android 逆向的朋友处理一个棘手问题他需要在真机上修改/system分区下的一个系统配置文件但无论用 adb shell 还是 root 后的文件管理器都提示“只读文件系统”。这让他卡了很久因为很多高级调试和定制功能都依赖对 system 分区的写入能力。这其实是一个经典的 Android 系统限制问题——出于安全和稳定性考虑Android 设备的/system分区默认以只读Read-Only模式挂载即使你拥有 root 权限也无法直接写入。很多人拿到 root 权限后第一反应就是去修改/system却发现依然“碰壁”。这背后的原因是 Android 系统在启动后将/system分区挂载为roread-only属性。单纯的remount命令有时会因为 SELinux、dm-verity 或系统完整性保护而失败。而将/system分区的文件系统从只读的ext4或erofs等重新挂载为可读写的ext4是解决这个问题的根本方法之一。这个过程不仅仅是执行一条命令它涉及到对 Android 启动流程、分区挂载机制和文件系统特性的理解。今天我们就来深入聊聊如何安全、有效地“破解” Android system 的读写限制并将其转换为可读写的 EXT4 文件系统。1. 为什么有 root 权限依然无法写入 /system拿到 root 权限su后很多开发者会自然地认为已经获得了系统的“完全控制权”。然而尝试向/system分区写入文件时却常常遇到Read-only file system的错误。这并非 root 权限失效而是由 Android 系统的多层防护机制共同作用的结果。1.1 核心限制挂载属性 (Mount Flags)这是最直接的一层限制。在 Android 启动过程中bootloader 和 init 进程会根据fstabfile system table文件中的配置来挂载各个分区。对于/system分区典型的挂载配置类似于/dev/block/platform/soc/1da4000.ufshc/by-name/system /system ext4 ro,barrier1,inode_readahead_blks8,dataordered 0 0注意这里的ro标志它明确指定了该分区以只读模式挂载。即使你通过su切换到了root用户这个挂载点本身的属性依然是只读的。这就好比一扇门分区被管理员系统从外面用锁ro标志锁住了你虽然拿到了房间里的最高权限root但门本身打不开你依然出不去。1.2 进阶防护SELinux 安全上下文SELinuxSecurity-Enhanced Linux是 Android 4.3 之后引入的强制访问控制安全模块。它给每个进程、文件、端口都打上了“标签”安全上下文。即使一个进程以 root 身份运行如果它的 SELinux 域domain没有被策略允许对某个标签的文件进行写操作那么写操作也会被拒绝。例如一个普通的 shell 进程u:r:shell:s0试图写入/system目录下的文件u:object_r:system_file:s0SELinux 策略很可能会拦截这次访问并产生avc: denied的日志。错误信息可能看起来像Permission denied但根源是 SELinux而非传统的 DAC自主访问控制权限。1.3 系统完整性验证dm-verity 与 AVB在较新的 Android 设备尤其是 Android 7.0 和启用 Verified Boot 的设备上/system分区可能受到 dm-verity设备映射验证或 Android Verified Boot (AVB) 的保护。dm-verity 会在内核层面验证分区中每个数据块的哈希值确保其未被篡改。如果检测到修改系统可能会拒绝挂载该分区或将其强制挂载为只读甚至导致无法启动。这意味着即使你成功以读写方式重新挂载了/system并修改了文件在下次重启时dm-verity 可能会检测到哈希不匹配从而引发各种问题。1.4 文件系统本身只读的 EROFS在一些最新的 Android 设备上厂商为了进一步提升系统分区的读取性能和安全性开始采用 EROFSEnhanced Read-Only File System作为/system分区的文件系统。EROFS 从设计上就是只读的无法通过简单的remount命令转换为读写模式。处理 EROFS 需要更底层的方法例如在刷机时替换整个分区镜像。理解这四层限制是成功进行读写操作的前提。我们的目标就是要在可控的范围内安全地绕过这些限制核心操作就是将/system分区以读写rw模式重新挂载。2. 从尝试到成功重新挂载 /system 为可读写 (rw)最常见的思路是使用mount命令的remount选项。但这远不止是执行mount -o remount,rw /system那么简单。你需要一个清晰的排查和操作路径。2.1 基础尝试与常见失败首先获取 root 权限并尝试最基本的命令adb shell su mount -o remount,rw /system如果运气好设备较旧或防护较弱这条命令可能直接成功。你可以用mount | grep system来验证输出中应该包含rw字样。但更常见的情况是失败并伴随各种错误Operation not permitted: 这通常指向 SELinux 限制。当前进程的上下文无权执行remount操作。Block device required: 你可能挂载的是/system目录本身而不是其对应的块设备。需要找到正确的设备节点。没有任何错误但挂载属性未改变: 命令执行了但系统可能因为 dm-verity 或其他内核机制在后台又将其恢复为只读。2.2 关键步骤找到正确的块设备并禁用 SELinux临时当基础命令失败时我们需要更精确的操作。第一步确定/system分区的实际块设备。不要直接对/system这个挂载点使用remount而是先找到它背后的物理分区。# 方法1: 使用 mount 命令查找 mount | grep /system # 输出示例/dev/block/sda21 on /system type ext4 (ro,seclabel,relatime,dataordered) # 方法2: 查看 /proc/mounts cat /proc/mounts | grep /system 记下设备路径例如/dev/block/sda21。第二步临时将 SELinux 设置为宽容模式 (Permissive)。这是绕过 SELinux 限制最直接但非永久的方法。在 Permissive 模式下SELinux 会记录违规行为但不会阻止。# 检查当前 SELinux 模式 getenforce # 如果输出是 Enforcing则设置为 Permissive setenforce 0 # 再次检查确认 getenforce第三步使用完整的设备路径进行重新挂载。现在使用找到的设备路径进行挂载mount -o rw,remount /dev/block/sda21 /system # 或者使用更明确的选项 mount -o remount,rw /dev/block/sda21 /system第四步验证挂载状态。mount | grep /system # 期望输出包含 rw例如(rw,seclabel,relatime,dataordered)如果此时输出显示为rw恭喜你你已经获得了/system的写入权限。你可以尝试创建一个测试文件touch /system/test_rw ls -l /system/test_rw rm /system/test_rw2.3 针对 dm-verity 设备的特殊处理对于启用了 dm-verity 的设备上述操作可能在当前会话生效但重启后修改会丢失或被检测到。要在这种设备上实现持久化修改通常需要刷入修改过的 boot 镜像移除或禁用 dm-verity。这通常通过刷入一个已经 patch 了verity标志的 boot.img 或 vbmeta.img 来实现。例如使用 Magisk 刷机时其preserve force encryption和disable verity选项就是做这个的。使用支持 dm-verity 关闭的定制 Recovery如 TWRP在 Recovery 模式下挂载/system时可以选择禁用 dm-verity。重要警告禁用系统完整性验证会降低设备的安全性使其更容易受到恶意软件的攻击。请仅在您完全理解风险、并且设备仅用于开发或测试的环境下进行此操作。3. 深入理解从 remount 到文件系统转换的误区澄清项目标题中的“转换成 EXT4实战”可能带来一个普遍的误解我们需要将/system分区的文件系统格式从其他类型“转换”为 EXT4。实际上在绝大多数情况下/system分区本来就是 EXT4 格式除了部分新设备使用 EROFS。我们做的“转换”并不是改变文件系统的底层格式如从 F2FS 转为 EXT4而是改变其挂载属性从只读 (ro) 变为读写 (rw)。这个过程更准确的描述是将已格式化为 EXT4 的/system分区从只读挂载模式切换为读写挂载模式。为什么会有“转换”的说法可能是因为在一些教程或工具中将“重新挂载为可读写”这个操作流程简化或口语化地称为“使 system 分区可写”而部分用户将其理解成了文件系统类型的转换。3.1 如何确认当前 /system 的文件系统类型执行以下命令mount | grep /system | awk {print $5} # 或者 blkid /dev/block/sda21 | awk -FTYPE\ {print $2} | awk -F\ {print $1}常见的输出有ext4: 标准 Linux 文件系统支持读写。erofs: 增强型只读文件系统设计上不支持写入。f2fs: Flash-Friendly File System多见于/data分区极少用于/system。如果你的设备显示是erofs那么标准的remount方法是无效的。对于 EROFS唯一的修改方法是在编译系统 (AOSP) 时将文件系统类型改为ext4。或者解包官方system.img修改内容后重新打包成ext4格式的镜像然后通过刷机工具Fastboot 或 Recovery刷入。3.2 真正的“转换”场景从 EROFS 到 EXT4这属于高级操作通常涉及系统编译或深度定制获取系统镜像从官方固件包中提取system.img或super.img并解包得到system分区镜像。解包镜像使用erofs-utils工具解包 EROFS 镜像或使用imjtool,lpunpack等工具处理稀疏镜像。修改内容在解压出的文件系统中进行所需的修改。重新打包为 EXT4 镜像使用make_ext4fs或其他工具将修改后的文件树打包成一个新的、EXT4 格式的system.img。刷入镜像在解锁 Bootloader 后通过fastboot flash system system.img刷入修改后的镜像。这个过程风险很高需要对应设备的特定知识且一旦出错容易导致设备变砖。对于绝大多数开发者和爱好者目标应该是“实现/system分区的读写”而非改变其文件系统格式。4. 工程化实践让 system 分区读写更稳定、更安全一次性挂载成功固然好但在实际开发或长期使用中我们更需要一个稳定、可重复且相对安全的环境。以下是一些进阶实践建议。4.1 创建自动化挂载脚本将挂载命令写成一个脚本方便每次启动后执行。可以将脚本放在/data/local/tmp/下。#!/system/bin/sh # mount_system_rw.sh # 切换到 root su # 设置 SELinux 为宽容模式可选根据需要 setenforce 0 # 查找 system 块设备。这里以 sda21 为例请根据你的设备修改 SYSTEM_DEVICE/dev/block/sda21 # 重新挂载为读写 mount -o remount,rw $SYSTEM_DEVICE /system 2/dev/null # 检查是否成功 if mount | grep -q /system .*rw,; then echo [OK] /system has been remounted as read-write. else echo [FAIL] Failed to remount /system. Check SELinux and dm-verity. fi通过adb push上传脚本并赋予执行权限adb push mount_system_rw.sh /data/local/tmp/ adb shell su chmod 755 /data/local/tmp/mount_system_rw.sh /data/local/tmp/mount_system_rw.sh4.2 通过 Magisk 模块实现持久化推荐对于已安装 Magisk 的设备编写一个 Magisk 模块是更优雅、更持久化的方案。Magisk 模块可以在系统启动早期以正确的上下文执行脚本从而绕过许多限制。一个简单的模块结构如下/system_rw_module/ ├── META-INF/ │ └── com/ │ └── google/ │ └── android/ │ ├── update-binary │ └── updater-script ├── module.prop └── post-fs-data.shmodule.prop: 模块属性定义。post-fs-data.sh: 在 post-fs-data 阶段执行的脚本这是挂载文件系统的好时机。在post-fs-data.sh中写入#!/system/bin/sh # 此脚本将在 post-fs-data 阶段执行此时可以安全地操作 /system 挂载点 # 重新挂载 /system 为读写 mount -o remount,rw /system # 如果需要可以在此处放置其他需要修改 /system 的操作 # 例如替换文件、设置权限等 # cp -rf $MODPATH/system/* /system/ # chmod 644 /system/etc/some_config.conf将文件夹打包成 zip通过 Magisk App 安装即可。这样每次开机/system都会自动被挂载为读写模式。4.3 重要注意事项与风险管控在对/system分区进行任何修改前请务必牢记以下几点备份备份备份修改/system前最好通过 TWRP Recovery 对整个系统进行完整备份NANDroid Backup。至少也要备份你打算修改的原始文件。理解修改内容不要盲目删除或替换/system下的文件。特别是/system/framework/,/system/app/,/system/priv-app/等目录下的核心应用和库错误的修改会导致系统无法启动或应用崩溃。注意文件权限和 SELinux 上下文如果你向/system添加了新文件需要设置正确的 Linux 权限如chmod 644对于普通文件chmod 755对于可执行文件和 SELinux 上下文通常使用chcon u:object_r:system_file:s0。否则可能导致服务无法启动或安全策略冲突。重启测试每次修改后进行重启检查系统是否能正常启动功能是否正常。如果卡在开机动画或重启循环你需要进入 Recovery 模式恢复备份或刷入原始系统镜像。明确目的问自己是否真的需要修改/system很多自定义需求可以通过 Magisk 模块系统化地修改/system而不实际写入、Xposed 框架修改运行时或修改/data分区下的用户配置来实现这些方式通常更安全、更容易恢复。对/system分区的读写操作是 Android 系统深度定制和开发的基石之一。它像一把锋利的解剖刀让你能触及系统的核心。但正如外科医生需要精确的解剖学知识和对风险的敬畏使用这把“刀”也需要你对 Android 的分区结构、挂载机制、安全策略有清晰的认识。从搞清楚mount命令和 SELinux 开始到谨慎地编写自动化脚本或 Magisk 模块每一步都应该是深思熟虑后的结果。最终我们追求的不是“破解”本身而是通过这种深度的控制权去实现更个性化的系统功能、进行更底层的调试分析或是完成那些在普通应用层无法做到的事情。记住能力越大责任越大在/system分区里操作的每一步都请留好后路。