# WeChat Android EnMicroMsg.db 解密读取工具链 ## 文件清单 | 文件 | 用途 | 运行环境 | |------|------|----------| | `wechat_android_key_hunter.js` | Frida 脚本:hook `libWCDB.so` 的 `sqlite3_key` / `sqlite3_key_v2`,截获 SQLCipher 密码 | Android 微信进程 | | `wechat_android_attach.py` | Python 控制脚本:attach 微信、收集 key、提取 DB、自动解密 | Termux / Debian proot / Mac | | `search_server_android.py` | Web 搜索服务器:读取解密后的 `EnMicroMsg.db`,提供会话/联系人/聊天记录搜索 | 任意有 Python 的环境 | ## 工作原理 ``` 微信启动 ↓ 打开第一个加密 DB (PreDownloadCheck.db) ↓ libWCDB.so!sqlite3_key(db, "e03ce81", 7) ← Frida 在这里截获 key ↓ 后续所有 DB (EnMicroMsg.db, WxFileIndex.db, ...) 复用同一 key ↓ adb shell su -c cat 复制 DB 文件到本地 ↓ sqlcipher 解密:PRAGMA key="e03ce81"; PRAGMA cipher_compatibility=1; PRAGMA cipher_page_size=1024; ↓ SQLite 明文库 → search_server_android.py 提供 Web UI ``` ## 关键发现(WeChat 8.0.72 on Android) | 项目 | 值 | |------|-----| | **SQLCipher key** | `e03ce81`(7 字符字符串密码,通过 `sqlite3_key` 传入) | | **cipher_compatibility** | `1` | | **cipher_page_size** | `1024` | | **Key 设置时机** | 打开第一个加密 DB 时调用一次 `sqlite3_key`,后续所有 DB 复用 | | **Java VM 可见性** | `Java.available = false`(微信有反注入,但 native hook 完全正常) | | **Hook 目标 so** | `libWCDB.so`(内含 SQLCipher,`sqlite3_key` 符号可通过 `mod.findExportByName()` 定位) | ## DB 结构(Android 版 vs macOS 版) | | Android `EnMicroMsg.db` | macOS `db_storage/` | |--|------------------------|---------------------| | 文件数 | 单文件 | 多个分库 | | 消息表 | `message`(`talker` 字段区分对象) | `Msg_` 分表 | | 联系人表 | `rcontact` | `contact_contact.db` 的 `contact` | | 会话表 | `conversation`(可能为空) | `session_session.db` 的 `SessionTable` | ### message 表关键字段 - `msgId` — 消息 ID - `type` — 消息类型:1=文本, 3=图片, 49=链接/卡片, 10000=系统消息 - `isSend` — 0=收到, 1=自己发送 - `createTime` — 毫秒时间戳 - `talker` — 聊天对象:`wxid_xxx`(单聊)、`xxx@chatroom`(群聊) - `content` — 消息内容。群聊格式:`sender_wxid:\n` ### rcontact 表关键字段 - `username` — wxid - `nickname` — 昵称 - `conRemark` — 备注名 - `type` — 1=好友, 2=群成员, 3=公众号 - `deleteFlag` — 0=正常 ## 使用步骤 ### 1. 环境准备 ```bash # 手机端:确认 frida-server 已运行(root) adb shell "ps -A | grep frida-server" # Debian proot 里安装 frida Python 包(版本匹配手机 frida-server) pip install frida==17.9.10 # 安装 sqlcipher(用于解密) # Debian: apt-get install sqlcipher # Mac: brew install sqlcipher ``` ### 2. 捕获 SQLCipher key ```bash python3 wechat_android_attach.py ``` - 脚本会自动 kill 微信、重新启动、attach Frida - 等待 `KEY CAPTURED` 输出 - key 自动保存到 `~/wxmoment/wechat_keys.json` ### 3. 提取 DB 文件 ```bash python3 wechat_android_attach.py --extract-db ``` - 复制 `EnMicroMsg.db` + `-shm` + `-wal` 到 `~/wxmoment/dbs/` - **必须复制 wal 文件**,否则丢失最新数据 ### 4. 解密 DB ```bash python3 wechat_android_attach.py --decrypt ``` - 自动尝试字符串密码 / hex key + 多种 cipher 配置组合 - 输出:`~/wxmoment/dbs/EnMicroMsg.db.decrypted.db` ### 5. 启动搜索服务器 ```bash python3 search_server_android.py ~/wxmoment/dbs/EnMicroMsg.db.decrypted.db ``` - 访问 http://localhost:5002 - 支持:会话列表、联系人浏览、聊天记录分页、全局搜索 ## 手动解密(如需自定义) ```bash sqlcipher EnMicroMsg.db PRAGMA key = "e03ce81"; PRAGMA cipher_compatibility = 1; PRAGMA cipher_page_size = 1024; ATTACH DATABASE 'EnMicroMsg_plain.db' AS plain KEY ''; SELECT sqlcipher_export('plain'); DETACH DATABASE plain; .quit ``` ## Frida 脚本 API 说明 `wechat_android_key_hunter.js` 的 Hook 点: | Hook 函数 | 模块 | 用途 | |-----------|------|------| | `sqlite3_key` | `libWCDB.so` | 捕获密码/key | | `sqlite3_key_v2` | `libWCDB.so` | 捕获密码/key(带 db name) | | `sqlite3_open_v2` | `libWCDB.so` | 记录 DB 文件路径 | | `sqlite3_exec` | `libWCDB.so` | 捕获 `PRAGMA key` / `PRAGMA cipher_*` | 发送的消息格式(JSON): ```json {"type": "key", "hex": "65303363653831", "len": 7, "via": "libWCDB.so!sqlite3_key", "path": "", "extra": {"native": true, "v2": false, "db": "0x77342ab938"}} ``` ## 注意事项 1. **frida-server 版本必须匹配 Python frida 包版本**(当前:17.9.10) 2. **微信是多进程应用**,主进程 PID 需要通过 `pgrep -x com.tencent.mm` 获取最小 PID 3. **spawn 模式会超时**,所以使用 `am force-stop` + `am start` + `attach(pid)` 的 early-bird 模式 4. **Java 层 hook 不可用**,因为微信主进程对 Frida 隐藏了 JVM。所有 hook 都在 native 层完成 5. **DB 路径**:`/data/data/com.tencent.mm/MicroMsg//EnMicroMsg.db` 6. **`` 目录名**:基于微信账号生成,每个账号不同