TEESimulator注入技术深度解析:ptrace远程加载从SCM_RIGHTS传fd到信号返回的完整过程
TEESimulator注入技术深度解析ptrace远程加载从SCM_RIGHTS传fd到信号返回的完整过程【免费下载链接】TEESimulatorSoftware simulation for Android hardware-backed key pairs with key attestation项目地址: https://gitcode.com/gh_mirrors/te/TEESimulatorTEESimulator 是一款针对 Android 硬件级密钥认证Key Attestation的软件模拟器它通过一个基于 ptrace 的注入工具inject把拦截库远程加载进系统的 keystore 守护进程从而在进程内部接管 KeyMint 请求。本文面向想搞懂 Android 进程注入原理的读者完整拆解这条链路从PTRACE_ATTACH附加进程、用SCM_RIGHTS跨进程传递文件描述符fd到利用受控返回地址触发信号、把远程调用的结果接回手里。一、为什么 TEESimulator 必须做 ptrace 注入TEESimulator 的拦截逻辑必须运行在 keystore 守护进程Android 12 的keystore210/11 的keystore自己的地址空间里才能挂钩它的 Binder 调用。但这类系统服务有两个护身符让常规手段全部失效无法重编译它是系统预置二进制你改不了它的代码。受限的链接器命名空间动态链接器会拒绝dlopen任何/data路径下的库——命名空间允许的搜索路径里根本不含/data检查发生在打开文件之前文件权限再大也没用。所以 TEESimulator 选择最原始的路子用 injector/main.cpp 中的inject工具ptrace附加到正在运行的守护进程替它调用dlopen加载我们的.so再调用库导出的entry()完成挂钩最后脱离现场——守护进程照常运行仿佛什么都没发生。二、注入前的三步准备附加、备份寄存器、让出红区整个注入由 injector/main.cpp 中的inject_library编排开头用 RAII 对象把顺序依赖写成了真正的控制流PTRACE_ATTACH附加目标进程收到SIGSTOP停下注入器用waitpid确认它确实停下了injector/utils.cpp 的wait_for_trace还会处理EINTR重试。备份全部寄存器get_regs拍一张 CPU 寄存器的快照存入backup_regs由RegisterRestorer负责在作用域退出时原样写回——目标进程会在被中断的那条指令上精确续跑。x86_64 额外下探 128 字节跳过被中断函数可能仍在使用的红区red zone避免往栈上写数据时踩坏现场。随后lsplt::MapInfo::Scan解析/proc/pid/maps得到目标进程中libc.so等模块的基址。所有远程函数地址都不直接写死而是用 injector/utils.cpp 的find_func_addr解决在本地dlopen同一个libc.so拿到符号偏移再加到目标进程中的模块基址上——ASLR 随机化的是加载基址不随机化库内部布局所以偏移量在两个进程里完全一致。三、SCM_RIGHTS 传 fd为什么递文件句柄是整个方案的灵魂既然不能把库路径递给keystore2那就换个思路不递路径递一个已经打开的文件描述符。Android 提供了android_dlopen_extANDROID_DLEXT_USE_LIBRARY_FD组合——给链接器一个 fd它就直接从 fd 加载 ELF彻底绕开路径与命名空间检查。坑在于fd 必须有效于目标进程的文件表。这正是SCM_RIGHTS的用武之地它是 Linux 内核原生的 fd 传递机制通过 Unix 域套接字的控制消息cmsg把发送方打开的文件在内核里复制一份到接收方的 fd 表中。injector/main.cpp 中transfer_fd_to_remote的完整舞蹈如下步骤动作关键点①远程调用socket(AF_UNIX, SOCK_DGRAM)套接字由目标进程自己创建活在 keystore 自己的 SELinux 域里传输才合法②生成 16 字符随机 magicbind 到抽象地址抽象 socket 没有文件系统节点不存在目录被 SELinux 拒绝穿越的问题③push_memory把cmsghdr缓冲区和msghdr压到目标栈上栈空间由REG_SP下移腾出16 字节对齐④remote_pre_call发起recvmsg(fd, …, MSG_WAITALL)目标进程阻塞在 recvmsg 内部等数据报到达⑤注入器本地sendmsg附带库文件的 fdSCM_RIGHTS内核在目标进程 fd 表中安装副本⑥remote_post_call收尾read_proc读回控制缓冲区解析 cmsg得到目标进程中那个 fd 的编号最后remote_dlopen拿这个编号配上ANDROID_DLEXT_USE_LIBRARY_FD远程调用android_dlopen_ext完成加载。用完的 fd 由RemoteLibraryHandle析构时远程调用close清理防止在守护进程里泄漏。四、信号返回用一次受控崩溃换回函数结果远程调用remote_callinjector/utils.cpp是整篇文章最值得细品的部分它是所有远程动作的原语在别的进程里调用任意函数并取回返回值。做法是改写目标寄存器参数写入 ABI 约定的参数寄存器x86_64 的rdi/rsi/…arm64 的x0–x7超出部分压栈指令指针REG_IP指向目标函数然后PTRACE_CONT放它跑。最关键的一步是设置一个我们控制的返回地址find_module_return_addr扫描目标 maps返回libc.so中一段可读但不可执行页面的起始地址。x86_64 把它压栈模拟callarm64 则装入链接寄存器x30。当远程函数执行完、跳回这个地址时CPU 试图从不可执行页取指触发SIGSEGV——故障地址恰好等于我们设置的返回地址。这个信号不是错误而是约定的完成信号waitpid因之返回remote_post_call校验REG_IP 期望返回地址任何别的停点都说明函数在真实位置崩了此时取PTRACE_GETSIGINFO记录崩溃细节并放弃最后从返回寄存器REG_RETrax/x0里直接读出函数结果。一句话总结这个技巧页面必须存在但跑不了因为故障才是信号而不是事故。remote_pre_call/remote_post_call拆成两半的用武之地正是上文第④步——让目标停在recvmsg内部注入器从外部完成sendmsg再回来收尾。五、Staging 兜底与 entry() 契约如果 fd 传递失败比如 seccomp 过滤了recvmsginjector/main.cpp 会走inject_via_staging兜底把库拷到/data/local/tmp/lib随机8位.so、chmod 0644、远程调用普通dlopen随后ScopedFileDeleter立即unlink文件——inode 因目标已映射而继续存活文件却从磁盘上消失。注意它只在命名空间宽松的场景有效Android 10/11 的keystore可以keystore2不行后者只能靠 fd 传递。加载成功后remote_find_entry在目标里dlsym出entry符号并远程调用参数就是dlopen句柄。两个值得记住的细节从不dlclose库常驻目标进程钩子才持续有效。注入成功≠钩子生效remote_call_entry只要调用完成就返回 true。所以守护进程会另行验证——等拦截库通过控制 socket/data/misc/keystore/.teesim-ctl藏在 keystore 自己的 0700 数据目录里报到见 Const.kt 与 module/sepolicy.rule 中对应 SELinux 授权长时间不到报就打日志告警提示查avc: denied。六、控制面守护进程如何驱动注入循环Kotlin 侧的 Injector.kt 把一切串起来启动后开线程轮询/proc找 keystore 进程名对应的 pid等 Binder 服务注册完毕避免注入半初始化的进程然后执行inject pid lib.so entry。keystore 守护进程会频繁重启每次重启都会丢掉我们的库所以循环监听 pid 变化并重新注入连续失败 3 次后把退避从 2 秒拉长到 10 秒避免死磕一个卡死的服务。SELinux 层面module/sepolicy.rule 授予crash_dump域对 keystore 的process *权限即 ptrace 附加并允许 keystore 读取/data/adbadb_data_file下的拦截库文件——enforcing 策略的设备上这两条缺一不可。七、关键文件索引路径作用injector/main.cpp注入总编排transfer_fd_to_remote、remote_dlopen、inject_via_staging与 RAII 守卫injector/utils.cppptrace 原语寄存器读写、process_vm_readv内存搬运、remote_call三件套injector/include/utils.hpp各架构寄存器宏REG_SP/REG_IP/REG_RET与 API 声明injector/README.md注入器设计文档fd 传递六步舞、staging 兜底、entry 契约app/src/main/java/org/matrix/teesim/Injector.kt控制面注入循环找 pid、判服务就绪、重注入与确认module/sepolicy.ruleptrace 附加与库文件读取的 SELinux 授权CMakeLists.txtinject目标的构建定义按 ABI 交叉编译八、写在最后TEESimulator 的注入器把操作系统教材里的几块拼图——ptrace寄存器操控、process_vm_readv跨进程内存访问、SCM_RIGHTSfd 传递、不可执行页故障——组装成了一条完整可用的远程dlopen流水线。理解它等于同时理解了 Android 链接器命名空间的限制与绕过方式、以及用故障当信号这一类精巧的系统编程技巧。若想动手复现建议从 injector/README.md 开始再对照 injector/main.cpp 顶部的 ASCII 流程图逐段走读源码。【免费下载链接】TEESimulatorSoftware simulation for Android hardware-backed key pairs with key attestation项目地址: https://gitcode.com/gh_mirrors/te/TEESimulator创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

CodexHost 8个进阶技巧:Diff审查、消息级Fork、Worktree并行与Subagent可视化

CodexHost 8个进阶技巧:Diff审查、消息级Fork、Worktree并行与Subagent可视化

CodexHost 8个进阶技巧:Diff审查、消息级Fork、Worktree并行与Subagent可视化 【免费下载链接】codex-host Run Pi and Claude Code directly in Codex Desktop. 在 Codex Desktop 中直接运行 Pi 和 Claude Code。 项目地址: https://gitcode.com/gh_mirrors/co/c…

2026/10/27 3:52:22 阅读更多 →
揭秘Ornith-1.5-35B-A3B-GGUF的自我改进训练范式:从自我脚手架到端到端强化学习

揭秘Ornith-1.5-35B-A3B-GGUF的自我改进训练范式:从自我脚手架到端到端强化学习

揭秘Ornith-1.5-35B-A3B-GGUF的自我改进训练范式:从自我脚手架到端到端强化学习 【免费下载链接】Ornith-1.5-35B-A3B-GGUF 项目地址: https://ai.gitcode.com/hf_mirrors/ornith-ai/Ornith-1.5-35B-A3B-GGUF Ornith-1.5-35B-A3B-GGUF 是开源推理模型 Ornit…

2026/10/24 18:50:10 阅读更多 →
HY-World 2.0 架构全景解析:4阶段流水线如何把一句话变成可探索3D世界

HY-World 2.0 架构全景解析:4阶段流水线如何把一句话变成可探索3D世界

HY-World 2.0 架构全景解析:4阶段流水线如何把一句话变成可探索3D世界 【免费下载链接】HY-World-2.0 HY-World 2.0: A Multi-Modal World Model for Reconstructing, Generating, and Simulating 3D Worlds 项目地址: https://gitcode.com/gh_mirrors/hy/HY-Worl…

2026/10/25 8:07:14 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/26 12:00:21 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/25 22:36:10 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/26 4:52:12 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/26 12:00:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/26 5:00:37 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/26 3:16:46 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 12:00:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/25 13:21:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 8:34:37 阅读更多 →