fuqiuluo’s blog

记录美好生活

心情随笔

ColorOS splash 缓存 + OPLUS uxicons 残留探测

#安全#Linux#逆向#ColorOS
type
Post
status
Published
date
Oct 27, 2026
slug
summary
tags
安全
Linux
逆向
ColorOS
category
心情随笔
icon
password

1. 摘要

本文分析两条检测链路:
  1. OPLUS uxicons 残留:/data/oplus/uxicons/{pkg}/...,权限和 SELinux 策略都对 appdomain 敞开,是主信号。
  1. 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 原文里有:
位置在 init.oplus.rootdir.rc 的 on post-fs-data 段,注释署名 [email protected], 2020-04-24, Add for uxicons。
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 教程
Loading...