Skip to content

[方案/征求合并] macOS Apple Silicon 通用数据库密钥提取:受控临时重签、登录时捕获与自动恢复 #101

Description

@coderscsy

macOS Apple Silicon 数据库密钥提取集成提案

上游背景

这是对 #88(macOS 无法稳定获取密钥)的已验证方案提案,也吸收了 #87 暴露的“运行时改动已签名 App Bundle 会破坏后续启动校验”问题。

现有正式腾讯签名微信在部分 Mac 上无法被捕获组件附加,表现为 PROCESS_ACCESS_DENIED。本地派生版本已经完成一次真实端到端验证;希望先征求维护者对集成边界和安全模型的意见,再整理最小 PR。

目标

为 WeChatDataAnalysis 提供一个不依赖旧密钥缓存、可验证、失败可恢复的 macOS Apple Silicon 密钥提取流程。工具只处理当前用户有权访问的本机微信数据,不联网、不上传密钥或聊天内容。

本提案解决的是正式腾讯签名微信进程无法被现有捕获组件稳定附加的问题。它不是绕过账号登录:用户必须亲自在手机端确认登录,并在受控流程中重新登录同一账号。

已验证范围

  • Apple Silicon Mac;
  • 微信 4.x 沙盒数据目录;
  • 微信 4.1.12 的一次端到端验证;
  • 使用活动数据库首页完成 WCDB 密钥密码学校验;
  • 成功、取消、捕获超时和异常路径均恢复腾讯官方签名微信。
  • 定向测试 57 项通过,本地派生分支完整测试 836 项通过;
  • 发布审计确认安装包不包含数据库、日志、偏好、密钥缓存、个人绝对路径或本地证书材料。

Intel Mac、未来微信版本以及多套并行安装仍需单独验收,不能从 Apple Silicon 的结果推断为已支持。

根因

  1. 正式腾讯签名微信受到 macOS 进程保护,直接附加可能返回 PROCESS_ACCESS_DENIED
  2. 微信 4.x 的活动数据库位于 Documents/app_data/xwechat_files;同账号可能残留 Documents/xwechat_files 旧副本。
  3. 如果用旧副本首页的 salt 校验本次登录候选,正确密钥也会被拒绝,最终表现为固定时长超时。
  4. ad-hoc 签名的应用每次重建都会改变指定要求,macOS 的完全磁盘访问授权可能失效。

建议状态机

1. 环境检查

  • 微信路径必须解析为明确的 .app,不接受宽泛目录或通配符;
  • 校验当前微信为腾讯官方签名;
  • 验证 LLDB、Apple Silicon 架构、工作目录可写;
  • 微信 4.x 只选择 app_data/xwechat_files 活动库;权限不足时立即报错,不回退旧副本;
  • 读取目标数据库首页,拒绝明文 SQLite、短文件和不可读文件。

2. 准备和可恢复备份

  • 正常退出微信;
  • 在同一 APFS 卷创建写时复制工作副本或恢复槽;
  • 保存官方版本号、构建号、CDHash 和备份位置;
  • 重签只发生在受控工作副本;
  • 原版和工作副本通过同卷原子换位,避免直接修改最近启动且受保护的 bundle;
  • 所有路径和状态写入当前用户私有目录,权限为 0700/0600

3. 首次登录与断点预检

  • 启动临时签名微信,让用户正常登录并进入聊天主界面;
  • LLDB 短暂附加,解析系统 PBKDF2 断点和按模块 UUID 管理的内部返回断点;
  • 只验证断点位置可执行,随后立即分离;
  • 预检无可用断点时停止,不要求用户退出账号。

4. 重新登录时实时捕获

  • 用户先在未监测状态退出到二维码页;
  • 启动 LLDB 监测后,再由用户扫码并在手机确认登录;
  • 通用路径监测 CCKeyDerivationPBKDF,仅接受符合 WCDB 参数形状的调用;
  • 内部返回断点作为按微信模块 UUID 显式登记的备用路径,未知版本不猜偏移;
  • 先读取并匹配目标数据库 salt,再读取 32 字节候选;
  • 候选必须通过目标数据库首页 HMAC 校验才算成功。

5. 保存和恢复

  • 只保存已经由活动数据库验证的 32 字节密钥;
  • 密钥文件权限为 0600,安装包、日志和 Issue 不包含密钥;
  • 无论成功、取消、超时还是异常,都关闭临时微信并原子恢复官方 bundle;
  • 恢复后再次执行深度代码签名校验,确认 Tencent Developer ID 和 Team ID;
  • 状态文件只在恢复完成后删除,应用重启时优先处理未完成恢复。

诊断要求

超时不能只显示“未获取密钥”。建议记录不含敏感内容的计数:

  • PBKDF2 断点触发次数;
  • 参数形状匹配次数;
  • 目标数据库 salt 命中次数;
  • 内部返回断点触发次数;
  • 候选数据库校验失败次数。

这样可以区分“没有触发重新登录计算”“选错账号或数据库”“断点版本不兼容”和“候选布局变化”。日志不得打印候选密钥、数据库首页或用户路径。

通用化与签名

  • 公共 Release 应由项目现有 Developer ID Application 证书签名并公证;
  • 源码本机构建可以显式使用一张长期固定的本地自签名代码证书;
  • 不能把某个开发者的本地证书、私钥或签名元数据放进仓库或安装包;
  • 默认 ad-hoc 构建仅适合一次性开发测试,升级后可能需要重新授予隐私权限;
  • 固定 bundle identifier 和固定指定要求可让完全磁盘访问权限在同一签名身份升级时延续。

建议的上游集成边界

  1. 将捕获状态机放在 Python 后端的 macOS 密钥服务中;
  2. Electron 仅负责展示步骤、打开系统设置和退出确认,不直接处理密钥;
  3. 复用现有账号检测结果,但在微信 4.x 强制规范化到活动 app_data 数据库;
  4. 密钥写入现有受限 key store,再由现有解密流程消费;
  5. 保留项目现有私有原生运行时作为独立能力,纯 LLDB 流程不应静默下载或执行未知二进制;
  6. 未知微信模块 UUID 时只保留系统 PBKDF2 路径,并给出明确兼容性诊断。

安全边界

  • 仅处理用户本人或已明确授权的数据;
  • 不支持远程附加、后台静默捕获、绕过手机确认或批量账号操作;
  • 不修改微信网络行为,不注入长期驻留代码;
  • 不把重签微信作为日常客户端;
  • 每次开始前验证官方备份,每次结束后验证官方恢复;
  • 不把聊天数据库、媒体、日志、密钥、个人路径或证书私钥提交到 Git。

最小验收清单

  • 活动库和旧库并存时始终选择活动库;
  • 完全磁盘访问缺失时立即失败且不改动微信;
  • 断点预检失败时不要求退出账号;
  • 登录捕获成功后可以解开当前活动数据库;
  • 使用错误账号登录时不会保存候选;
  • 超时、取消、应用崩溃和系统重启后都能恢复官方微信;
  • 恢复后的微信通过 codesign --verify --deep --strict
  • 发布审计确认包内没有数据库、日志、偏好、密钥缓存、个人绝对路径和本地证书材料;
  • Apple Silicon 的单元测试、打包校验和一次真实端到端验证全部通过。

如果维护者认可这个状态机和临时重签边界,可以继续按上游当前目录结构拆成一个最小、可审查的 PR,并把微信版本/模块 UUID 兼容表与回归测试分开维护。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions