type
Post
status
Published
date
Oct 27, 2026
slug
summary
tags
安全
Linux
逆向
ColorOS
category
心情随笔
icon
password
1. 摘要
本文分析两条检测链路:
- OPLUS uxicons 残留:
/data/oplus/uxicons/{pkg}/...,权限和 SELinux 策略都对appdomain敞开,是主信号。
- ColorOS splash 快照缓存:
/data/system/splash/...,SELinux 层放行,DAC 是主要关卡,是增强信号。
检测本质是一个已知文件名的存在性 oracle:不需要读文件内容,只需要按文件名探测文件是否存在。代价是必须枚举或猜测文件名,这也解释了实现里为什么会出现 displayId × activityType × 图标变体的暴力循环。
2. 核心模型:已知文件名的存在性 oracle
探测要过两道门:DAC 和 SELinux。
在 uxicons 上,两道门都是敞开的;在 splash 上,SELinux 基本放行,DAC 是唯一关卡。
2.1 uxicons:权限全开的 oracle
关键路径和标签:
路径 | mode | 标签 |
/data | 0771 system:system | system_data_root_file |
/data/oplus | 0775 system:system | system_data_file |
/data/oplus/uxicons | 0777 system:system | uxicons_data_file |
{pkg}/ 及 png | 推断 ≥0644/0755 | uxicons_data_file,(/.*)? 继承 |
init 原文里有:
SELinux 侧,CO15 / CO16 的
system_ext_sepolicy.cil 一致:注意 dir 权限里有 read。配合 0777 的 DAC,任意 App 可以直接
opendir() 枚举整个 uxicons 目录,不用逐包猜。并且 uxicons_data_file 是 mlstrustedobject,多用户 MLS category 不拦截。为什么设计成这样? ART+ 主题图标是在每个 App 自己的进程里加载的:framework 的
OplusUXIconLoader.findAppDrawable() 挂在 PackageManager 的 loadIcon 链路上,App 进程自己去 /data/oplus/uxicons/{pkg}/{prefix}.png 解码自己的图标。既然要求所有 App 都能读自己的图标,权限就只能对整个 appdomain 开。检测是该设计带来的直接可探测结果。3. 数据从哪里来
3.1 splash:system_server 的启动画面快照缓存
splash 的写入者在
oplus-services.jar:前身是 ColorOS 7 的
ColorAppStartingSnapshotPersister,有完整反编译源码。触发时机:应用启动、starting window 退出 / 首帧绘制完成后,
SurfaceControl.captureLayers 截主窗口,webp 有损落盘。读取时机是桌面点图标时的 preloadAppSplash,即“应用秒开”。关键限制来自 ColorOS 7 源码语义:截图只对全屏、非黑名单、且属于系统应用或 RUS 云控白名单里的第三方应用发生,或者云控开关
isSupportSplashSnapshotForAllApps 全开。也就是说,第三方应用会不会进 splash 缓存是云控决定的。这条 oracle 对 root manager 这类第三方包存在天然漏报面。uxicons 才是主信号,splash 是补充。
3.2 uxicons:OPLUS 桌面的图标库
写入侧在桌面(OplusLauncher,platform_app 域):
- 云下载:
UxIconDownloadManager/CheckIconUpdateRequest;
- 图标风格切换;
- 新装应用首次渲染图标;
- 用户自定义:
choose/子目录,拨号图标还有choose/dialer_前缀。
读侧在每个 App 自己的进程。所以“安装过且图标被桌面渲染过”就会留痕,不需要用户打开过这个应用,这比 splash 必须冷启动过更强的 oracle。
社区生态也都在往这个目录写:DarkIcon-Auto、ArtPlus、ColorOS-MonetIcon-Completion-Plus。这些换图标模块的存在本身就是该目录生命力的证据。
命名规则逐文件:
文件 | 用途 | 强度 |
monochrome*.png | 单色 / 莫奈取色图标,桌面日志原文 “monochrome build-in not found, try load from data ux resource” | 已验证 |
recfg / recbg | 经典浅色风格的前景层 / 背景层,最近任务卡片与桌面共用 | 已验证 |
rec_night* | 暗色模式图标,只需前景层 | 已验证 |
game_app.png | 游戏类应用图标资源,桌面有 GAME_APP_FILE_CHECK、隐藏游戏相关串 | 推断 |
nsd.png | 与 mat、peb 并列的一种图标风格,方法名 getMatOrPebOrNsdDrawable,全称未查实 | 未定 |
_1x2/_2x1/_2x2 | ColorOS 16 桌面“大图标”多尺寸变体 | 已验证 |
4. 版本演进:命名字典会漂移
这是实现里最大的工程风险。
ColorOS | splash 侧形态 | 证据 |
7 (A10) | /data/system_ce/{u}/appsnapshots/{pkg}.jpg,JPEG q95 | 源码已验证 |
12 (A12) | 同路径 appsnapshots,只有 .png,没有 splash / webp | dump 字符串 |
13/14 | 公开 dump 缺失,未验证 | — |
15 (A15) | /data/system/splash/{pkg}_{u}_{d}.webp,格式串 %s_%s_%s,没有 MAIN 后缀 | dump 字符串 |
16 (A16) | 加 _MAIN / _VIEW 后缀,与 SurfacePreview / QuickStart 同期引入 | dump 字符串 |
推论:
- 三档 activityType 里,空后缀那一档覆盖 CO15 及更早;
_MAIN/_VIEW只对 CO16 有意义;
- CO12 及更早要探测
appsnapshots路径,目前很多实现完全没覆盖;
_MAIN/_VIEW的语义尚未定案。两种候选:按启动 Intent 区分(ACTION_MAIN 桌面启动 / ACTION_VIEW 深链),或 QuickStart 主 / 二级页面。要定案得 jadx 看StartingSurfacePreviewController.getShortFileNameForSurfacePreview;
- displayId 来自
DisplayContent.getDisplayId(),主屏恒 0,折叠内外屏共用 0,非 0 只出现在流转 / 车机 / 副屏。实际文件名里绝大多数是_0,扫描上限可以从 0–99 砍到 0–4,先 0 后顺序。
5. 生命周期与命中语义
splash
- 卸载有清理钩子:
onPackageRemovedAndCleanup/deleteSnapshotForPackage;
- 深浅色切换、语言、布局方向变化会
clearCache(userId)整用户清空;
- CO16 新增按过期时间淘汰:
CAPTURE_FILE_EXPIRED_TIME;
- 重启保留,DE 存储,开机即可用,这正是它服务开机后首次冷启动的设计目的。
命中语义约等于:“近期冷启动过且在云控白名单内”。
uxicons
- 卸载大概率清理:桌面
IconDisusedEventHandler+ installd 被授予uxicons_data_file的unlink/rmdir/relabel;
- 无 LRU,重启保留;
- 生命周期 ≥ PM 可见性有实证:XDA 的 Netflix 案例里,包已经不在
pm list packages,/data/oplus/uxicons/com.netflix.mediaclient还在盘上。被冻结 / 对 PM 隐藏的应用照样留痕。
命中语义约等于:“装过或仍在装,图标被渲染过”。
一个值得注意的清理细节:整删
/data/oplus/uxicons 后,桌面(platform_app)对 /data/oplus(0775)没有写权限,在线期间建不回这个目录,要等重启 init 重建。也就是说 root 侧一条 rm -rf /data/oplus/uxicons 能让这条 oracle 物理失效到下次重启,代价只是主题图标降级。PICP-ColorOS 甚至已经在用 chmod 555 阻止系统自动下载 Art+ 图标。7. 结论
uxicons 和 splash 检测的共同点,是探测系统进程和桌面进程写入 data 分区的缓存文件。这些文件不在目标 App 的进程视图里,隐藏栈不会碰;其中 uxicons 因为 ART+ 图标加载机制,权限天然对
appdomain 敞开,甚至可以直接枚举目录。参考资料
- CO15 oplus_ossi_dump:
DroidDumps/oplus_ossi_dump
- CO16 oneplus dump:
DqrKnzx/oneplus_op595dl1_dump
- ColorOS 7 反编译框架源码:
dstmath/OppoFramework
- uxicons file_contexts:
RandomPush/oplus_ossi_dump
- realme dump 的
/data/oppo→/data/oplus迁移配置
- XDA Netflix 残留案例
- DarkIcon-Auto、ArtPlus、ColorOS-MonetIcon-Completion-Plus
- 一加社区 uxicons 777 教程
