Belugary
b37d440f47
feat: macOS 图片 AES key 从磁盘 kvcomm 缓存派生(issue #23)
...
macOS 用户长期无法用 C 版 find_image_key_macos 从微信进程内存提取
V2 图片密钥(issue #23 报告 197K 候选全部失败)。新增
find_image_key_macos.py 走完全不同的路径:从磁盘 kvcomm 缓存
文件名派生密钥,无需扫描内存、无需 root、无需重签名。
派生算法
--------
- 扫 ~/.../app_data/net/kvcomm/key_<code>_*.statistic 文件名
- 对每个 (code, wxid) 候选:
xor_key = code & 0xFF
aes_key = MD5(str(code) + cleaned_wxid).hex()[:16] # ASCII 字符串
- 用 V2 _t.dat 文件 [0xF:0x1F] 16 字节做 AES-128-ECB 模板验证:
解出来必须是图像 magic(JPEG / PNG / GIF / WebP / wxgf)
- 为防短 magic 偶然命中,要求多个不同模板都通过验证才算成功
- 命中后写回 config.json 的 image_aes_key / image_xor_key,
monitor_web.py 自动加载
致谢
----
派生算法源自 @hicccc77 在 issue #23 的评论;参考实现见其 WeFlow
项目 (CC BY-NC-SA 4.0)。本模块是独立的 Python clean-room 实现,
未复制其 TypeScript 源码;函数边界与变量命名沿用算法的自然结构
(regex 模式 / MD5 调用顺序 / magic 字节表等不可避免地相同)。
健壮性细节
----------
- 多候选 kvcomm 路径:枚举 5 个不同的 macOS 微信版本路径布局
- 多模板交叉验证:默认收集 3 个不同密文,全部通过才算命中
- 已有 image_aes_key 仍有效时短路返回,不重写 config
- 原子写 config.json:tmp + os.replace + finally 清理 .tmp
- 多 wxid 候选:同时试 raw 和归一化后的 wxid(A_Hare_626a → A_Hare)
- print(flush=True) 逐次显式(与 find_image_key.py 风格一致)
测试
----
新增 tests/test_find_image_key_macos.py,53 个测试覆盖:
派生算法 / wxid 归一化 / kvcomm 路径推算(含多候选)/ 模板收集
(去重 / 子目录 / max_files 边界)/ AES 验证(5 种 magic / 短输入
/ 空 key)/ 多模板交叉验证 / 端到端集成(命中 / 各种失败分支)/
原子写 / main 短路(已有有效 key 不重写 / 已有错 key 落到派生)。
全部通过:python -m unittest discover tests → 88/88。
兼容性
------
- 无新增依赖(pycryptodome 已在 requirements.txt)
- 不改任何现有 Python 文件,零回归风险
- 现有 Windows / Linux 路径 (find_image_key.py / find_image_key_monitor.py) 不受影响
2026-04-27 14:10:15 +08:00
Belugary
989badd14f
feat: 给 transcribe_voice 工具加持久化缓存 ( #58 )
...
Whisper 本地推理在 CPU 下每条语音数秒到数十秒,且同一段 voice_data
产出相同 text,非常适合缓存。新增 voice_transcriptions.json 持久化
存储,命中时跳过 DB 查询、SILK 解码和 Whisper 推理全链路。
关键技术选择:
- 缓存 key 用 json.dumps([username, local_id]),即使 username 含
分隔符也不冲突
- 写入走 tmp + os.replace 原子替换,进程中断不会损坏主文件
- 条目记录 model_size,Whisper 默认模型升级后旧条目自动失效
- 空转录也缓存(配合 model_size 失效),避免静音片段每次重跑
- threading.Lock 防御并发 load/save 竞态
- 首次 OSError 写 stderr 警告一次,后续静默避免刷屏
小的行为改进:resolve_username 移到 whisper/pysilk 导入探测之前,
bad chat_name 情况下不再需要 whisper 已安装也能给出"找不到聊天对象"
的错误提示。
15 个新测试:持久化 roundtrip、UTF-8 保留、corrupt JSON 容错、原子
写、写前失败不污染主文件、并发 load/save、缓存命中跳过重活、model
不匹配视为 miss、key 对含分隔符 username 的防御。全部通过。
2026-04-25 00:19:08 +08:00
btc-z
edf2c0940a
feat: 新增聊天导出与语音转录 CLI 脚本 ( #57 )
...
* feat: 新增聊天导出与语音转录 CLI 脚本
新增两个独立 CLI 脚本,用于将单个聊天导出为结构化 JSON、并批量
填充语音消息的 Whisper 转录。区别于 MCP 工具:这些脚本面向离线
导出/归档,适合一次性拉取大量消息,或在会话外喂给其他 LLM/索引
管线使用。
- export_chat.py:跨分片合并某个聊天的全部消息,按时间排序后输出
紧凑 JSON(type 为 text 时省略,is_group 仅群聊保留等)。复用
mcp_server 中的消息解析/发送者解析辅助函数。
- transcribe_chat.py:读入 export_chat.py 产出的 JSON,对所有尚
未转录的 voice 消息调用 Whisper,原地写回 transcription 字段。
幂等(已有 transcription 的消息跳过)、崩溃安全(每条写回一次
输出文件)。
- .gitignore:新增 *.json 通配,避免本地导出文件被误提交。
config.example.json 已被跟踪,不受影响。
修复:transcribe_chat.py 原先调用 _silk_to_wav 时缺少 local_id
参数(commit c149389 将 local_id 加入签名用于文件名唯一化),
本 PR 中已补齐。
* docs: 新增聊天导出 JSON 数据格式文档
新增 docs/chat_export_format.md,描述 export_chat.py 与
transcribe_chat.py 产出的 JSON schema:顶层字段、消息对象的必填/
可选字段、默认值省略规则,以及加载与过滤的 Python 示例。
与现有 docs/macos-*.md 指南风格一致,避免在脚本 docstring 中堆叠
大段表格。export_chat.py 的 docstring 加一行指针指向本文档。
* docs: 聊天导出格式文档翻译为中文
与 docs/macos-*.md 既有指南保持一致的语言风格,将
docs/chat_export_format.md 翻译为中文。JSON 字段名、Python
代码示例等技术标识保持英文不变。
* fix: 回应 PR #57 review — 崩溃处理、幂等性、schema 补全
根据 review (#57 ) 的反馈:
- export_chat.py: _resolve_chat_context 返回 None 时的崩溃改为友好
退出,并在 resolve 成功后打印 display_name (username),便于用户
核对 resolve_username 的模糊匹配结果。
- export_chat.py: _query_messages 的 limit=999999 改为 None,避免
超长历史被悄悄截断(_query_messages 对 None 会省略 LIMIT 子句)。
- export_chat.py: 输出 JSON 顶层新增 username 字段,让
transcribe_chat.py 可以跳过二次模糊匹配,避免同名联系人漂移。
- transcribe_chat.py: 优先读取 JSON 顶层的 username,旧导出文件
(无 username)回退到按 chat 名解析,保持向后兼容。
- transcribe_chat.py: 删除未使用的 import io / import wave,将循环
内的 import datetime 提至模块顶部。
- export_chat.py: _decode_sticker_desc 的 varint 单字节简化给出
注释说明局限,以及对 create_time 排序加 "or 0" 防御。
- export_chat.py / transcribe_chat.py: 模块 docstring 翻译为中文,
与 docs/macos-*.md 保持一致。
- docs/chat_export_format.md: 同步补充 username 字段说明。
- .gitignore: 将 *.json 收窄为 *_export*.json / *_transcribed*.json,
避免误屏蔽未来的 config/fixtures,同时匹配导出工具实际产出的
文件名。
2026-04-25 00:16:37 +08:00
btc-z
02bc9c1840
feat: 新增语音 MCP 工具 + macOS 密钥提取修复 ( #53 )
...
* feat: 新增语音 MCP 工具 + macOS 密钥提取修复
- 新增 get_voice_messages / decode_voice / transcribe_voice MCP 工具
- 语音数据存储在 media_0.db VoiceInfo 表(SILK v3 格式)
- decode_voice 解码为 WAV 文件(saved to decoded_voices/)
- transcribe_voice 通过 Whisper 自动识别语言转录
- 新增 get_chat_history oldest_first 参数,支持从最早消息开始分页
- 修复 macOS 下 check_wechat_running / ensure_keys 逻辑
- 改用 pgrep 检测微信进程,绕过不支持 macOS 的 Python 扫描器
- 无 all_keys.json 时打印清晰引导,提示运行 C 版扫描器
- 新增 Makefile(build / keys / decrypt / web 快捷命令)
- .gitignore 补充 find_all_keys_macos 二进制和 decoded_voices/
* fix: 语音查询支持多分片 media DB + 文件名唯一化
解决 PR #53 review 的阻塞项 #1,顺手修 #3、#6。
#1 `_get_media_db_path()` 硬编码 `media_0.db`
- 新增模块级 `MEDIA_DB_KEYS`,镜像 `MSG_DB_KEYS` 的分片发现逻辑
- `_fetch_voice_row` 遍历所有分片,按 `(chat_name_id, local_id)`
首个命中即返回;单条语音在 media DB 家族内唯一,命中即可停
- `get_voice_messages` 从每个分片各取 `LIMIT limit`,合并排序后
截断到 `limit`。选择"每分片取 limit 条再合并"而非"按
max(create_time) 排序后逐个取到 limit 即停止":后者假设分片
间时间不重叠,一旦 WeChat 改分片策略就会静默丢消息;前者工作
量 O(N 分片 × limit),在任何分片布局下都正确
#3 输出文件名冲突
- `_silk_to_wav` 增加 `local_id` 参数,输出 `{user}_{time}_{lid}.wav`,
同一秒内两条语音不会互相覆盖;两个调用方都已在作用域内持有
`local_id`
#6 `_fetch_voice_row` 的 `local_id=None` 死分支
- 随 #1 的重写一并删除,`local_id` 改为必填位置参数
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
* refactor: macOS 密钥提取分层下沉到 find_all_keys.py
解决 PR #53 review 的阻塞项 #2。
review 里提到"跟 PR #51 冲突"实测不存在 —— PR #51 当前 0 文件改动
(fork 分支已与上游同步),但架构建议本身是对的:macOS 处理应集中
在 `find_all_keys.py`,而不是在 `main.py` 提前 return 截胡。
- `main.py:ensure_keys()` 移除 darwin 专属提前返回分支,macOS 走
和其他平台相同的 `extract_keys()` 路径
- `find_all_keys.py:_load_impl()` 在 darwin 分支抛出带
`sudo ./find_all_keys_macos` 操作指引的 RuntimeError;非 macOS
的平台兜底分支保留
- `main.py` 里已有 `except RuntimeError` 会打印并 `sys.exit(1)`,
用户可见行为不变
未来若有 PR 在 `find_all_keys.py` 加 macOS 自动编译 / dispatch,
直接替换这段 RuntimeError 即可,不再需要改 `main.py`。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
* chore: Makefile 支持 PYTHON 变量覆盖
解决 PR #53 review 的非阻塞项 #7。
原 Makefile 硬编码 `.venv/bin/python3`,没有 venv 的用户跑 `make
decrypt` 直接报错。引入 `PYTHON ?= .venv/bin/python3`:默认行为
不变(仍走 venv),想用系统 Python 的用户 `PYTHON=python3 make
decrypt` 即可。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
* docs: 回应 PR #53 review #4 — 澄清 silk-python 与 pysilk 包名关系
验证:本项目 import 的 `pysilk` 实际由 `pip install silk-python`
(synodriver/pysilk) 提供;pypi 上另有同名 `pysilk==0.0.1` 是无内容
的占位包,不可用。错误消息里 `pip install silk-python` 已经是对的,
但 reader 看到 `import pysilk` 仍会困惑,所以:
- `_silk_to_wav` 的 import 处加一行注释,点名所用的是
synodriver 版本,并提醒 pypi 上还有 pilk / pysilk 两个同类包
- `decode_voice` / `transcribe_voice` 的 docstring 加 "依赖:" 行,
明确 "pip install silk-python (import 名为 pysilk)",MCP 客户端
读 tool 描述就能看到正确的安装命令
未新增 requirements.txt 条目:voice 支持是可选功能(tool 内
try/except ImportError 懒加载),保持非必需依赖的语义。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com >
2026-04-23 14:10:22 +08:00
ylytdeng
e86e00df87
fix: 新联系人/新群名称不刷新(issue #46)
...
之前的修复 load_contact_names() 读的是 decrypted/contact/contact.db
静态快照,新加联系人不在里面,所以"自动刷新"实际不生效。
现改为通过 db_cache 实时解密源 contact.db 再加载,确保新增联系人
即时可见。db_cache 内部靠 mtime 检测变化,微信写入后下次查询会触发
重新解密。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-23 13:55:51 +08:00
ylytdeng
a8cf64c0a6
docs: 补充 README macOS 操作说明
...
- 环境要求和快速开始章节新增 macOS 小节
- 添加 macOS 版 config.json 示例
- 明确 codesign、编译、扫描、解密四步流程
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-22 20:56:31 +08:00
ylytdeng
69a2f44240
feat: /api/history 支持按群过滤和增量拉取,更新 README API 文档
...
- /api/history 新增 chat、since、limit 参数
- README 新增 HTTP API 端点说明和联系人标签工具文档
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-09 11:43:41 +08:00
ylytdeng
7eb29b03e8
feat: 新增联系人标签查询功能
...
解析 contact.db 的 contact_label 表和 extra_buffer protobuf Field #30,
支持查询标签列表及指定标签下的成员。
- mcp_server.py: 新增 get_contact_tags / get_tag_members MCP 工具
- monitor_web.py: 新增 /api/tags JSON 端点,支持 ?name= 过滤
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-06 09:54:21 +08:00
ylytdeng
b80e7d1c14
fix: 新群/新联系人自动刷新联系人缓存
...
检测到消息的用户名不在联系人缓存中时,自动重新加载
contact.db,解决新建群聊一直显示 chatroom ID 的问题。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-31 18:43:34 +08:00
ylytdeng
396d4b24e2
fix: CLI 入口支持 V2(AES) 格式图片解密
...
decode_image.py 的 CLI 入口之前只走 XOR 解密路径,
V2 格式图片会直接报错退出。改为使用 decrypt_dat_file
智能入口,自动判断 V1/V2/XOR 格式。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-26 16:40:16 +08:00
joshua-deng
0821dc0e4e
Update README.md
...
加了一个tg群,防失联
2026-03-23 17:25:19 +08:00
ylytdeng
944546beb1
fix: 统一所有 JSON 文件读写为 UTF-8 编码
...
Windows 中文环境默认编码为 GBK,未指定 encoding 会导致
config.json/all_keys.json 解析失败。修复 9 个文件共 17 处。
Closes #32
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-20 14:32:37 +08:00
joshua-deng
67244597f2
Merge pull request #28 from dsjzazs/feat/auto-install-deps
...
fix: 改为通过 requirements 安装依赖
2026-03-14 22:22:54 +08:00
joshua-deng
3e79c8e093
Merge pull request #30 from dsjzazs/main
...
MCP增强消息查询,支持时间范围和分页
2026-03-14 17:38:37 +08:00
dsjzazs
7c42ff5d38
Investigate get_chat_history limit
2026-03-14 16:59:17 +08:00
dsjzazs
2cd180c63a
Merge pull request #2 from dsjzazs/codex/searchmessages
...
Add unit tests for MCP search and fix pagination
2026-03-14 16:39:12 +08:00
dsjzazs
9ae558a31e
Fix global search pagination
2026-03-14 16:36:55 +08:00
dsjzazs
2e03247fb9
Add MCP dependency and pin versions ( #1 )
2026-03-14 15:13:28 +08:00
dsjzazs
b623711410
Add MCP search unit tests
2026-03-14 14:07:51 +08:00
dsjzazs
4bda20f7aa
feat: 更新 README
2026-03-14 10:24:23 +08:00
dsjzazs
7e7f7a2516
feat: 增强消息查询功能,支持时间范围和分页
2026-03-14 10:21:21 +08:00
dsjzazs
8e8edc649c
fix: 改为通过 requirements 安装依赖
...
README 改为统一使用 requirements.txt 安装依赖,并补充 zstandard 依赖,避免手动漏装。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-13 16:27:09 +08:00
ylytdeng
7020409543
fix: full_decrypt 写入前自动创建输出目录
...
full_decrypt 打开 out_path 写入时未创建父目录,
首次运行 monitor_web 且 decrypted/ 不存在时会报
FileNotFoundError。
Fixes #22
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-10 17:21:11 +08:00
ylytdeng
030680eb85
fix: 修复短时间大量消息丢失问题
...
旧逻辑用 `if ts == prev_ts: continue` 粗暴跳过上轮时间戳的所有消息,
但同一秒内可能有多条不同消息(如连续转发公众号文章),导致只显示
最后一条,其余丢失。
改为用 (username, timestamp, msg_type) 精确去重:
- 主消息和 hidden 消息显示后都记录到 _shown_keys
- 过滤时精确匹配已显示的消息,不再按时间戳整体跳过
- _shown_keys 每轮清理过期条目(保留 5 分钟),防止内存泄漏
Fixes #20
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-09 19:52:46 +08:00
joshua-deng
64b2c9fdef
Merge pull request #19 from BiboyQG/feat/chat-history-formatting
...
功能改进实用,问题不阻塞合并。
2026-03-09 19:48:06 +08:00
Banghao Chi
fd67536ef7
Refine chat history message parsing
2026-03-08 20:52:33 -05:00
Banghao Chi
fa273b810d
Improve chat history formatting
2026-03-08 15:30:10 -05:00
ylytdeng
a5a347f69e
Merge PR #18 : feat: Linux 数据库解密支持
...
- 新增 find_all_keys_linux.py (通过 /proc/pid/mem 扫描密钥)
- 新增 key_utils.py (跨平台路径兼容)
- 新增 key_scan_common.py (公共扫描逻辑)
- 拆分 find_all_keys.py 为平台分发入口
- 所有下游模块统一使用 get_key_info() 查找密钥
Fixes #12 (部分: Linux 支持)
Co-authored-by: PeanutSplash <b1300658700@outlook.com >
2026-03-07 21:35:37 +08:00
PeanutSplash
30112b9a10
fix(linux): address code review feedback
...
- SUDO_USER: skip fallback entirely when user is invalid (KeyError)
- load_config: move default merge after db_dir check to avoid dead code
- _is_wechat_process: prefer exact comm match, use exe substring as fallback
2026-03-07 21:35:24 +08:00
PeanutSplash
3d58b6508c
fix(linux): validate SUDO_USER and use prefix matching for interpreters
...
- Validate SUDO_USER via pwd.getpwnam() to prevent path injection
- Use prefix matching for interpreter detection to cover python3.10+ etc.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-07 21:35:24 +08:00
PeanutSplash
bf77cc97d8
refactor(linux): improve wechat detection and sudo db path fallback
2026-03-07 21:35:24 +08:00
PeanutSplash
bc80a1578d
refactor(find_all_keys_windows): drop unused constants imports
2026-03-07 21:35:24 +08:00
PeanutSplash
6d9b2c0fe4
refactor(find_all_keys): extract shared key scan logic
2026-03-07 21:35:24 +08:00
PeanutSplash
872e3f58dc
fix: handle exited PIDs and narrow message DB keys
2026-03-07 21:35:24 +08:00
PeanutSplash
f9c338b48d
feat: add Linux support with cross-platform memory scanning
...
- Add Linux memory scanner (`find_all_keys_linux.py`) using `/proc/<pid>/mem`,
same approach as Windows/macOS — no GDB, no function offsets, no restart needed
- Extract Windows-specific code to `find_all_keys_windows.py`
- Make `find_all_keys.py` a platform dispatcher (Windows / Linux)
- Add `key_utils.py` for cross-platform path matching (`/` vs `\` in all_keys.json)
- Update `config.py` with Linux auto-detection of db_storage paths
- Update all consumers (decrypt_db, monitor, monitor_web, mcp_server) to use
`get_key_info()` for platform-agnostic key lookup
Tested on remote Linux container: 15/15 DBs scanned, decrypted, and verified.
2026-03-07 21:35:24 +08:00
ylytdeng
5879b58239
Merge PR #15 : feat: macOS 图片密钥扫描器 + 批量解密器 (C)
...
新增 find_image_key.c 和 decrypt_images.c,
通过 Mach VM API + CommonCrypto 实现 macOS 图片解密。
Co-authored-by: bbingz
2026-03-07 21:35:08 +08:00
bbingz
e84f1d5130
fix: fallback key in multi-key mode + bound printf context
...
- decrypt_images.c: try image_keys.json lookup first, fall back to
config.json single key when CT pattern not mapped (previously returned
-5 immediately in multi-key mode)
- find_image_key.c: cap ASCII context printf to remaining buffer length,
preventing out-of-bounds read near region end
2026-03-07 21:35:00 +08:00
bbingz
96c1a5ac2e
fix: add file size validation and clarify Method 2 intent
...
- decrypt_images.c: validate aes_ct_size + xor_size fits within file
before reading, preventing out-of-bounds reads on corrupt files
- decrypt_images.c: remove unused bytes2hex function
- find_image_key.c: add comment explaining Method 2 design intent —
hex ASCII bytes used directly as AES key (not hex-decoded)
2026-03-07 21:35:00 +08:00
bbingz
03582dd82c
fix: narrow Method 2 scan to hex charset [0-9a-f]
...
Previous range [a-z0-9] was too broad, matching non-hex characters
g-z which wastes CPU on false candidates. WeChat image keys are
lowercase hex strings.
2026-03-07 21:35:00 +08:00
bbingz
0576151b67
feat: add macOS image key scanner and batch decryptor (C)
...
- find_image_key.c: scans WeChat process memory for V2 image AES keys
using Mach VM API + CommonCrypto batch decryption
- decrypt_images.c: batch decrypts V2 .dat image files using keys
from image_keys.json, handles AES-ECB + XOR + raw_data segments
Build: cc -O3 -o find_image_key find_image_key.c -framework Security
cc -O3 -o decrypt_images decrypt_images.c -framework Security
2026-03-07 21:35:00 +08:00
ylytdeng
2b03a81a8f
fix: 统一路径分隔符为正斜杠,修复 macOS/Linux 兼容性
...
all_keys.json 中的 key 统一使用 `/` 作为路径分隔符,
消除 Windows 反斜杠硬编码,确保跨平台兼容。
涉及文件: find_all_keys.py, decrypt_db.py, monitor.py,
monitor_web.py, mcp_server.py, decode_image.py, latency_test.py
Fixes #17
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-07 00:53:48 +08:00
joshua-deng
1294953681
Merge pull request #14 from bbingz/pr/macos-c-scanner
...
核心功能已验证,新增独立文件不影响现有功能。
2026-03-06 09:29:42 +08:00
joshua-deng
fc2ae833dc
Merge pull request #13 from bbingz/pr/macos-docs
...
文档质量高,实测数据详实。剩余小问题不阻塞合并。
2026-03-06 09:29:35 +08:00
bbingz
992c3f5ee4
fix: replace nonexistent scan_keys.js with actual tools in quickstart
...
Quickstart step 4 referenced scan_keys.js which doesn't exist in the
repo. Replace with find_all_keys_macos.c (Method A) and note Frida as
Method B requiring user's own script. Also add config.json note for
step 5.
2026-03-05 23:26:55 +08:00
bbingz
18ffb2e7fa
fix: use forward slashes in JSON output and add size==0 guard
...
- Remove forward-to-backslash conversion in JSON keys — forward slashes
are native macOS paths and don't need JSON escaping (backslash paths
like \b would be misinterpreted as escape sequences by JSON parsers)
- Add size==0 guard after mach_vm_region to prevent infinite loop
2026-03-05 23:19:22 +08:00
bbingz
76dd2b6d95
fix: clear header reserved-space field and add per-page HMAC note
...
- Zero out SQLite header offset 20 (reserved-space) after decryption,
otherwise SQLite miscalculates usable page size
- Add comment noting production code should verify HMAC on every page,
not just page 1
2026-03-05 23:18:03 +08:00
bbingz
d38d7ebf9c
fix: replace glob() with nftw() and add chunk overlap
...
- glob() does not support ** recursive matching on macOS (POSIX).
Replace with nftw() + opendir to recursively walk db_storage/.
- Add overlap between memory chunks to catch x'...' patterns
spanning chunk boundaries.
2026-03-05 22:02:49 +08:00
bbingz
d4314c4857
fix: address review feedback on docs
...
- decrypt_page: zero-fill reserve for all pages (consistency)
- Move reserve into configs tuple for clarity
- Remove unused import os
- Trim duplicated permission content, reference permission guide
- Replace empty scan_keys.js shell with find_all_keys_macos reference
2026-03-05 21:55:10 +08:00
bbingz
1f9ca3792a
feat: add macOS C memory key scanner
...
Scans WeChat process memory for SQLCipher encryption keys using
Mach VM API. Outputs all_keys.json compatible with decrypt_db.py.
Build: cc -O2 -o find_all_keys_macos find_all_keys_macos.c -framework Foundation
Usage: sudo ./find_all_keys_macos [pid]
2026-03-05 21:49:00 +08:00
bbingz
98933d5987
docs: add macOS permission guide and 3.x vs 4.x decryption comparison
...
- macOS permission guide: SIP, task_for_pid, codesign requirements
- 3.x vs 4.x decryption guide: SQLCipher parameter differences,
multi-config DB handling, complete Python decryption examples
2026-03-05 21:48:35 +08:00