by zhuyansen
微信收藏可视化 Claude Code Skill — 从加密 DB 到交互式 HTML 报告的端到端管线
# Add to your Claude Code skills
git clone https://github.com/zhuyansen/wx-favorites-reportGuides for using ai agents skills like wx-favorites-report.
See how wx-favorites-report compares with popular alternatives.
wx-favorites-report is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by zhuyansen. 微信收藏可视化 Claude Code Skill — 从加密 DB 到交互式 HTML 报告的端到端管线. It has 644 GitHub stars.
wx-favorites-report's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/zhuyansen/wx-favorites-report" and add it to your Claude Code skills directory (see the Installation section above). wx-favorites-report ships a SKILL.md manifest, so compatible agents can discover and load it automatically.
wx-favorites-report is primarily written in Python. It is open-source under zhuyansen on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh wx-favorites-report against similar tools.
No comments yet. Be the first to share your thoughts!
Available after the catalog security scan passes.
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
将微信收藏数据(加密 Favorite.db)端到端解密、解析、生成交互式 HTML 可视化报告。
询问用户是否已有解密后的 Favorite.db。
# 复制微信到桌面并去掉 Hardened Runtime
cp -R /Applications/WeChat.app ~/Desktop/WeChat.app
codesign --force --deep --sign - ~/Desktop/WeChat.app
pip3 install frida frida-tools
# 关闭原版微信,从桌面副本启动
killall WeChat 2>/dev/null; sleep 2
# 用 frida spawn 模式启动微信并 hook PBKDF2
PYTHONPATH=$(python3 -c "import site; print(site.getusersitepackages())") python3 << 'PYEOF'
import frida, time
JS_CODE = """
function buf2hex(buffer) {
var a = new Uint8Array(buffer); var h = '';
for (var i = 0; i < a.length; i++) h += ('0' + a[i].toString(16)).slice(-2);
return h;
}
var found = false;
Process.enumerateModules().forEach(function(m) {
if (found) return;
m.enumerateExports().forEach(function(exp) {
if (found) return;
if (exp.name === "CCKeyDerivationPBKDF") {
found = true;
send("[*] Hook installed on " + m.name);
Interceptor.attach(exp.address, {
onEnter: function(args) {
this.pwLen = args[2].toInt32();
this.saltLen = args[4].toInt32();
this.rounds = args[6].toInt32();
this.pw = args[1]; this.salt = args[3];
this.dk = args[7]; this.dkLen = args[8].toInt32();
},
onLeave: function(retval) {
if (this.pwLen < 4 || this.pwLen > 256) return;
if (this.saltLen < 4 || this.saltLen > 64) return;
var saltHex = buf2hex(this.salt.readByteArray(this.saltLen));
var dkHex = buf2hex(this.dk.readByteArray(this.dkLen));
var pwHex = buf2hex(this.pw.readByteArray(this.pwLen));
send("[PBKDF2] r=" + this.rounds + " salt=" + saltHex);
var f = new File("/tmp/wechat_frida_keys.log", "a");
f.write("rounds=" + this.rounds + "\\npw=" + pwHex + "\\nsalt=" + saltHex + "\\ndk=" + dkHex + "\\n\\n");
f.flush(); f.close();
}
});
}
});
});
if (!found) send("[!] CCKeyDerivationPBKDF not found");
"""
device = frida.get_local_device()
pid = device.spawn(["/Users/" + __import__('os').getenv('USER') + "/Desktop/WeChat.app/Contents/MacOS/WeChat"])
session = device.attach(pid)
script = session.create_script(JS_CODE)
script.on("message", lambda msg, data: print(msg.get("payload", msg)))
script.load()
device.resume(pid)
print("WeChat running. Login → open Favorites → wait 60s...")
time.sleep(120)
session.detach()
print("Done. Check /tmp/wechat_frida_keys.log")
PYEOF
重要:微信启动后必须登录并打开「收藏」页面,触发 favorite.db 的密钥加载。
解析 frida 日志,找到 favorite.db 对应的 enc_key(通过 salt 匹配),然后用 Python 解密:
# 核心解密逻辑(内置在 parse_favorites.py 的上游)
import hashlib, hmac, struct
from Crypto.Cipher import AES
# enc_key = 从 frida 日志中 256000 轮 PBKDF2 输出匹配 DB salt 的 dk
# 逐页 AES-256-CBC 解密,HMAC-SHA512 校验
安装依赖:pip3 install pycryptodome
python3 ~/.claude/skills/wechat-favorites-viz/scripts/parse_favorites.py \
--input "<解密后的 favorite.db 路径>" \
--output "<输出目录>/data.json"
兼容 WeChat 3.x (FavItems) 和 4.x (fav_db_item) 表结构。
python3 ~/.claude/skills/wechat-favorites-viz/scripts/generate_report.py \
--input "<输出目录>/data.json" \
--output "<输出目录>/report.html"
# 推荐用 http server(file:// 下部分交互可能受限)
cd <输出目录> && python3 -m http.server 8765 &
open http://localhost:8765/report.html
| 区域 | 内容 |
|---|---|
| 统计卡片 | 总数、时间跨度、日均收藏、最忙日 |
| 亮点发现 | 最爱来源、主力类型 |
| 月度趋势 | 折线 + 面积图 |
| 类型分布 | 甜甜圈图 |
| 来源 Top15 | 水平柱状图 |
| 活跃热力图 | 星期 × 小时 |
| 时段分布 | 小时 / 星期柱状图 |
| 词云 | 标题 + 描述提取 |
| 标签云 | 微信收藏标签 |
| 收藏浏览 | 按类型筛选 + 按标签筛选 + 搜索 + 排序 + 分页 |
| 详情弹窗 | 点击卡片展开完整内容、链接、来源、标签 |
| Type | 含义 | 解析字段 |
|---|---|---|
| 1 | 文本 | desc |
| 2 | 图片 | datafmt + fullsize |
| 4 | 视频 | datatitle + datadesc |
| 5 | 文章/链接 | pagetitle + pagedesc + link + pagethumb_url |
| 8 | 文件 | datatitle + datafmt + fullsize |
| 14 | 聊天记录 | datalist → 逐条 datadesc 拼接 |
| 其他 | 位置/笔记/小程序等 | 通用 title + desc 回退 |
pip3 install pycryptodome)pip3 install frida frida-tools)<输出目录>/
├── data.json # 解析后的结构化数据
└── report.html # 单文件可视化报告(可直接分享)
从加密的微信 Mac 本地数据库中提取收藏数据,生成交互式可视化 HTML 报告。
报告包含:统计仪表盘、月度趋势、类型分布、来源排行、活跃热力图、词云、标签云,以及可按类型/标签筛选的收藏浏览区。
截图请打开
report.html后自行截取(数据含个人信息,不宜公开分享截图)
# 在 Claude Code 中说:
微信收藏可视化
Claude 会自动完成密钥提取、解密、解析、报告生成全流程。
pip3 install frida frida-tools pycryptodome
微信 App Store 版有 Hardened Runtime 保护,需要复制一份去掉签名限制:
cp -R /Applications/WeChat.app ~/Desktop/WeChat.app
codesign --force --deep --sign - ~/Desktop/WeChat.app
关闭当前微信,用 frida 启动桌面版微信:
killall WeChat 2>/dev/null; sleep 2
# 运行 frida hook 脚本(见 SKILL.md 中完整代码)
# 微信启动后:登录 → 打开「收藏」页面 → 等待 60 秒
frida 会 hook CCKeyDerivationPBKDF 函数,捕获所有 PBKDF2 密钥派生调用。
输出文件:/tmp/wechat_frida_keys.log
从 frida 日志中找到 favorite.db 对应的 enc_key(通过 salt 匹配),用 Python 解密:
# favorite.db 路径:
# ~/Library/Containers/com.tencent.xinWeChat/Data/Documents/
# xwechat_files/<wxid>/db_storage/favorite/favorite.db
# 解密参数: SQLCipher 4
# AES-256-CBC, HMAC-SHA512, PBKDF2 256000 轮, page_size=4096, reserve=80
# 解析数据
python3 parse_favorites.py --input favorite_decrypted.db --output data.json
# 生成 HTML 报告
python3 generate_report.py --input data.json --output report.html
# 打开(推荐用 http server)
cd <输出目录> && python3 -m http.server 8765
open http://localhost:8765/report.html
在实现过程中经历了 6 轮迭代,以下是关键经验:
| 尝试 | 方法 | 结果 | 原因 |
|---|---|---|---|
| 1 | C 内存扫描 x'hex' 格式 | 0 keys | WeChat 4.x 不用此格式存密钥 |
| 2 | 搜索原始 salt 字节 | 误匹配 | 匹配到 ASCII 字符串不是真密钥 |
| 3 | HMAC 暴力验证 (8B对齐) | 未找到 | 过滤条件跳过了真正位置 |
| 4 | 无过滤暴力 (4B对齐) | 未找到 | 密钥经 PBKDF2 派生后存储,不是原始 enc_key |
| 5 | DYLD hook / lldb | 被阻止 | macOS SIP + Hardened Runtime |
| 6 | frida + CCKeyDerivationPBKDF | 成功 | hook 系统 PBKDF2 函数捕获派生过程 |
坑 1: SIP 阻止签名 /Applications 下的微信 复制到 ~/Desktop 再签名。
坑 2: sudo 启动微信导致数据目录变成 /var/root 不用 sudo,以普通用户身份运行 frida。
坑 3: favorite.db 密钥在启动时不加载 微信只在用户打开「收藏」页面时才加载 favorite.db。frida 运行期间必须手动打开收藏。
坑 4: WeChat 4.x 表结构变化
3.x 用 FavItems + FavDataItem,4.x 改为 fav_db_item 单表,content 是 XML。
坑 5: XML 字段名不统一
文章标题在 <pagetitle> 不是 <title>,聊天记录在 <datalist><dataitem><datadesc>,视频标题在 <dataitem> 内部的 <datatitle>。
坑 6: JS 引号嵌套
onerror="this.style.display='none'" 在 Python f-string + JS 模板字符串中会导致语法错误。用 " 替代。
坑 7: file:// 协议下 onclick 不工作 改用 event delegation(addEventListener on parent element)。
坑 8: ECharts 图表间距 图表容器需要明确的 height,否则部分区域渲染为空白。
~/.claude/skills/wechat-favorites-viz/
├── SKILL.md # Skill 定义(触发词、流程、参数)
└── scripts/
├── parse_favorites.py # 解析器(SQLite/CSV/JSON → 统一 JSON)
├── generate_report.py # 报告生成器(JSON → 单文件 HTML)
└── demo_data.py # 模拟数据生成(测试用)
| 组件 | 技术 |
|---|---|
| 密钥提取 | frida 17.x, CCKeyDerivationPBKDF hook |
| 数据库解密 | PyCryptodome AES-256-CBC, HMAC-SHA512 |
| 数据解析 | Python sqlite3 + regex XML |
| 可视化 | ECharts 5.x CDN, echarts-wordcloud 2.x |
| 报告格式 | 单文件 HTML,暗色主题,内联所有依赖 |