HANDOFF.md
5.29 KB
HANDOFF: WeChat Android EnMicroMsg.db 解密方案
由 Claude 完成并交接给 Hermes。本文件位于
~/.hermes/tools/wechat/目录下。
你的角色
你是 Hermes Agent,现在接手 WeChat Android 数据库解密和读取工作。 用户(yibo)需要你在 Android 手机上(Termux + Debian proot 环境)执行微信 SQLite 数据库的提取、解密和读取。
文件位置(全部在 Termux 主目录下)
~/.hermes/tools/wechat/
├── wechat_android_key_hunter.js # Frida 脚本:hook libWCDB.so 截获 SQLCipher key
├── wechat_android_attach.py # Python 控制脚本:attach / extract / decrypt
├── search_server_android.py # Web 搜索服务器:读取解密后的 EnMicroMsg.db
└── README_Android.md # 完整操作文档
关键成果(已通过测试验证)
| 项目 | 值 |
|---|---|
| 目标 | WeChat Android 8.0.72 EnMicroMsg.db |
| SQLCipher key | e03ce81(7 字符字符串密码) |
| cipher_compatibility | 1 |
| cipher_page_size | 1024 |
| 获取方式 | Frida hook libWCDB.so!sqlite3_key,在打开第一个加密 DB 时截获 |
| Java 层 | Java.available = false(微信有反注入),native hook 正常工作 |
| 解密验证 | ✅ message 表 183 条消息可读,rcontact 4481 个联系人 |
三步操作(你必须能执行)
步骤 1:捕获 key
环境要求:
- frida-server 17.9.10 已在手机上运行(
ps -A | grep frida-server) - Python frida 包已安装:
pip install frida==17.9.10 - 手机已 root(Magisk)
执行:
cd ~/.hermes/tools/wechat
python3 wechat_android_attach.py
预期输出:
[*] Killing WeChat...
[*] Starting WeChat...
[*] Attaching to PID xxxxx...
[KEY CAPTURED via libWCDB.so!sqlite3_key]
hex: 65303363653831
len: 7
Key 会自动保存到 ~/wxmoment/wechat_keys.json。
步骤 2:提取 DB
python3 wechat_android_attach.py --extract-db
这会复制:
EnMicroMsg.dbEnMicroMsg.db-shmEnMicroMsg.db-wal
到 ~/wxmoment/dbs/。WAL 文件必须复制,否则丢失最新数据。
步骤 3:解密
python3 wechat_android_attach.py --decrypt
脚本会自动:
- 读取
wechat_keys.json中的 key - 尝试字符串密码和 hex key 两种格式
- 尝试多种 cipher 配置组合
- 输出
~/wxmoment/dbs/EnMicroMsg.db.decrypted.db
步骤 4:Web 查看
python3 search_server_android.py ~/wxmoment/dbs/EnMicroMsg.db.decrypted.db
- 会话列表(按最后消息时间排序)
- 联系人浏览(按拼音首字母排序)
- 聊天记录分页查看
- 全局消息搜索
手动解密(备用)
如果自动解密失败:
sqlcipher ~/wxmoment/dbs/EnMicroMsg.db
PRAGMA key = "e03ce81";
PRAGMA cipher_compatibility = 1;
PRAGMA cipher_page_size = 1024;
ATTACH DATABASE 'plain.db' AS plain KEY '';
SELECT sqlcipher_export('plain');
DETACH DATABASE plain;
.quit
DB 结构(Android 版)
message 表(所有消息在同一个表)
| 字段 | 说明 |
|---|---|
msgId |
消息 ID |
type |
类型:1=文本, 3=图片, 49=链接/卡片, 10000=系统消息 |
isSend |
0=收到, 1=自己发送 |
createTime |
毫秒时间戳 |
talker |
聊天对象:wxid_xxx(单聊)、xxx@chatroom(群聊) |
content |
消息内容。群聊格式:sender_wxid:\n<body> |
rcontact 表(联系人)
| 字段 | 说明 |
|---|---|
username |
wxid |
nickname |
昵称 |
conRemark |
备注名 |
type |
1=好友, 2=群成员, 3=公众号 |
deleteFlag |
0=正常 |
注意事项
- frida-server 版本必须匹配 Python frida 包(当前 17.9.10)
- 微信是多进程应用,主进程 PID 取
pgrep -x com.tencent.mm的最小值 - spawn 模式会超时,所以脚本使用
am force-stop+am start+attach(pid)的 early-bird 模式 - Java 层 hook 不可用,所有 hook 在 native 层完成
- DB 路径:
/data/data/com.tencent.mm/MicroMsg/<hash>/EnMicroMsg.db,<hash>因账号而异 - Key 是动态捕获的,每次微信启动可能变化,需重新捕获
故障排查
| 问题 | 解决 |
|---|---|
No USB Frida device found |
确认 frida-server 在运行:`adb shell "ps -A \ |
unable to find process with name com.tencent.mm |
Frida 枚举不到主进程,脚本已自动 fallback 到 pgrep 取 PID |
Java is not defined |
正常现象,脚本已降级到 native-only hook |
file is not a database |
Key 错误或 cipher 配置不对,检查 wechat_keys.json 和 cipher 配置 |
conversation 表为空 |
正常现象,search_server_android.py 已 fallback 到用 message 表生成会话列表 |
后续工作(你可能需要做的)
- 批量解密其他 DB:微信还有
WxFileIndex.db、FinderWCDB.db等,理论上共用同一个 key,可以批量解密验证 - 增量同步:微信运行时 WAL 文件不断变化,需要定期重新提取和解密
- 适配更多消息类型:当前 search_server 只完整处理了文本(type=1)和链接卡片(type=49),其他类型显示为
[类型XX] - 集成到 lemonPCRM:把解密后的 DB 数据接入项目的数据管道