TEESimulator安全与反检测设计:无Keybox即惰性、递归防护与检测点消除的完整盘点
【免费下载链接】TEESimulatorSoftware simulation for Android hardware-backed key pairs with key attestation项目地址: https://gitcode.com/gh_mirrors/te/TEESimulator
📱TEESimulator是一个 Android 密钥认证模拟(Key Attestation Simulation)项目:它在真实的 keystore 守护进程内部运行一个软件版 KeyMint,让指定应用拿到由用户自有 Keybox 签发的证书链,而其他所有密钥仍留在真实硬件上。正因它寄生在系统安全进程里,TEESimulator 反检测设计与安全设计比功能本身更值得细读——一旦留痕被识别,后果不是崩溃,而是"被看穿"。本文完整盘点它的三大防线:无Keybox即惰性、递归防护与检测点消除。
为什么模拟器的第一原则是"失败要安全" 🛡️
TEESimulator 注入的是系统级的keystore2(Android 12+)或keystore(10/11)守护进程。这类环境里的任何 bug 都有双重风险:
| 风险 | 普通应用的后果 | 本项目的后果 |
|---|---|---|
| 功能 bug | 应用崩溃,用户重装 | 密钥体系损坏,数据永久丢失 |
| 行为异常 | 无人在意 | 被检测方判定"环境异常" |
所以项目的第一设计哲学写在 README.md 里:没有配置时的模块是惰性的(inert),而不是危险的(hazard)。下面按三层防线逐一拆解。
防线一:无Keybox即惰性——不装钥匙就只是块砖 🧱
这是整套TEESimulator 安全设计中最核心的一条:拦截器加载 ≠ 拦截器工作。
1. Keybox 永远不随模块分发
模块只带默认配置(module/config.default.json),私钥所在的keybox.xml必须由用户自行放入/data/adb/teesim/。没有它,拦截器什么都不做——官方原话:"a misconfigured module is inert rather than a hazard"。
2. 入口即"全转发"状态
注入库的入口函数 keymint/keymint_entry.cpp 只做三件事:启动控制服务器、以未配置状态安装钩子、等待控制守护进程推送配置。在收到有效配置推送之前,所有 Binder 调用原路转发真实硬件,一个字节都不动。
3. 配置有严格的校验门槛
守护进程会验证 Keybox 必须同时包含 RSA 与 ECDSA 密钥、证书链长度 ≥ 2,任何一项不满足都拒绝推送。配置错误不会"半工作",只会整体惰性。
4. 启动竞态窗口也不破坏密钥🚀
存在一个微妙窗口:keystore2 在开机后一秒内就开始用密钥,而守护进程还在收割设备参数。如果此时对"我们创建的密钥"返回硬错误,应用会把别名删掉重建——静默销毁用户所有已加密数据。keymint/keymint_router.cpp 中的WaitForDefaultTa选择阻塞至多 8 秒等待配置,超时后返回HARDWARE_NOT_YET_AVAILABLE("稍后再来")而非"密钥损坏",且用静态标志保证只停一次,避免拖垮 binder 线程池。
💡 一句话:先证明你能正确签名,才允许你碰流量。
防线二:递归防护——转发不能变成死循环 ♻️
拦截器需要把目标应用的请求"截下来",把非目标请求"放过去"。而"放过去"本身又是一次 Binder 调用——会再次穿过同一个钩子。不处理就是无限递归。
TEESimulator 用三层机制保证转发绝对安全:
线程局部转发标志(核心手段)keymint/keymint_hook.cpp 中有一个
thread_local布尔量tls_forwarding。路由器每次调用真实 HAL 前,用 RAII 风格的ForwardGuard把它置位,钩子发现标志为真就立刻直通、不再拦截。选线程局部而非全局,是因为其他线程上无关的 KeyMint 流量仍须被拦截——全局标志会误伤。自有设备黑名单(第二道保险)本地伪装设备
TeesimKeyMintDevice与真实 KeyMint 共享同一个接口描述符,会被"身份检查"误认。项目用独立集合g_our_devices记录"这是我们造的设备",从源头排除。注意它用独立互斥锁:热路径上的查询绝不能被设备构造时的阻塞式 IPC 卡住,且锁顺序严格固定,避免死锁。负缓存与"非我所有"回落
g_local_for_proxy对"不包装"的 proxy 缓存nullptr(如 SOFTWARE 级别),避免每次调用都重新探测;Android 10/11 侧的 keystore/keystore_router.cpp 则用"not mine → 原样重放给真实服务"的回落机制,被拒交易零改动地继续走真实路径。
📖 完整推理过程见 keymint/README.md 的Recursion guard一节。
防线三:检测点消除——把"可被观察到的差异"清零 🕵️
反检测的本质:每个"与真实设备不一致的行为"都是一个检测点。TEESimulator 的设计几乎处处围绕"少留一个差异"展开。
补丁模式:默认少模拟,多转发
module/config.default.json 的默认模式是patch:generateKey直接转发给真实硬件,密钥真正硬件背书、认证内容含真实版本与 tee-enforced 授权;项目只在最后对证书叶子重签名(换 Keybox 根、修正 root of trust,实现于 rust/teesim-km/src/resign.rs)。硬件路径没被模拟,检测面自然最小。仅在硬件不可用时才退化为全量生成模式。
只读系统属性,绝不写入
拦截器需要感知设备的 RKP(远程密钥配置)策略来决定是否拒绝目标应用的 attestation key 查询。keymint/keymint_hook.cpp 中注释写得很直白:"We only ever READ the property — a global write would be an obvious detection point."读策略、改行为,但从不修改系统可见状态。
注入不留痕
injector/main.cpp 的注入流程处处隐藏踪迹:
- fd 传递优先:通过
SCM_RIGHTS+ 抽象 Unix 套接字把库的 fd 送进目标进程再dlopen——抽象地址没有文件系统条目,磁盘上查无此物; - Staging 兜底秒删:fd 传递失败时把库临时拷到
/data/local/tmp,dlopen成功后立即删除文件(内核保留已映射的 inode),"hide tracks"; - 不 dlclose:库常驻且只导出
entry一个符号(keymint/exports.map),其余全部隐藏,既防符号冲突,也缩小被dl_iterate_phdr之类手段枚举到的面。
钩子范围最小化
安装钩子时优先只探测主可执行文件的 PLT,而不是扫描全部.so——避免动态库补丁工具对每个无关库打印 "symbol not found" 警告。日志噪音本身就是检测点,这条优化直接来自"keystore2 的 binder 客户端就链接在主程序里"的事实。
设备身份"采一次、冻死它" 🔒
root of trust(verified-boot 状态、vbmeta 公钥等)被刻意设为不可配置:守护进程启动时用一个一次性硬件密钥收割真实值并冻结(app/src/main/java/org/matrix/teesim/Harvester.kt)。伪造的根信任是签名链里最容易被交叉验证戳穿的矛盾点;而真实根信任 + 真实补丁级别 + 自有 Keybox 链,构成的证书在结构上自洽——这正是项目 README 强调的 "internally consistent by construction"。
如何验证这些设计在工作? ✅
- WebUI(KernelSU/APatch 下可用)可查看收割状态、注入状态与守护进程实时日志;
- 恢复路径:
su -c 'kill $(pidof keystore2)'杀掉守护进程即可得到干净实例——新进程在无注入状态下启动,直到模块重新注入; - 惰性自证:删掉 keybox.xml 后保存配置,所有应用行为应与未装模块时完全一致,这就是"无Keybox即惰性"的直观验收。
总结:三大防线一览
| 防线 | 核心机制 | 防住什么 |
|---|---|---|
| 无Keybox即惰性 | 不随模块分发私钥 + 未配置全转发 + 严格校验 | 配置错误造成的意外行为与数据破坏 |
| 递归防护 | tls_forwarding线程局部标志 + 自有设备黑名单 + 负缓存 | 转发引发的无限递归、并发误伤 |
| 检测点消除 | 补丁模式、只读属性、注入不留痕、冻结真实身份 | 每个"与真机不一致"的可观察差异 |
这套设计的启示在于:安全不是"加一个开关",而是把"错误状态 = 安全状态"写进架构——惰性默认、最小干预、零留痕。对想研究 Android 密钥认证原理与反检测工程实践的开发者来说,keymint/README.md 与 injector/README.md 是两篇密度极高的工程笔记,值得通读。
【免费下载链接】TEESimulatorSoftware simulation for Android hardware-backed key pairs with key attestation项目地址: https://gitcode.com/gh_mirrors/te/TEESimulator
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考