
在做系统定制这类事情时很多人把“绕过检测”想得太简单以为在build.prop里改一行ro.product.modelAIDA64就会乖乖显示你想要的型号。实际上Momo这种检测工具看的不是单一属性而是一整套系统行为证据链AIDA64这样的硬件测试工具也会把内核、传感器、CPU调度器这些底层信息全部拉出来等你刷完机再打开一看改过的地方和没改过的地方互相矛盾一眼就是“移植机”。我维护AOSP定制系统好几年经常遇到这类问题测试机上刷了userdebug版本Momo直接弹出十几个红色检测项我把型号改成了某款主流机型AIDA64里却显示主板型号仍然是开发板的代号。这些坑背后其实是一个核心问题设备画像不是几个人为设置的字符串而是系统从内核到用户态逐层上报信息的汇总。本文就以我自己编译AOSP、刷入真机、再逐一验证Momo和AIDA64检测结果的完整过程为例讲清楚从编译环境搭建到设备画像配置的实操链路以及哪些检测项能通过、哪些无论如何都过不了。说明一下前提以下操作只建议在你自己拥有的测试设备上进行用于系统开发、应用兼容性测试和隐私研究。别把思路拿去对付金融、社交账号这类真正意义上的风控体系那既违法违规也大概率翻车。1. 先搞清楚检测方在看什么Momo和AIDA64的检测逻辑拆解定制ROM的整个过程本质上就是“站在检测方的角度反向校准设备画像”。你不先理解Momo怎么看AIDA64怎么读做出来的系统就是改了一堆表面参数但一验就穿。1.1 Momo不是靠单一特征而是“组合出证据链”Momo是一款专门检查Android设备是否存在root、Magisk、Xposed、异常系统属性、异常挂载等情况的检测工具。它现在不光在玩机圈流行很多应用的“风险环境检测”也会用类似逻辑。记住一个关键点Momo不是一个“查一下su文件在不在”那么简单的东西它的判断建立在几十个检测项的交叉验证上。常见的检测项大概有这么几类系统属性类ro.debuggable是否为1、ro.build.type是否是userdebug或eng、ro.build.tags是否包含test-keys、ro.secure是否等于0、ro.build.selinux是否为0或permissive。文件系统类/system/bin/su、/system/xbin/su、/sbin/su这类路径是否存在/system/app下有没有MagiskManager对应的包路径/system/etc/init/里是不是多了可疑的rc脚本。运行环境类SELinux状态是否Enforcing、dm-verity是否处于disabled/乱报状态、kernel是否被替换成非官方签名。挂载类system、vendor、data分区是不是处于读写挂载状态有没有把magisk的镜像直接挂到某个目录上。你可以把Momo理解成一个“审计员”它不依赖任何一条证据就下结论而是把所有信息汇总后给出“这系统不像原厂”的概率。所以很多人在玩机时只改了ro.build.tagsrelease-keys其他红色项还在Momo照样判违规。1.2 AIDA64做的事把设备画像拉到桌面上AIDA64不是安全检测工具它的作用是读取设备硬件和系统信息按理说跟“绕过”没关系。但恰恰因为它忠实读取系统底层数据才会把定制ROM里“改不干净”的部分暴露出来。它会从这几个来源读取信息Java API层Build.MODEL、Build.MANUFACTURER、Build.FINGERPRINT、Build.HARDWARE、Build.DEVICE这些最终来自/system/build.prop或vendor/build.prop。/proc 文件系统/proc/cpuinfo里的处理器型号、核数、Features/proc/meminfo里的内存信息/proc/cmdline里的内核启动参数。/sys 文件系统传感器节点、电池信息、屏幕参数、触摸IC型号等基本上是设备树(driver)直接暴露出来的。内核实时状态内核版本、内核编译工具链、TCP拥塞算法、CPU调度器类型。所以AIDA64更像一面“照妖镜”。你改了Build.MODEL它会显示新机型但你去“设备信息”页看显示面板型号可能还是原厂那个编号这就形成了矛盾。Momo看的是安全属性AIDA64看的是物理属性两者叠加之后你定制ROM的“设备画像”是否协调一眼就能判断。2. 搭建AOSP编译环境的正确姿势Ubuntu、Docker与依赖问题真正动手前你必须有一个能稳定编译AOSP的环境。这里很多新手第一个反应就是拿自己电脑硬扛结果同步源码就同步了两天编译到一半内存爆掉。实际上编译AOSP的底线要求并不低但也有不少优化空间。2.1 编译机器的最低底线内存、磁盘、耗时和OS选择AOSP各版本对机器要求不大一样但基本逃不出下面这个表格项目建议规格备注操作系统Ubuntu 20.04 / 22.04 LTS其他发行版也可以但依赖包名不同Ubuntu生态最顺内存16GB起步32GB更稳Android 13以后开R8/JIT内存吃得厉害9和11在16GB下也能过磁盘至少300GB可用空间源码加out目录轻松超过200GBSSD是刚需Swap最少8GB内存偶尔不够时靠swap续命但别指望swap弥补16GB以下的内存CPU8核以上时间差很大8核大概2-3小时16核能压到1小时左右JDK版本Android 9用OpenJDK 8Android 11及以上用OpenJDK 11版本不对直接编译失败如果只是想做系统层的小修改没必要追最新版本。我个人的体会是Android 9和Android 11是两个比较成熟的定制起点因为对应的第三方kernel和设备树资源最丰富踩坑时也更容易找到参考。2.2 依赖安装与源码同步最容易被“半路失败”卡死的环节在Ubuntu上安装编译AOSP的依赖网上有很多脚本但大家容易漏掉的是这两个包libssl-dev和libncurses5-dev。Android 9的编译特别吃ncurses5Ubuntu 20.04之后默认库里已经没有了需要手动装。普通依赖安装可以这样执行sudo apt update sudo apt install -y git-core gnupg flex bison build-essential zip curl \ zlib1g-dev libc6-dev-i386 libncurses5-dev libncursesw5-dev \ x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils \ xsltproc unzip fontconfig openjdk-8-jdk python3注意这个命令里我特意加了python3。Android 11之前的编译脚本很多时候还用python2但Ubuntu 20.04默认不带python2需要自己装或者配置软链。如果你编Android 11记得还要装一次OpenJDK 11并把默认java版本切换过去。源码同步强烈建议用镜像源别直接用谷歌官方源不然网络折腾死人。这里以清华AOSP镜像为例大概流程是mkdir -p ~/aosp cd ~/aosp repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-9.0.0_r61 repo sync -c -j8-c的意思是只同步当前分支而不是把上千个仓库的全部历史都拉下来能省大量磁盘空间和时间。如果你需要做多个版本可以每个版本独立目录别混在一起。同步经常断我的习惯是写一个循环脚本断掉就自动重连直到所有仓库都显示完成。2.3 用Docker临时编译适合只想改少量配置文件的人不是所有人都有条件专门腾一台Ubuntu机器。如果你只想改build.prop、塞几个预置apk、改SystemUI的包名等轻度定制用Docker跑AOSP编译环境反而更方便。常见做法是用一个带全部依赖的Ubuntu容器把源码目录挂载进去docker run -it --rm -v ~/aosp:/src -w /src \ ubuntu:20.04 bash容器里再装依赖或者提前做成镜像。不过注意Docker里编译AOSP对挂载卷的I/O性能要求很高macOS的Docker Desktop如果文件系统是gRPC-FUSE速度会明显变慢建议把源码放在Linux主机上。真机工程师通常不会全程Docker但临时测试完全够用。3. 从源码到刷机包第一次编译必须理解的几个关键点很多人卡在编译这关其实不是命令难而是不理解user、userdebug、eng这三种构建类型的区别。这个区别直接决定后续你在Momo里会看到什么。3.1 为什么第一次建议用userdebug而不是debugAOSP的lunch目标名里常见的后缀有eng工程师模式功能最全但系统属性大量开放刷完必被Momo检测。userdebug在user基础上开放adb root和部分调试功能能用来抓日志、改属性。user接近量产版ro.debuggable0ro.build.typeuser最接近原厂系统。如果你想快速验证定制效果先用userdebug编译方便adb root进去改文件但如果你想验证检测结果最终一定要切到user版本。因为Momo对userdebug的检测几乎是必然亮红的这不是你改某个属性就能彻底掩盖的system server里很多行为都会不一样。3.2 编译命令流和两个常见错误AOSP编译的经典流程如下# 进入源码根目录 cd ~/aosp # 加载编译环境 source build/envsetup.sh # 选择目标这里以通用arm64镜像为例 lunch aosp_arm64-userdebug # 开始编译-j后面的数字根据CPU核数来 make -j16如果你的设备是特定机型lunch时选择对应的device配置。但开发板上或通用镜像用aosp_arm64/target就行。编译到一半最常见到下面几个错误Out of memory或者Killed加swap或者把-j调小。比如16核机器用-j8稳住比速度重要。Jack server相关报错Android 9之前的版本用Jack编译Java代码对内存和tmp目录权限有要求。可以配置JACK_SERVER_VM_ARGUMENTS-Xmx4096m或者干脆编Android 11R8替代Jack之后这类问题少一大半。编译成功后输出路径一般在out/target/product/你的设备名/里面会有system.img、vendor.img、boot.img等镜像。刷机时如果你用的是官方解锁过的bootloader直接fastboot刷入即可fastboot flash boot boot.img fastboot flash system system.img # 如果还有vendor分区 fastboot flash vendor vendor.img fastboot reboot刷机前千万注意备份原厂镜像尤其是Bootloader、基带、persist这三个分区。定制ROM翻车的概率不低炸了基带后悔都来不及。4. 设备画像改造从build.prop到内核cmdline哪些能改哪些改不动设备画像这个词听起来玄实际就是“系统所有能对外上报的信息”的集合。改造它不是改一个文件而是要从“检测方会读哪些地方”反推过去。4.1 入门级操作在源码产品配置里改系统属性如果你是在源码里定制不建议直接改编译产物里的build.prop而应该在设备产品配置目录里设置变量。比如你在device/厂商/设备名/device.mk里会看到很多PRODUCT_开头的变量关键画像属性一般是这样配置的PRODUCT_MODEL : 你要显示的型号 PRODUCT_BRAND : 你要显示的品牌 PRODUCT_DEVICE : 设备代号 PRODUCT_MANUFACTURER : 生产商 PRODUCT_NAME : 产品名这些变量最终会由build系统生成build.prop里的ro.product.model、ro.product.brand等属性。比直接改文件规范而且重新编译时会自动生成不会每次都被覆盖。如果你只想快速验证某一个属性也可以先在编译好的镜像上手动改再用magiskboot重新打包boot.img或直接adb root后修改/system/build.prop并重挂载。不过这种改动是临时的一重启可能被文件系统校验干回去。4.2 只改build.prop远远不够AIDA64真正在意的“硬信息”在哪很多人改完build.prop重启打开AIDA64发现“主板型号”还是原厂代号“内核版本”还是原来的编译者信息。原因在于这些信息不是build.prop提供的而是来自内核、/proc和驱动节点/proc/cpuinfoCPU型号、Features、CPU part值由内核根据实际SoC填充用户空间改不了。/proc/cmdline内核启动参数由bootloader传递改系统分区对这块没用。/sys/class/dmi/id 或者 /sys/firmware/devicetree/base设备树信息由boot.img里的dtb提供。传感器、屏幕、电池型号由各个内核驱动直接上报基本都在/sys底下。这就是为什么很多“改串改型号”的工具只能改wifi、蓝牙等文件级信息但改不了AIDA64里的CPU型号。想要彻底改掉这一类底层硬件标识你需要修改设备树、内核配置甚至重新编译kernel。这部分难度直接上升一个级别不是每个ROM都能做到而且很容易把设备刷成砖。我自己在实际项目里的取舍是如果目标是让AIDA64显示的“设备品牌、型号、系统版本”保持一致build.prop和对应overlay足够了如果连主板信息都要伪装那就要把device.mk里的板级配置、内核config、dtb全部对齐工程量大且收益有限多数时候没必要。4.3 从源码编译层面做“画像一致性”修改以Android 11为例一个比较完整的修改流程大概是在device/我的厂商/我的设备/BoardConfig.mk里定义硬件相关参数。在device/我的厂商/我的设备/device.mk里配置PRODUCT_MODEL、PRODUCT_BRAND等。在对应产品的overlay/frameworks/base/core/res/res/xml/device_config_overrides.xml或者config.xml里覆盖系统配置让Settings里显示的设备名称也保持一致。如果改了设备型号建议同步改vendor分区里的prop文件例如vendor.build.prop避免Settings与AIDA64读到的值不一致。重新编译并刷机后用getprop | grep ro.product检查一遍确保所有ro.product.*属性和你的目标画像一致。这一步做完检测方获取到的“设备身份”基本统一了。注意你改的必须是一整套组合而不是只改一个model。Momo和AIDA64都不傻它们会横向对比Build.MODEL与Build.DEVICE、Build.HARDWARE等值如果Model是某大厂旗舰Device却是你手上的开发板代号立刻就能看出来你改过。5. 用Momo和AIDA64验证效果哪些项能过、哪些项目前无解改完重新刷机别急着看结果就下结论。验证阶段反而最暴露问题。5.1 Momo检测userdebug构建想通过几乎不可能如果你编译的是userdebug版本Momo打开必定一片红。我就直接告诉你结论在这个状态下你靠改几个属性是过不干净的。因为userdebug构建本身就自带以下特征检测项userdebug默认状态你想伪造的结果ro.build.typeuserdebug可以在build.prop里改成userro.debuggable1可以在build.prop里改成0ro.build.tagstest-keys可以改成release-keysadb root可用无法在运行时隐藏系统服务状态会暴露系统签名非官方除非你手里的key本来就接近原厂否则无法伪造dm-verity可能关掉修改启动配置会触发更深层的完整性校验所以如果你真的想让Momo基本不报异常必须编译user版本并且不要挂载Magisk、KernelSU或任何root方案。你只要安装了rootMomo检测到su或者相关文件是铁定的那不是改属性逃得掉的。保持SELinux Enforcing不要为了让root工具工作改成Permissive。使用官方AOSP签名并且system、vendor分区保持只读挂载。我实测过一个干净的AOSP user版本Momo检测项里大部分是绿色或黄色只有设备解锁状态、bootloader解锁状态这些硬件级别信息没法隐藏。这已经很接近“看起来是一个自定义原厂系统”了。5.2 AIDA64验证画像统一性检查AIDA64的验证方式和Momo不一样它不会判定你“异常”但你能从显示结果里看出设备画像是否自洽。我习惯会看这几页“概览”页手机型号、厂商、Android版本、内核版本。“主板”页主板型号和芯片组。“系统”页Root权限、KNOX版本、加密状态。“传感器”页接近传感器、加速度计等列表。修改前的典型情况是build.prop已经改了目标型号但主板页显示的还是原设备SoC传感器列表里还挂着原机的传感器型号。修改并重新编译后概览页基本能对齐但主板页的芯片组名称由内核SoC型号报告决定这个想改就得改内核。5.3 我的一份实测结果参考下面是我在某测试机上的一段印象对比不是固定结论但能说明问题检查位置修改前修改后AIDA64概览-型号原始型号build.prop中自定义的型号AIDA64概览-制造商原厂名自定义品牌名AIDA64主板-硬件仍显示真实SoC代号仍显示真实SoC代号AIDA64系统-Root权限已Root未Root无suMomo检测总体大量红项部分黄项无严重Root证据也就是说改动作业只能覆盖“用户可见的设备身份层”无法覆盖“芯片和驱动上报的物理层”。如果哪个ROM号称能把AIDA64里CPU型号都改成骁龙8 Gen3那大概率是改了AIDA64的显示字体或者做了Xposed注入而不是真正改了内核上报结果很容易一升级就失效。6. 这次定制过程中踩过的坑和几条有用的边界建议最后这部分是实操经验不聊理论。6.1 别把它当成“银弹”AOSP定制ROM能解决的是“系统层设备画像一致性问题”它能让你以一个干净、非root、非测试版系统的姿态出现在Momo这类检测工具面前。但它不是万能的。bootloader解锁状态、原始硬件信息、基带版本这些都会在更深层暴露身份应用如果采用服务端风险决策不是本地检测你再怎么魔改设备画像都可能被关联出来。所以我建议把目标定清楚你是为了学习Android系统架构、做隐私隔离、做应用兼容性测试还是为了绕过某个应用的检测前者值得研究后者风险极高而且大概率得不偿失。6.2 几条让你少熬夜的实操经验第一永远保留一份原厂完整备份。写这篇文章用的测试机我至少刷崩过三次都是靠备份恢复的。如果你连persist分区都能拿到别犹豫全分区备份。第二改属性时尽量在源码编译期做别在运行期用sh改。运行期改属性看起来方便但很多Android系统组件启动后就不再重新读属性了结果就是你改完getprop看到新值但应用读到的还是旧值检测结果照样不对。第三日志里别留痕迹。如果你在userdebug里调试完准备出user版本时记得把ro.debuggable、ro.secure、persist.sys.root_access这些改干净编译输出目录最好也make clean一次防止旧产物串数据。第四不要随便下载来路不明的“AIDA64序列号/注册机”。那类文件很容易被插入木马和Hook代码注入进测试机后反而会污染你的验证结果。AIDA64免费版足够看到关键属性没必要冒这个险。6.3 最后再分享一个小技巧每次刷完机我做的第一件事不是开Momo而是先用adb连上去跑一遍系统属性清单adb shell getprop | grep -E ro.product|ro.build.type|ro.debuggable|ro.secure先把这些基础属性对齐再进系统看AIDA64和Momo。这个小习惯能帮你快速判断失败出在哪一层——是属性没改对还是底层硬件信息不一致还是root后门没清干净。排查思路理清了半天能解决的问题就不用拖到周末。