☰
TEESimulator 进阶使用指南:多用户与工作资料下的跨应用目标(Scope 与 uid 匹配机制详解)
2026/10/3 16:52:41 网站建设 项目流程

TEESimulator 进阶使用指南:多用户与工作资料下的跨应用目标(Scope 与 uid 匹配机制详解)

【免费下载链接】TEESimulatorSoftware simulation for Android hardware-backed key pairs with key attestation项目地址: https://gitcode.com/gh_mirrors/te/TEESimulator

TEESimulator 是一款面向 Android 的硬件级密钥认证(Key Attestation)软件模拟模块,它能在不修改设备 TEE 的前提下,为指定的目标应用生成与真实 TEE 结构完全一致的认证证书。本文面向进阶用户,深入讲解它在**多用户(Multi-User)与工作资料(Work Profile)**场景下的进阶玩法,并完整拆解 Scope 的 uid 匹配机制——为什么同一个应用在不同用户下是"两个不同的调用者",以及如何让 TEESimulator 精准命中它们。

为什么多用户场景是进阶玩家必须掌握的一课

在 TEESimulator 中,一个 Profile 通过apps[]数组指定目标应用。但很多人遇到过一个"灵异现象":明明主用户的应用被模拟成功了,工作资料里的同款应用却依然走真实硬件。

答案藏在 Android 的 uid 规则里:

调用者uid 构成示例
主用户(user 0)的某应用appId10123
user 10(工作资料)的同款应用10 × 100000 + appId1010123
user 10 的 system_server10 × 100000 + 10001001000

也就是说:同一个包名在不同 Android 用户下是不同的进程、不同的 uid、对 keystore 而言是两个完全独立的调用者。这个"每用户 100000 的步长"(PER_USER_RANGE)是理解 Scope 机制的钥匙,源码中的定义位于 Packages.kt:

  • userIdOf(uid):从 uid 反推所属用户,uid / 100000
  • uidForPackage(pkg, userId):解析"某用户在某用户下的应用 uid",主用户走公开 PackageManager,工作资料/次级用户则通过IPackageManager的按用户重载跨用户查询(daemon 以 root 运行,系统会豁免跨用户权限检查)

💡一句话结论:写com.android.vending只会命中主用户的 Play Store;工作资料那份克隆体需要单独指名。

Scope 的三种条目写法:包名、pkg@用户、uid 令牌

TEESimulator 把apps[]的解析集中在 Scope.kt 中,每个条目只可能是下面四种形态之一:

  1. 普通包名——com.android.vending,含义是"主用户(user 0)下安装的这个应用";
  2. pkg@N用户令牌——com.android.vending@10,含义是"user 10 里的同一应用",这是覆盖工作资料或次级用户的标准写法;
  3. uid:N原始令牌(进阶)——uid:1010123,直接瞄准某个调用者 uid,适用于共享 uid 应用、或包名未知的场景;
  4. 非法条目—— 无法解析,会被安全丢弃并在日志中告警。

对应的校验正则定义在 schema.js:

APP_ENTRY_RE = 包名 | 包名@数字 | uid:数字

一个值得注意的设计:即使包名指向的应用尚未安装,普通包名也会原样保留并下发(后续安装后仍能按名字命中);而 uid 只有在真实解析成功时才会下发,永远不会是 -1。

两级匹配机制:先包名、后 uid 的路由决策

配置最终通过本地 socket 推送到注入 keystore daemon 的原生拦截库。Android 12+ 的路由核心在 keymint_router.cpp 的ProfileForRequest中,它按两级优先级决定一个请求走模拟还是转发真实硬件:

第一级:认证应用 ID(包名匹配)

应用发起认证请求时,KeyMint 参数里带有ATTESTATION_APPLICATION_ID,其中嵌入了包名。路由器用它在各 Profile 的packages[]中查找。

关键细节:认证应用 ID只有包名、没有用户。所以路由器会用调用者 uid 除以 100000 得到"调用者所属用户",再与条目的用户号比对——这正是pkg@N语法的底层价值:

主用户的 Play Store 与工作资料的 Play Store 包名完全相同,唯能区分的只有 uid 所属用户。若不做这层校验,工作资料的克隆体会"误命中"为主用户配置的条目。

第二级:调用者 uid(兜底匹配)

创建认证密钥时应用往往不带认证 ID(无 challenge、无应用 ID),此时第一级落空,路由器退而比较 Binder 调用者 uid 与各 Profile 的uids[]。uids[]是有效 uid 集合:已安装包名解析出的 uid +uid:N令牌 + 自动包含扩展,三者合并去重。

📌 两条数组(packages[]与uids[])彼此独立、长度不必相同——这是 Resolver.kt 在推送配置时明确的契约。

实战:给工作资料配置独立 Keybox

工作资料是 TEESimulator 多用户能力最典型的应用场景:企业设备中,你常常希望主用户应用与工作资料克隆体使用不同的认证策略(不同 keybox、不同补丁级别),甚至让工作资料那份完全走真实硬件。

步骤如下:

  1. 确认用户号:在 WebUI 的 Scope 选择器中,设备用户会列出(如0 Owner、10 Work profile),次级/工作用户由IUserManager.getUsers枚举,服务不可用时回退读取/data/system/users目录;
  2. 指名目标用户:在 Profile 的 apps 中加入com.android.vending@10(@10即工作资料);
  3. 分派不同 Profile:为工作资料克隆体建立独立 Profile,指向另一个 keybox 文件。由于"每个包/uid 只能归属一个 Profile"是硬性校验规则,主用户与工作资料各占一条,互不冲突;
  4. 保存即生效:daemon 监视配置变化并即时重推,无需重启。

日志中的贴心提示:当某条目只指名了主用户、但同一应用还安装在其他用户时,Scope 会主动打印提示——

'com.android.vending' is also installed for user 10 ('Work profile') — add 'com.android.vending@10' to target that copy too

避免"没生效"被误认为 bug。

自动包含(autoIncludeNewApps):为什么它不吞掉工作资料

开启autoIncludeNewApps后,Profile 会自动收编"基线之后新安装"的应用 uid。多用户场景有两个安全设计:

  • 基线按裸包名记录:known_packages.json在首次运行时冻结当时的全部包名。由于工作资料克隆的包名与主用户相同,它在基线里被视为"既有应用",不会被自动收编——这是刻意的安全方向,防止 keybox 被应用到无人要求的地方;
  • 空基线拒绝工作:基线文件缺失、为空或损坏时,自动包含整体跳过并告警。若把空基线当真,"所有包都不在基线里"会成立,整个设备都会被自动包含——恰好是反效果。文件写入采用"临时文件 + 原子重命名",杜绝半截写入。

此外 v1 基线(多用户支持之前生成,只含 user 0)会在下次运行时一次性补全:仅并入主用户没有的包(即纯粹存活于工作资料/次级用户的应用),user 0 部分保持原冻结时刻不变,随后升级为 v2 格式。相关逻辑全部收敛在 Scope.kt 的baselineKnownPackages。

用 WebUI Scope 选择器管理多用户目标

手改config.json容易出错,WebUI 的 Scope 选择器(scope-view.js)把多用户目标管理做成了可视化列表:

  • 一应用多行:同一应用装在多个用户下时显示为多行——工作资料克隆体有独立 uid、独立调用者身份,因此单独一行、单独勾选。点击某行,写入的是该行所属用户的条目(主用户为com.foo,user 10 为com.foo@10);
  • 筛选与排序:按"最近请求过密钥的应用"(Recent,默认)、用户应用、系统应用、已选项筛选,支持按使用频次、最近使用、名称、安装时间排序,还能按用户过滤;
  • 占用提示:已被其他 Profile 显式占用的条目会置灰并标注归属,避免配置冲突;自动包含的 uid 单独标识,且"手动固定"与"自动包含"互斥——一旦固定,下次解析即从自动集合中移除;
  • 低 uid 警告:app id(uid % 100000)低于10000的条目(system/shell 级)会被标警——那是系统调用者而非普通应用,误配没有意义。

💡uid:N令牌在 UI 中仅支持手工增删,普通点选永远写入包名条目——这是有意保留的"高级操作"边界。

常见问题排查清单 🛠️

症状原因处理
工作资料应用未被模拟条目只写了裸包名,仅命中主用户追加pkg@用户号条目
日志出现NOT INSTALLED for user N (dropped)该用户下确实没装这个包核对工作资料是否已安装克隆体
日志提示also installed for user 10 — add ...@10主用户条目不覆盖其他用户克隆体按提示补条目
is not a valid package name, pkg@user or uid:N token条目含非法字符(如包名内多余的@)检查拼写,@后必须紧跟纯数字
自动包含未生效且提示no package baseline yet基线尚未成功冻结(如首次枚举失败)等待下一次 resolve 自动重试,勿手动写空文件
目标 uid 告警"privileged uid"误把系统/shell uid 配进 apps移除该条目,普通应用 app id ≥ 10000

所有解析过程都有完整日志(Scope[profileId]: '条目' -> uid N (user M)格式),排查时先看日志再改配置。

小结

理解 Scope 的 uid 匹配机制只需记住三件事:

  1. uid = 用户号 × 100000 + appId,跨用户克隆体是不同的调用者;
  2. 匹配两级进行:认证请求先按"包名 + 调用者用户"匹配,无应用 ID 的请求再按有效 uid 兜底;
  3. pkg@N与uid:N是精确制导工具,WebUI Scope 选择器则是管理它们的安全入口。

掌握这些后,无论是企业设备的工作资料隔离策略,还是多用户环境下的差异化认证配置,TEESimulator 都能精确到"哪一份应用副本"的粒度为你服务。更多配置项(keybox、补丁级别、设备身份)可参考默认配置 config.default.json 与项目根目录的 README.md。

【免费下载链接】TEESimulatorSoftware simulation for Android hardware-backed key pairs with key attestation项目地址: https://gitcode.com/gh_mirrors/te/TEESimulator

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询