# wx_msg_extractor **Repository Path**: jimonik/wx_msg_extractor ## Basic Information - **Project Name**: wx_msg_extractor - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-18 - **Last Updated**: 2026-06-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # wxmsg Android 应用:通过 Shizuku 复制微信本地数据,**自动解密** `EnMicroMsg.db`,展示联系人聊天记录,并解析多种消息类型(文本、图片、语音、链接、引用、表情、视频、文件等)。 ## 环境要求 - userdebug / 可调试设备 - 使用 `app/platform.jks` 的 **platform 签名** 安装 - 手机已安装并登录 **微信** - 已安装并运行 [**Shizuku**](https://shizuku.rikka.app/),且已授权本应用 ## 使用 1. 启动 Shizuku 2. 打开 wxmsg,在 Shizuku 中授权 3. 点击右上角 **刷新**(会同步数据库、密钥文件、`WxFileIndex.db`) 4. 点击联系人查看聊天记录 ## 构建安装 ```bash ./gradlew :app:assembleDebug adb install -r app/build/outputs/apk/debug/app-debug.apk ``` ## 架构 | 模块 | 路径 | 作用 | |------|------|------| | `WxDataSync` | `util/WxDataSync.java` | Shizuku 复制 DB、密钥文件、`WxFileIndex.db` | | `WxKeyResolver` | `wx/WxKeyResolver.java` | 密钥推导(MD5 + ini 备选) | | `WxDatabase` | `wx/WxDatabase.java` | SQLCipher 解密,打开主库与文件索引库 | | `WxRepository` | `wx/WxRepository.java` | 联系人/消息查询,媒体元数据补全 | | `WxMessageParser` | `wx/WxMessageParser.java` | 消息类型识别、XML 解析、预览文本 | | `WxXmlHelper` | `wx/WxXmlHelper.java` | appmsg / refermsg / emoji XML 字段提取 | | `WxFileIndex` | `wx/WxFileIndex.java` | 查询 `WxFileIndex.db` 获取视频/文件路径 | | `WxMediaPath` | `wx/WxMediaPath.java` | 图片/语音/视频/表情/附件远程路径规则 | | `WxMediaCache` | `util/WxMediaCache.java` | Shizuku 复制媒体到本地缓存 | | `BitmapLoader` | `util/BitmapLoader.java` | 图片/GIF 解码(含 `ImageDecoder`) | | `VoicePlayer` | `util/VoicePlayer.java` | SILK → WAV 解码后播放 | | `MessageAdapter` | `adapter/MessageAdapter.java` | 多类型聊天气泡 UI | ## 数据同步 刷新时通过 Shizuku 从微信目录复制到 App 缓存(`cache/wechat_db/`),主要包括: | 文件 | 用途 | |------|------| | `EnMicroMsg.db` (+ wal/shm) | 加密聊天记录 | | `WxFileIndex.db` | 视频/文件等媒体索引 | | `auth_info_key_prefs.xml` | 读取 UIN | | `com.tencent.mm_preferences.xml` | UIN 备选 | | `MicroMsg/CompatibleInfo.cfg` | 读取绑定 deviceId(IMEI) | | `MicroMsg/systemInfo.cfg` | UIN 备选 | | `EnMicroMsg.db.ini` | 密钥备选(createmd5) | 微信用户目录(hash 目录)路径会保存在 `WxDataSync.Result.remoteHashDir`,用于后续复制 `image2/`、`voice2/`、`video/`、`emoji/`、`attachment/` 等媒体文件。 复制完成后会 `chown/chmod` 到 App UID,否则无法读取。 ## EnMicroMsg.db 解密方式 微信使用 **WCDB(SQLCipher 3)** 加密数据库。`EnMicroMsg.db` 与 `WxFileIndex.db` 使用相同密钥。App 内实现与微信 `openDatabase` 一致。 ### 密码(passphrase) 7 位小写 hex 字符串,以 UTF-8 文本形式传入 SQLCipher(例如 `"4b1103f"`)。 ``` password = MD5(deviceId + uin).substring(0, 7).toLowerCase() ``` - **uin**:微信账号 ID - 优先 `auth_info_key_prefs.xml` 的 `_auth_uin` - 或 `last_login_uin` / `systemInfo.cfg` - **deviceId**:设备标识,与 IMEI 拼接规则相同 - 优先从 `MicroMsg/CompatibleInfo.cfg` 解析绑定 IMEI - **Android 10+ 且 cfg 为空时**,微信使用固定值:`1234567890ABCDEF` 示例(Android 10+、cfg 为空): ``` MD5("1234567890ABCDEF" + "1654314370")[:7] = "4b1103f" ``` ### 密钥尝试顺序 1. `MD5(deviceId + uin)[:7]`(主路径) 2. `EnMicroMsg.db.ini` 中 `createmd5=` 的前 7 位(备选;部分版本 ini 可能过期,不可单独依赖) ### SQLCipher 参数 与 WCDB 默认一致(见 `WxDatabase.java`): ``` PRAGMA cipher_page_size = 1024 PRAGMA kdf_iter = 4000 PRAGMA cipher_hmac_algorithm = HMAC_SHA1 PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1 PRAGMA cipher_use_hmac = OFF ``` ## 消息类型支持 ### 完整支持(解析 + UI) | type | 含义 | 表现 | |------|------|------| | **1** | 文本 | 原文气泡 | | **3** | 图片 | 缩略图/原图(`image2/`) | | **34** | 语音 | SILK 解码播放(`voice2/`) | | **285212721** | 公众号/网页链接 | 标题 + 摘要卡片,点击打开 URL | | **318767153** | 支付通知 | 同上 | | **822083633** | 引用回复 | 引用条 + 回复正文 | | **47** | 表情 | 本地 emoji 或 CDN 下载展示 | | **43** | 视频 | 缩略图 + 时长,点击系统播放器打开 | | **1090519089** | 文件 | 文件名 + 大小,点击打开 | | **436207665** | 红包 | 卡片,可点击 | | **419430449** | 转账 | 卡片,可点击 | | **268445456** | 撤回提示 | 居中系统提示 | | **10000 / 10002** | 系统消息 | 居中系统提示 | ### appmsg 内层类型(XML ``) | 内层 type | 含义 | |-----------|------| | 5 | 链接 | | 6 | 文件 | | 57 | 引用(refermsg) | | 2000 | 转账 | | 2001 | 红包 | type **49** 等通用 appmsg 会按 XML 内层 type 自动归类。 ## 媒体路径规则 | 类型 | 远程路径(相对 hash 目录) | |------|---------------------------| | 图片 | `image2/{hash[0:2]}/{hash[2:4]}/{hash}.jpg` 等 | | 语音 | `voice2/{md5(imgPath)[0:2]}/{md5[2:4]}/msg_{imgPath}.amr` | | 视频 | `video/{md5[0:2]}/{md5[2:4]}/video_{filename}.mp4` | | 表情 | `emoji/{md5}.gif` 等,失败时从 `EmojiInfo.cdnUrl` 下载 | | 附件 | `attachment/{md5[0:2]}/{md5[2:4]}/{md5}` | 视频/文件优先通过 `WxFileIndex.db`(表 `WxFileIndex3` 或 `WxFileIndex2`)按 `msgId + msgType` 查真实路径。 本地缓存目录:`cache/wechat_db/media/`。 ## 依赖 - [SQLCipher Android](https://www.zetetic.net/sqlcipher/) — 数据库解密 - [Shizuku](https://github.com/RikkaApps/Shizuku) — 读取微信私有目录 - [SilkDecoder](https://github.com/xxinPro/SilkDecoder) — 微信 SILK 语音解码 ## 调试 ```bash adb logcat -s WxMsg ``` 成功解密日志示例: ``` key derive deviceId=****CDEF uin=****4370 md5[:7]=****103f decrypted key=****103f source=md5(defaultDeviceId+uin) WxFileIndex opened size=... copied image ... bytes copied voice ... bytes ``` ## 已知限制 - 需 Shizuku 授权;微信未登录或密钥文件缺失时解密失败 - 媒体文件须微信已下载到本地;未下载的原图/视频/文件可能显示「未找到」 - `CompatibleInfo.cfg` 为空时使用默认 deviceId,与 Android 10+ 微信行为一致 - `EnMicroMsg.db.ini` 的 createmd5 可能过期,以 MD5 推导为准 - 表情 GIF 在 API 28+ 使用 `ImageDecoder`;部分厂商 ROM 主题色异常已用固定颜色规避