HANDOFF.md 5.67 KB

HANDOFF: WeChat Android EnMicroMsg.db 解密方案

由 Claude 完成并交接给 Hermes。本文件位于 ~/.hermes/tools/wechat/ 目录下。


你的角色

你是 Hermes Agent,现在接手 WeChat Android 数据库解密和读取工作。 用户(yibo)需要你在 Android 手机上(Termux + Debian proot 环境)执行微信 SQLite 数据库的提取、解密和读取。

文件位置(全部在 Termux 主目录下)

部署到手机后这些文件平铺在一个目录里(下方命令均假设当前目录就是它)。 仓库源码则按功能分目录:scripts/db-decrypt/(解密套件)、scripts/search/(搜索服务)、scripts/docs/(本文档)。

~/.hermes/tools/wechat/
├── wechat_android_key_hunter.js    # Frida 脚本:hook libWCDB.so 截获 SQLCipher key   ← 源: db-decrypt/
├── wechat_android_attach.py        # Python 控制脚本:attach / extract / decrypt       ← 源: db-decrypt/
├── search_server_android.py        # Web 搜索服务器:读取解密后的 EnMicroMsg.db        ← 源: search/
└── README_Android.md               # 完整操作文档                                       ← 源: docs/

关键成果(已通过测试验证)

项目 值
目标 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.db
  • EnMicroMsg.db-shm
  • EnMicroMsg.db-wal

到 ~/wxmoment/dbs/。WAL 文件必须复制,否则丢失最新数据。

步骤 3:解密

python3 wechat_android_attach.py --decrypt

脚本会自动:

  1. 读取 wechat_keys.json 中的 key
  2. 尝试字符串密码和 hex key 两种格式
  3. 尝试多种 cipher 配置组合
  4. 输出 ~/wxmoment/dbs/EnMicroMsg.db.decrypted.db

步骤 4:Web 查看

python3 search_server_android.py ~/wxmoment/dbs/EnMicroMsg.db.decrypted.db

访问 http://localhost:5002,支持:

  • 会话列表(按最后消息时间排序)
  • 联系人浏览(按拼音首字母排序)
  • 聊天记录分页查看
  • 全局消息搜索

手动解密(备用)

如果自动解密失败:

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=正常

注意事项

  1. frida-server 版本必须匹配 Python frida 包(当前 17.9.10)
  2. 微信是多进程应用,主进程 PID 取 pgrep -x com.tencent.mm 的最小值
  3. spawn 模式会超时,所以脚本使用 am force-stop + am start + attach(pid) 的 early-bird 模式
  4. Java 层 hook 不可用,所有 hook 在 native 层完成
  5. DB 路径:/data/data/com.tencent.mm/MicroMsg/<hash>/EnMicroMsg.db,<hash> 因账号而异
  6. 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 表生成会话列表

后续工作(你可能需要做的)

  1. 批量解密其他 DB:微信还有 WxFileIndex.db、FinderWCDB.db 等,理论上共用同一个 key,可以批量解密验证
  2. 增量同步:微信运行时 WAL 文件不断变化,需要定期重新提取和解密
  3. 适配更多消息类型:当前 search_server 只完整处理了文本(type=1)和链接卡片(type=49),其他类型显示为 [类型XX]
  4. 集成到 lemonPCRM:把解密后的 DB 数据接入项目的数据管道