mirror of
https://github.com/jackwener/wx-cli.git
synced 2026-10-08 07:45:45 +00:00
Lays down the skeleton for聊天附件 (chat attachment) extraction. This commit
introduces the `attachment` module with:
- `attachment_id`: opaque base64url(json) round-trip handle for CLI/IPC. Carries
`(chat, local_id, create_time, kind)` — `local_id` alone is not unique
(实测同 chat 内最多 7 条同 local_id 的记录), so create_time is required for
disambiguation.
- `decoder/`: dispatch by 6B header magic. Three branches:
- `V2_MAGIC` → AES-128-ECB + raw + XOR (need image AES key)
- `V1_MAGIC` → AES-128-ECB with fixed key `cfcd208495d565ef` (= md5("0")[:16])
- else → legacy single-byte XOR with magic auto-detect
Manual ECB + PKCS7 unpad to avoid pulling in another crate.
- `resolver`: `message_resource.db` lookup chain
`username → ChatName2Id.rowid → MessageResourceInfo.packed_info → md5`
+ on-disk `.dat` selection (full > _h > _t) under
`<wxchat_base>/msg/attach/<md5(chat)>/<YYYY-MM>/Img/<md5>[_t|_h].dat`.
Honors `message_local_type % 2^32` to strip the high flag bits, and orders by
`message_create_time DESC` to handle local_id reuse.
- `image_key/`: stub trait + macOS / Windows placeholders. To be filled by
codex with the V2 image key extraction (kvcomm + brute-force on macOS, memory
scan on Windows).
V1 decoder ships with 6 unit tests covering every supported magic + the BMP
extra validation; resolver ships with packed_info parser + dat-file selection
tests; v2 decoder ships with header validation tests. 21 tests pass.
`cargo check` and `cargo check --target x86_64-pc-windows-gnu` both clean.
81 lines
1.6 KiB
TOML
81 lines
1.6 KiB
TOML
[package]
|
||
name = "wx-cli"
|
||
version = "0.1.11"
|
||
edition = "2021"
|
||
description = "WeChat 4.x (macOS/Linux) local data CLI — decrypt SQLCipher DBs, query chat history, watch new messages"
|
||
license = "Apache-2.0"
|
||
repository = "https://github.com/jackwener/wx-cli"
|
||
keywords = ["wechat", "sqlcipher", "decrypt", "cli"]
|
||
categories = ["command-line-utilities"]
|
||
readme = "README.md"
|
||
|
||
[[bin]]
|
||
name = "wx"
|
||
path = "src/main.rs"
|
||
|
||
[dependencies]
|
||
# CLI
|
||
clap = { version = "4", features = ["derive"] }
|
||
|
||
# 异步
|
||
tokio = { version = "1", features = ["full"] }
|
||
|
||
# 序列化
|
||
serde = { version = "1", features = ["derive"] }
|
||
serde_json = "=1.0.140"
|
||
serde_yaml = "0.9"
|
||
|
||
# SQLite
|
||
rusqlite = { version = "0.31", features = ["bundled"] }
|
||
|
||
# 加密
|
||
aes = "0.8"
|
||
cbc = { version = "0.1", features = ["alloc"] }
|
||
hmac = "0.12"
|
||
sha2 = "0.10"
|
||
pbkdf2 = "0.12"
|
||
|
||
# 解压
|
||
zstd = "0.13"
|
||
|
||
# 错误处理
|
||
anyhow = "1"
|
||
|
||
# 时间
|
||
chrono = { version = "0.4", features = ["serde"] }
|
||
|
||
# 跨平台路径
|
||
dirs = "5"
|
||
|
||
# MD5 (联系人表名 Msg_<md5>)
|
||
md5 = "0.7"
|
||
|
||
# 附件 ID 编码(base64url)
|
||
base64 = "0.22"
|
||
|
||
# 正则表达式
|
||
regex = "1"
|
||
roxmltree = "0.20"
|
||
|
||
# IPC Windows named pipe(Unix 直接用 tokio::net::UnixListener)
|
||
[target.'cfg(windows)'.dependencies]
|
||
interprocess = { version = "2", features = ["tokio"] }
|
||
|
||
[target.'cfg(unix)'.dependencies]
|
||
libc = "0.2"
|
||
|
||
[target.'cfg(target_os = "windows")'.dependencies]
|
||
windows = { version = "0.58", features = [
|
||
"Win32_System_Diagnostics_Debug",
|
||
"Win32_System_Diagnostics_ToolHelp",
|
||
"Win32_System_Threading",
|
||
"Win32_Foundation",
|
||
"Win32_System_Memory",
|
||
] }
|
||
|
||
[profile.release]
|
||
opt-level = 3
|
||
lto = true
|
||
codegen-units = 1
|
||
strip = true
|