Files
wx-win-agent/docs/validation/Message-Model-2026-09-06.md
T
rogee fb8c25c83c feat: database-backed message model with multi-account key cache
- Add Windows 4.1.x Config.Cipher pointer-chain key extraction with cross-chunk
  MemoryPatternScanner and bounded blob XOR decoding; keys still require per-DB
  page-1 HMAC verification before caching.
- Cache keys by account fingerprint + database relative path; db scan --save
  skips memory scanning entirely once all discovered databases are cached.
- Add DbMessage model (localId, serverId, type, timestamp, sender, display name,
  avatar, isSelf) read read-only from Msg_{md5(chat)} via SQLCipher with hex/zstd
  content decoding and contact.db name resolution.
- CLI: db messages / db contacts / db schema with masked defaults; include the
  earlier chat send --session wiring. 97 Core tests pass; real-machine validated.
2026-09-06 14:35:19 +08:00

3.9 KiB
Raw Blame History

完整消息模型:只读数据库消息读取与多账号密钥缓存(2026-09-06)

目标与边界

  • 本阶段补齐「完整消息模型」:稳定消息 ID、发送者、时间戳、收发方向等 UIA 无法提供的字段,全部来自只读 SQLCipher 数据库。
  • 不写数据库、不注入、不修改微信进程、不做登录绕过;密钥只通过页面 1 HMAC 校验后缓存。
  • 一个机器多账号:密钥按「账号指纹 + 库相对路径」缓存,已缓存账号后续 db scan 直接跳过内存扫描。

密钥提取(Windows 微信 4.1.13.63

  • 旧式明文十六进制扫描(ASCII/UTF-16)在该版本找不到可验证密钥。
  • 新增 Windows 4.1.x 的 Config.Cipher 只读指针链扫描:
    • 全内存找 com.Tencent.WCDB.Config.Cipher 字符串地址;
    • 用字符串地址+长度组成的 16 字节对再次全内存定位对象节点(节点基址 = 配对地址 - 0x10);
    • 沿节点 +0x28 → 配置指针 +0x88 → 数据指针 +0x8 / 长度 +0x10 读回最多 1024 字节的加密配置块;
    • 固定 33 字节 XOR 掩码解码,提取 x'<64~192 hex>' 字面量,候选密钥要求 ≥15 个不同字节且非全 0/全 FF;
    • 最终仍以每个目标库页面 1 HMAC 校验为准。
  • MemoryPatternScanner 处理跨分块/跨区边界匹配;所有读出的进程内存缓冲均清零。
  • 扫描结果:5 个进程、19,309 个候选、149,800 次校验 → 20 个数据库全部 PageHmacVerified,来源进程 8912。

多账号缓存

  • db scan --save 先加载密钥缓存,计算「发现库 − 已缓存库」;无待办则 scanned=false 直接跳过(processCount/candidateCount=0)。
  • 第二次 db scan --save 验证:scanned=false,缓存仍 20 个库,无需重扫。
  • 缓存键大小写不敏感(Windows 路径);新账号/新库出现时才触发增量扫描。

消息模型与读取

  • 消息表名:Msg_{md5(chat_wxid)};在 message/message_*.dbmessage/biz_message_*.db 中定位。
  • 只读查询列:local_id, server_id, local_type, create_time, hex(message_content), WCDB_CT_message_content, real_sender_idLEFT JOIN name2id 得发送者 wxid。
  • 内容解码:hex → UTF-8;压缩标记且带 zstd 魔数 28 b5 2f fd 时用 zstd 解压(ZstdSharp.PortCore 内跨平台)。
  • 发送者显示名/头像:contact/contact.dbcontact 表按 wxid 批量查 remark → nick_name → usernamesmall_head_url
  • 收发方向:账号根目录名 <wxid>_<random> 前缀匹配发送者即 IsSelf=trueAccountRootPath 指向 db_storage,其父目录名才是账号目录)。
  • CLIdb messages --account <fp> --chat <wxid> [--limit] [--include-content]db contactsdb schema;默认脱敏,--include-content 才显示名称/内容/头像。

真机验收

  • Windows 10.0.19044,微信 4.1.13.63,原交互会话 1(已解锁),唯一密钥缓存。
  • 群聊名解析:db contacts --contains 测试 命中 53271859539@chatroom,昵称「消息测试专用群组」。
  • 消息读取:db messages --chat 53271859539@chatroom --limit 6 --include-content 返回 6 条:
    • 每条含 local_id712)、server_idtype=1、RFC3339 时间戳、发送者、IsSelf、显示名、头像、内容。
    • 内容正是此前本机发送的测试标记(wx-agent-isolation-*wx-agent-repeat-*wx-agent-m6-listener-*),证明 hex/zstd 解码正确。
    • 本机发送消息 IsSelf=truesenderName=Rogee;发送者名/头像经 contact.db 解析。
  • Core97/97 测试通过;Release 全量构建与 self-contained 发布 0 警告 0 错误。
  • 密钥文件位于 %LOCALAPPDATA%\WxAgent\database-keys.json,ACL 仅当前用户;CLI 输出不含密钥。

尚未完成(本阶段之外)

  • 通用发送能力、导航能力、合并聊天记录展开仍按顺序推进。
  • 消息模型与 UIA 事件流的合并(实时新消息方向归属)不在本阶段。