From e880623d4f6f4ee96947d0ce54188814eedf6a91 Mon Sep 17 00:00:00 2001 From: yibo Date: Wed, 24 Jun 2026 18:21:17 +0800 Subject: [PATCH] docs(wechat_plain): Mac 微信 4.x 数据库解密静态调研记录 --- wechat_plain/scripts/db-decrypt/mac-wechat-4x-db-decrypt-research.md | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+), 0 deletions(-) create mode 100644 wechat_plain/scripts/db-decrypt/mac-wechat-4x-db-decrypt-research.md diff --git a/wechat_plain/scripts/db-decrypt/mac-wechat-4x-db-decrypt-research.md b/wechat_plain/scripts/db-decrypt/mac-wechat-4x-db-decrypt-research.md new file mode 100644 index 0000000..3e8543b --- /dev/null +++ b/wechat_plain/scripts/db-decrypt/mac-wechat-4x-db-decrypt-research.md @@ -0,0 +1,121 @@ +# Mac 微信 4.x 聊天记录数据库解密 — 研究记录(未执行,纯调研) + +> 状态:**只做了静态调研,没有对系统或微信做任何实际操作**(没关 SIP,没装任何解密工具,没碰任何 Keychain/进程)。本机仍是默认安全配置。 +> 时间:2026-06-24。触发原因:Personal CRM 项目(`lifelog-recorder`)想评估能不能把 Mac 端微信客户端的聊天记录也接进来作为数据源。 + +## 1. 本机环境 + +- 微信 Mac 版本:**4.1.5** (build 31960),`/Applications/WeChat.app` +- 容器路径:`~/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/` +- 本机有两个账号目录: + - `wxid_51ap3m6p9xs722_8ead` — **当前活跃账号**(`message_0.db` 21MB,今天还在写) + - `yibooo_ac07` — 旧/备用账号(`message_0.db` 1GB,最后写入 4-08,应该是迁移后弃用了) + +这是微信 2024 年后重做的统一客户端(俗称"微信 4.0"),目录结构跟老版(单文件 `EnMicroMsg.db`,本项目 Android 侧 `wechat_plain/scripts/platform-tools/notes/EnMicroMsg.db` 记录的那套)完全不是一回事,**不能直接套用 Android 侧已有的 SQLCipher key 推导经验**(见 `wechat_plain/scripts/db-decrypt/` 下已有的 `wechat_android_*` 系列脚本——那些是 Android 端、走 Frida attach 设备进程,跟这次研究的 macOS 桌面客户端是两套完全独立的密钥体系)。 + +## 2. 目录结构 / 文件清单 + +每个账号目录下 `db_storage/` 关键文件: + +| 文件 | 内容 | +|---|---| +| `message/message_0.db` (+`-wal`/`-shm`) | 聊天正文,本机目前只有 `_0`,没有分片到 `_1` | +| `message/message_fts.db` | 全文索引 | +| `message/media_0.db` | 消息内媒体引用 | +| `message/biz_message_0.db` | 公众号/服务号消息 | +| `message/message_resource.db` | 消息资源 | +| `message/*.db-first.material` / `*-last.material` / `*-incremental.material` | WCDB 内部 checkpoint/合并用的中间文件,**不是明文备份**,本身也是加密格式的一部分 | +| `contact/contact.db` + `contact_fts.db` | 联系人 | +| `session/session.db` | 会话列表 | +| `sns/sns.db` | 朋友圈 | +| `head_image/head_image.db` | 头像 | +| `all_users/login//key_info.db` | 见下文「试错 1」 | + +文件头确认:`message_0.db` 开头不是 `SQLite format 3` magic,是随机字节——**确认整库是密文**,不是裸 SQLite。 + +## 3. 试错记录 + +### 试错 1:`key_info.db` 误以为是数据库密钥存放处(证伪) + +`all_users/login//key_info.db` 是**未加密**的标准 SQLite(文件头是正常的 `SQLite format 3`),表结构: + +```sql +CREATE TABLE LoginKeyInfoTable(user_name_md5 TEXT, key_md5 TEXT, key_info_md5 TEXT, key_info_data BLOB); +``` + +`key_info_data` 是个 ~179 字节的二进制 blob,一开始怀疑这就是 SQLCipher 密钥的某种包装形式。 + +**证伪方法**:对 `WeChat` 主二进制 (`/Applications/WeChat.app/Contents/MacOS/WeChat`,Mach-O universal x86_64+arm64) 跑 `strings`,过滤 cipher/key 相关符号,看到这组字符串聚在一起: + +``` +auth_key auth_id:key_info authkey GenEcdhKeyPair dhKeyAgreement +micromsg.ECDHKey mmcrypto.SecECDHKey Key_Info key_info_data key_info_md5 key_info.db +``` + +`GenEcdhKeyPair` / `dhKeyAgreement` / `ECDHKey` 这几个符号说明 `key_info.db` 这套东西是**登录鉴权用的 ECDH 密钥协商**(网络协议层的 authkey,用来跟微信服务器做登录握手),跟本地 SQLCipher 数据库加密**没有关系**。 + +**结论**:这条路是死的,不要浪费时间在 `key_info.db` 上。 + +### 试错 2:找本机有没有现成「聊天记录备份」文件可以绕开内存提取(证伪) + +设想:如果用户之前用过微信的「聊天记录迁移与备份」功能,本地可能留下一份独立的、时间点固定的备份数据库,理论上可以脱离"必须从正在跑的进程内存里挖密钥"这条路。 + +**搜索范围**: +- `xwechat_files/` 整个目录树(`find -maxdepth 6 -iname "*.db"`) +- 专门找 `*backup*` / `*migrat*` 命名的目录 +- 老版微信遗留路径 `Data/Library/Application Support/com.tencent.xinWeChat`(3.x 时代单文件库可能残留的地方) +- 全盘 `mdfind`(Spotlight 索引)搜 `EnMicroMsg` / `WCDB_Contact` / `wechat` 相关文件名,范围含 `~/Downloads`、`~/Desktop` + +**发现**: +- `xwechat_files/Backup//` 目录确实存在,但内容只有一个 `roam_device_info.dat`(设备漫游信息),**没有任何聊天记录数据库**。 +- `/msg/migrate/` 和 `/business/migrate/` 目录存在但本次没有展开看内容(标记为后续如果要继续深挖可以查的点,但目录名暗示是迁移过程的临时态,不太可能是稳定可用的全量备份)。 +- 全盘 `mdfind` 命中的全是项目代码里的字符串(本项目 Android 侧的 `EnMicroMsg.db` 笔记、各种带 "wechat" 文件名的截图/PPT),跟 Mac 微信客户端的数据库备份无关。 + +**结论**:本机**没有可以绕开内存提取的现成备份文件**。唯一的数据源就是运行中、被 SQLCipher4 加密的 `db_storage/message/message_0.db`(含 `-wal`)。如果要拿到明文,没有捷径,必须走"从运行中的微信进程内存里挖出实时密钥"这条路。 + +## 4. 加密方案技术结论(已通过公开资料 + 二进制字符串交叉确认) + +- 算法:**SQLCipher 4** +- 密钥格式:`x'<64位hex key><32位hex salt>'`,即 32 字节 AES key + 16 字节 salt,拼成 99 字符 hex 字符串传给 `PRAGMA key` +- 配套 PRAGMA:`PRAGMA cipher_compatibility = 4; PRAGMA cipher_page_size = 4096;` +- 密钥生命周期:**只在 WeChat 进程运行、且该账号数据库已被 WCDB 打开期间,短暂驻留在堆内存里**,新版本已经不会长期驻留(社区工具的 issue 里提到从某个版本开始"key 不再长期保留在内存数据中",需要在数据库刚打开的那个时间点抓)。 +- 提取手法(公开资料描述的方法,本次**没有实际操作**):用 `lldb` attach 到正在跑的 WeChat 进程,在它调用 `malloc(0x43)`(0x43=67 字节,密钥初始化分配的大小)前的 `mov x0/w0, #0x43` 指令处打断点,断点触发后用 `memory read` 把寄存器指向的内存读出来,就是上面那个 80 字节格式的密钥。 +- macOS 前置条件:**必须先 `csrutil disable`(关闭 SIP)**。正版 WeChat.app 是苹果公证签名、开了 Hardened Runtime 且没有 `get-task-allow` entitlement 的二进制,默认情况下任何第三方调试器都无法对它做 `task_for_pid`/attach,关 SIP 是公开资料里所有方法的共同前提。 + +## 5. 开源工具调研现状 + +| 项目 | 状态 | 备注 | +|---|---|---| +| [sjzar/chatlog](https://github.com/sjzar/chatlog) | **已完全删库** | 维护最好、用户最多的同类工具,作者收到微信官方函后以"合规风险"为由删除全部代码与提交历史,仓库只剩一份移除说明。**重要信号:这不是小项目,说明这类工具被腾讯主动追究过。** | +| [Thearas/wechat-db-decrypt-macos](https://github.com/Thearas/wechat-db-decrypt-macos) | 已 **archive**(上月,2026-05) | 文档明确写"只在微信 4.1.2.241 测试过",本机版本是 **4.1.5**,不保证特征码/偏移还对得上;archive 状态本身也说明作者放弃跟进新版本。 | +| [ylytdeng/wechat-decrypt](https://github.com/ylytdeng/wechat-decrypt) | 仓库仍在线 | 未实际验证,标称支持从内存提取密钥 + 解密 SQLCipher4 + 实时消息监控 | +| [cocohahaha/wechat-decrypt-macos](https://github.com/cocohahaha/wechat-decrypt-macos) | 仓库仍在线 | 标称用 Mach VM API 做内存提取 | +| [L1en2407/wechat-decrypt](https://github.com/L1en2407/wechat-decrypt) | 仓库仍在线 | 标称跨 Windows/macOS/Linux | +| [ydotdog/wechat-export-macos](https://github.com/ydotdog/wechat-export-macos) | 仓库仍在线 | 一键解密导出工具 | +| [nalzok/wechat-decipher-macos](https://github.com/nalzok/wechat-decipher-macos) | 仓库仍在线但很老 | DTrace 脚本方案,针对的是更老的单文件 `message.db` 时代客户端,跟本次目标(4.x `xwechat_files` 结构)不是同一套,方法论可能已经过时 | + +## 6. 风险评估 + +1. **法律/合规信号是真实且新鲜的**:chatlog 案例证明腾讯会主动对这类工具发函施压,即便用途是解密用户自己账号的本机数据,仍然落在微信 ToS"禁止反向工程"条款射程内,有现成的执法先例(不是假设性风险)。 +2. **系统级安全开关**:关闭 SIP 会削弱整机代码完整性保护,不只是对 WeChat 一个 App 生效,是机器级别的安全降级,且需要重启进恢复模式操作。 +3. **方案不稳定**:特征码/内存偏移跟具体版本号绑定,微信几乎每次更新都可能改变,本机当前版本(4.1.5/31960)没有任何一个已知工具明确验证过适配,等于每次都要重新逆向,不是一次性能跑通的方案。 + +## 7. 结论 / 暂定路线 + +**本次研究到此为止,没有进入实际解密阶段**。原因是上面三条风险叠加(法律先例 + 系统级改动 + 工程不稳定)已经足够大,在没有更强烈需求之前不值得动手。 + +低风险备选方案(如果只是要把 Mac 端聊天记录接进 Personal CRM,不追求结构化全量):微信客户端自带「聊天记录迁移与备份」「导出聊天记录」功能(设置内),走官方支持路径导出,不涉及逆向,但只能按对话手动导出 txt/html,不是可批量查询的结构化数据库。 + +如果以后要重新评估这件事,建议先确认: +- 微信 Mac 版本是否升到了某个已知被验证过的版本(关注上表里那些仍在维护的仓库的 issue 区,看有没有人报过跟当前版本匹配的成功案例); +- 用户对关闭 SIP + 潜在 ToS 风险的接受程度有没有变化。 + +## 参考链接 + +- [ylytdeng/wechat-decrypt](https://github.com/ylytdeng/wechat-decrypt) +- [L1en2407/wechat-decrypt](https://github.com/L1en2407/wechat-decrypt) +- [cocohahaha/wechat-decrypt-macos](https://github.com/cocohahaha/wechat-decrypt-macos) +- [Thearas/wechat-db-decrypt-macos](https://github.com/Thearas/wechat-db-decrypt-macos)(含《微信数据库解密.md》,内存特征码扫描法的具体描述来源) +- [nalzok/wechat-decipher-macos](https://github.com/nalzok/wechat-decipher-macos) +- [ydotdog/wechat-export-macos](https://github.com/ydotdog/wechat-export-macos) +- [sjzar/chatlog](https://github.com/sjzar/chatlog)(**已删库**,仅剩移除声明,记录其曾经存在过且被官方函下架这件事本身) -- libgit2 0.21.4