Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/windows-wechat-vault.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Windows WeChat Vault

on:
pull_request:
paths:
- "yichen-wechat-windows-vault/**"
- ".github/workflows/windows-wechat-vault.yml"
push:
branches: [main]
paths:
- "yichen-wechat-windows-vault/**"
- ".github/workflows/windows-wechat-vault.yml"

permissions:
contents: read

jobs:
test:
runs-on: windows-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.12"
cache: pip
cache-dependency-path: yichen-wechat-windows-vault/requirements.txt
- name: Install pinned dependencies
run: python -m pip install -r yichen-wechat-windows-vault/requirements.txt
- name: Compile scripts
run: >-
python -m py_compile
yichen-wechat-windows-vault/scripts/sqlcipher_codec.py
yichen-wechat-windows-vault/scripts/wal_snapshot.py
yichen-wechat-windows-vault/scripts/secret_store.py
yichen-wechat-windows-vault/scripts/windows_memory.py
yichen-wechat-windows-vault/scripts/windows_vault.py
yichen-wechat-windows-vault/scripts/vault_cli.py
- name: Run tests
run: python -m unittest discover -s yichen-wechat-windows-vault/tests -v
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
**/wechat-keys.json
**/wechat-*.json
**/wechat-*-state.json
**/YichenWeChatVault/
**/keys/account.json
**/.env
**/.env.*
**/*secret*
Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ To request commercial authorization, contact me on WeChat at `yichen365ai` and i
20. Choose between Step and Doubao/Volcengine ASR without duplicate submissions (`yichen-asr`)
21. Create authorized WeCom documents and manage todos, meetings, and schedules through the official CLI without controlling the desktop app (`yichen-wecom-operations`)
22. Turn one public X Post or Thread URL into verified 3:4 image slices and a finished video that embeds complete native video visuals and preserves their original audio when present (`yichen-x-slicer`)
23. Build read-only, integrity-checked local Weixin 4.x snapshots on Windows without `wx-cli`, injection, hooks, or process control (`yichen-wechat-windows-vault`)

## Included Skills

Expand Down Expand Up @@ -237,6 +238,19 @@ Turn one public X status URL into finished social assets:

Install this Skill directly with `npx skills add mcncarl/yichen-skills --skill yichen-x-slicer`.

### 23) `yichen-wechat-windows-vault`

Independent Windows counterpart to the Mac WeChat local vault:

- Uses read-only Windows process inspection only after explicit current-task consent
- Accepts a database key only after SQLCipher HMAC and SQLite-header validation
- Protects stored keys with current-user DPAPI and keeps snapshots under `%LOCALAPPDATA%`
- Copies DB/WAL/SHM as a stable set, validates WAL checksums and commits, and runs SQLite integrity checks
- Supports full or incremental immutable snapshots plus the Mac skill's contacts, sessions, history, search, export, Favorites, and Moments query surface
- Does not depend on `wx-cli`, Frida, injection, hooks, drivers, Weixin UI automation, or process-control APIs

See [yichen-wechat-windows-vault/README.md](./yichen-wechat-windows-vault/README.md) for the consent boundary, installation, architecture, and verification evidence.

## Project Structure

```text
Expand All @@ -261,6 +275,12 @@ yichen-skills/
│ ├─ list_contacts.py
│ ├─ search_sns.py
│ └─ wechat_digest.py
├─ yichen-wechat-windows-vault/
│ ├─ SKILL.md
│ ├─ README.md
│ ├─ requirements.txt
│ ├─ scripts/
│ └─ tests/
├─ yichen-mac-wechat-dual-open/
│ ├─ SKILL.md
│ ├─ scripts/
Expand Down Expand Up @@ -368,6 +388,7 @@ yichen-skills/
- Dependencies:
- X article drafts: `pip install playwright pycryptodome && python3 -m playwright install chromium`
- WeChat local vault: `pip install pycryptodome zstandard`
- Weixin Windows vault (Python 3.10+): `pip install -r yichen-wechat-windows-vault/requirements.txt`
- WeChat dual open: `pip install Pillow`
- Content archive (Douyin): `pip install playwright requests && python3 -m playwright install chromium`
- Content archive (Xiaohongshu): `pip install requests`
Expand Down
20 changes: 20 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
20. 在 Step 与豆包/火山 ASR 之间安全路由并避免重复提交(`yichen-asr`)
21. 通过企业微信官方 CLI 创建授权文档并管理待办、会议和日程,不操控客户端(`yichen-wecom-operations`)
22. 把一条公开 X Post 或 Thread 链接转成经过验收的 3:4 图片切片与成片,完整嵌入原生视频并在有源音轨时保留原声(`yichen-x-slicer`)
23. 在 Windows 上生成只读、经过完整性校验的微信 4.x 本地快照,不依赖 `wx-cli`,不注入、不 Hook、不控制进程(`yichen-wechat-windows-vault`)

## 包含的技能

Expand Down Expand Up @@ -236,6 +237,19 @@ Mac 微信双开——无需第三方工具,一条命令搞定:

可直接运行 `npx skills add mcncarl/yichen-skills --skill yichen-x-slicer` 安装。

### 23) `yichen-wechat-windows-vault`

Mac 微信本地 Vault 的独立 Windows 对应版本:

- 仅在当前任务得到明确同意后使用 Windows 只读进程检查
- 只有同时通过 SQLCipher HMAC 与 SQLite 文件头校验的数据库 key 才会被接受
- key 使用当前 Windows 用户的 DPAPI 加密,快照保存在 `%LOCALAPPDATA%` 私有目录
- 把 DB/WAL/SHM 作为稳定文件集复制,校验 WAL 帧与提交,并运行 SQLite 完整性检查
- 支持全量/增量不可变快照,以及与 Mac 版一致的联系人、会话、历史、搜索、导出、收藏夹和朋友圈查询
- 不依赖 `wx-cli`、Frida、注入、Hook、驱动、微信 UI 自动化或进程控制 API

同意边界、安装、架构和验证证据见 [yichen-wechat-windows-vault/README.md](./yichen-wechat-windows-vault/README.md)。

## 目录结构

```text
Expand All @@ -260,6 +274,12 @@ yichen-skills/
│ ├─ list_contacts.py
│ ├─ search_sns.py
│ └─ wechat_digest.py
├─ yichen-wechat-windows-vault/
│ ├─ SKILL.md
│ ├─ README.md
│ ├─ requirements.txt
│ ├─ scripts/
│ └─ tests/
├─ yichen-mac-wechat-dual-open/
│ ├─ SKILL.md
│ ├─ scripts/
Expand Down
30 changes: 30 additions & 0 deletions yichen-wechat-windows-vault/PROVENANCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Provenance and clean implementation statement

This directory is a new Windows implementation created after the earlier Windows proposal was rejected. It does not contain or invoke `wx-cli`, and no code from that rejected implementation was reused.

## File lineage

- `scripts/windows_memory.py`, `windows_vault.py`, `secret_store.py`, `sqlcipher_codec.py`, and `wal_snapshot.py` are new implementations written for this contribution.
- SQLCipher geometry and HMAC behavior were implemented from the public Tencent SQLCipher source, Tencent WCDB documentation, Zetetic SQLCipher documentation, and SQLite's official WAL format documentation. SHM `maxFrame`/`nBackfill` handling follows the public Tencent WCDB WAL repair parser and SQLite wal-index layout.
- Windows process-memory and DPAPI calls use Microsoft-documented APIs through Python `ctypes`.
- `scripts/vault_cli.py` is adapted from this repository's own `yichen-wechat-local-vault/scripts/vault_cli.py` so that Windows and Mac expose the same read-only query commands. Its configuration and data-root handling were changed for Windows.
- No Tencent, Zetetic, SQLite, Microsoft, `cryptography`, or `zstandard` source code is copied or vendored here.

## Deliberately excluded behavior

- no spawning or relaunching Weixin;
- no process termination, suspension, resume, debugging, injection, hooking, remote allocation, or memory writes;
- no UI automation or message sending;
- no third-party Weixin CLI or binary;
- no hard-coded key, salt, account identifier, process address, or private test data;
- no silent key capture or plaintext export.

## Validation evidence expected for a release

1. Windows CI passes all synthetic codec, WAL, DPAPI, query, export, and safety tests.
2. `skill-creator` metadata validation passes.
3. A current official Windows Weixin build is diagnosed without exposing account data.
4. With explicit consent, at least one real active database key is captured and validates.
5. After the user manually exits Weixin, every discovered DB/WAL/SHM set is snapshotted, all required capability databases refresh into a promoted generation, optional gaps are explicitly disclosed, and query smoke tests pass.

Items 4 and 5 are local-only evidence and must never publish keys, database files, account paths, or chat content.
122 changes: 122 additions & 0 deletions yichen-wechat-windows-vault/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Yichen WeChat Windows Vault

An independent Windows counterpart to `yichen-wechat-local-vault`. It creates local, immutable plaintext snapshots of the current Windows user's Weixin 4.x databases and provides the same read-only query/export surface as the Mac skill.

## What it does

- Discovers official Windows Weixin account databases under the current user's `Documents\xwechat_files`.
- With explicit current-task consent, reads only `Weixin.exe` process memory and waits for an ordinary SQLCipher key-use window.
- Aggregates independently validated matches across every readable Weixin subprocess instead of assuming all database contexts live in one process.
- Validates every captured key against both the SQLCipher page HMAC and SQLite header before accepting it.
- Protects accepted keys with current-user Windows DPAPI; raw keys are never printed or stored in the repository.
- Copies DB/WAL/SHM only after the user manually exits Weixin.
- Validates the SQLite WAL header plus the native-endian SHM wal-index/checkpoint state, then validates and applies only the active committed frame range.
- Runs `quick_check` and `integrity_check` before atomically promoting a snapshot.
- Supports contacts, sessions, unread/new messages, history, global search, statistics, Markdown export, group digest sources, Favorites, and Moments.
- Opens plaintext snapshot databases with SQLite `mode=ro` plus `PRAGMA query_only`; exports are atomic and refuse to replace an existing file unless `--overwrite` is explicitly supplied.

It does not use `wx-cli`, Frida, injection, hooks, drivers, Weixin UI automation, or process-control APIs.

## Supported environment

- Windows 10/11 x64
- Official Weixin 4.x
- Python 3.10+

Local validation was performed on Windows 11 with Weixin `4.1.13.7`. The memory scanner recognizes documented Tencent SQLCipher context geometry and fails closed if the ABI or page validation changes.

## Install

```powershell
py -3 -m venv "$env:LOCALAPPDATA\YichenWeChatVault\runtime"
& "$env:LOCALAPPDATA\YichenWeChatVault\runtime\Scripts\python.exe" -m pip install --upgrade pip
& "$env:LOCALAPPDATA\YichenWeChatVault\runtime\Scripts\python.exe" -m pip install -r ".\requirements.txt"
```

Runtime dependencies are exactly pinned. See `THIRD_PARTY_NOTICES.md` and `sbom.spdx.json`.

## Quick start

```powershell
python .\scripts\windows_vault.py diagnose
```

After the user explicitly approves reading Weixin process memory and storing the resulting database keys locally:

```powershell
python .\scripts\windows_vault.py capture --targets all --duration 240 --consent-read-process-memory
```

The user should manually visit the relevant Weixin areas while capture runs. Key buffers are protected while idle and are visible only during normal database operations. The tool does not create that activity itself.

Then the user manually exits Weixin and runs:

```powershell
python .\scripts\windows_vault.py refresh --mode full
python .\scripts\windows_vault.py status
python .\scripts\vault_cli.py sessions --limit 20 --format text
```

Run `python .\scripts\vault_cli.py --help` for all query commands.

An explicit export path is collision-safe by default. If the target already exists, choose a new path or deliberately add `--overwrite`; group digest-source filenames automatically receive a `-run-N` suffix on same-second collisions.

For later runs, `refresh --mode incremental` is the default. It still creates a new immutable generation and re-copies and hashes every encrypted DB/WAL/SHM set, but it reuses an integrity-checked plaintext database when the encrypted set and DPAPI key fingerprint are unchanged. Use `--mode full` to force decryption of every database.

## Private data layout

```text
%LOCALAPPDATA%\YichenWeChatVault\
├── keys\account.json # DPAPI ciphertext and non-secret metadata
└── vault\
├── current.json # updated only after required coverage succeeds
├── state\ # read-only query cursors
└── generations\<id>\
├── encrypted\db_storage\ # stable DB/WAL/SHM copies
├── decrypted\db_storage\ # plaintext local snapshot
└── manifest.json # hashes, WAL report, integrity result
```

Old generations are never deleted automatically. Exports default to `%USERPROFILE%\Documents\YichenWeChatVault\exports` and may contain plaintext personal data.

## Snapshot coverage

A Windows account can contain low-frequency auxiliary databases whose key is never used unless that feature has data. Promotion therefore follows the Mac skill's keyed-database behavior while keeping a stricter capability gate:

- Required when present: `contact/contact.db`, `session/session.db`, `sns/sns.db`, `favorite/favorite.db`, `message/message_resource.db`, every `message/message_N.db`, and every `message/biz_message_N.db`.
- Optional and explicitly disclosed when unavailable: search indexes and feature-specific stores such as chatbot, emoticon, media-cache, WeClaw, solitaire, and other auxiliary databases.

Every discovered DB/WAL/SHM set is still copied and listed in the manifest. A missing or invalid required database prevents promotion; an optional failure remains visible through `optional_missing_databases` and can be captured later without blocking the already verified Mac-equivalent query surface. `all_databases_decrypted` is true only when no optional database is missing.

## Why process-memory reading is necessary

Current Weixin protects SQLCipher key buffers while they are idle. During normal database page encryption/decryption, the existing buffer is briefly made usable and then protected again. This project samples the already-running process using the read-only Windows access rights `PROCESS_QUERY_INFORMATION | PROCESS_VM_READ`; a candidate is retained only when it verifies against the target database. It does not modify the process or invoke Weixin code.

This is sensitive behavior and therefore requires an explicit command-line consent flag in addition to the Skill's instruction to obtain current-task user approval.

## WAL correctness

Copying or decrypting only the `.db` file can lose committed updates that exist only in `-wal`. The snapshot pipeline validates the WAL header and both native-endian SHM wal-index header copies, including their checksums, salt, page size, committed `maxFrame`, and `nBackfill`. Frames at or below `nBackfill` are already present in the database, and frames beyond `maxFrame` are inactive storage that SQLite/WCDB may leave in the WAL file after a reset. Only the active range is checked for rolling checksum continuity, decrypted with per-page SQLCipher HMAC verification, and applied through its final commit. The result is truncated to the validated committed database size and must pass SQLite integrity checks.

The test suite constructs a real reserved-byte SQLite fixture, encrypts it page-by-page, writes a valid WAL-only update, and proves the merged plaintext database contains the update. It separately proves that a validated SHM reset ignores stale WAL capacity while a corrupted active frame without that boundary still fails closed. It also covers tampered page HMACs, DPAPI round trips, consent gating, safety API bans, and query/export behavior.

## Verification

```powershell
python -m unittest discover -s .\tests -v
python -m py_compile .\scripts\sqlcipher_codec.py .\scripts\wal_snapshot.py .\scripts\secret_store.py .\scripts\windows_memory.py .\scripts\windows_vault.py .\scripts\vault_cli.py
```

Privacy-safe local acceptance on Windows 11 / Weixin `4.1.13.7` discovered 19 DB/WAL sets, DPAPI-protected 11 strictly validated keys, promoted a full generation with every required capability database and 9 integrity-checked plaintext databases, and disclosed 10 optional gaps. Two of those optional gaps were FTS databases whose codec extension is unavailable in the standard Python SQLite runtime; the other eight had no active key. Contacts, sessions, history, Favorites, and Moments returned non-empty results through `mode=ro` / `query_only` connections. A following incremental generation integrity-checked and reused all 9 unchanged plaintext databases. No private values or account paths were published.

## Technical references

- [Tencent SQLCipher fork](https://github.com/Tencent/sqlcipher) — codec and cipher-context layout.
- [Tencent WCDB encryption documentation](https://github.com/Tencent/wcdb/wiki/C%2B%2B-%E5%8A%A0%E5%AF%86%E4%B8%8E%E9%85%8D%E7%BD%AE) — WCDB cipher-key behavior and defaults.
- [Tencent WCDB WAL repair parser](https://github.com/Tencent/wcdb/blob/master/src/common/repair/parse/Wal.cpp) — SHM `maxFrame`/`nBackfill` boundaries and rolling-checksum recovery semantics.
- [SQLCipher design](https://www.zetetic.net/sqlcipher/design/) — salt, page encryption, IV, and HMAC design.
- [SQLite WAL file format](https://www.sqlite.org/fileformat2.html#walformat) — header, frame, commit, and checksum semantics.
- [Microsoft `VirtualQueryEx`](https://learn.microsoft.com/windows/win32/api/memoryapi/nf-memoryapi-virtualqueryex) and [`ReadProcessMemory`](https://learn.microsoft.com/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory) — read-only process inspection APIs.
- [Microsoft DPAPI `CryptProtectData`](https://learn.microsoft.com/windows/win32/api/dpapi/nf-dpapi-cryptprotectdata) — current-user key protection.

See `PROVENANCE.md` for the implementation lineage and clean-version statement.
Loading