Skip to main content
Glama
README.md
# wxrpa

微信 Windows 版的操作库,给 agent 和脚本用。两半:

- **操作客户端**:发消息、发文件,走 `PostMessage` 投递,**不抢你的前台、不动你的鼠标键盘**,你用电脑的时候它也能跑。
- **读本地库**:微信 4.x 的数据库解包(SQLCipher 4),读会话、聊天记录、联系人、群成员。

为什么做这个:微信 4.0 起本地库从自研 wxSQLite3 换成了 SQLCipher 4,3.x 那批导出工具基本全废——本机实测 `pywxdump 3.1.46` 对着 `Weixin.exe 4.1.7.27` 直接回 `WeChat No Run`。而 UI 自动化那套(WeChatFerry/wcf 之类)大多依赖注入 DLL,版本一动就崩。所以这里走了另一条路:**能不碰客户端就不碰(读库),必须碰的时候只投递消息、不抢焦点(写)**。

## 装上

```
pip install -e .
```

依赖:pillow / numpy / opencv / rapidocr-onnxruntime(OCR)/ uiautomation / cryptography / zstandard。
要 MCP 再加 `pip install -e ".[mcp]"`。

环境:Windows 10/11,微信 **4.x**(实测 4.1.7.27),Python 3.10+。

## 发消息(不抢你的键鼠)

```
wxrpa send-text 文件传输助手 "开完会了"
wxrpa send-file 文件传输助手 D:\out\report.pdf
```

它会先滚动会话列表找到这个会话、点开、**回读会话标题核对**,对上了才输入和发送。核对不过直接中止,不会硬发。

发之前想确认它在干嘛:

```
wxrpa status
```

### 为什么默认不抢焦点

两条路都试过:

| 通道 | 结果 |
|---|---|
| `SendInput`(真鼠标键盘) | 能用,但要点亮前台、光标会跳,等于把你挤开 |
| `UIA InvokePattern` | **不能用**,而且它自己会把微信拉到前台 |
| `PostMessage`(投递 WM_LBUTTONDOWN / WM_CHAR) | **能用,前台和光标都不动** ← 默认走这条 |

有个绕不过去的限制:**微信的搜索结果是 Qt 的 popup 窗口,微信不是当前活动应用时它根本不显示**。所以搜索这条路在非侵入模式下废了,改成滚会话列表 + OCR 找人。找不到的(比如很久没聊、不在列表里)要么你手动打开一次,要么加 `--intrusive` 让它临时抢一下焦点去用搜索——那条路会短暂夺走你的输入焦点,默认关着。

## 读聊天记录(从数据库解包)

先有密钥(下一节),然后:

```
wxrpa chats --limit 20                  # 会话列表
wxrpa read 文件传输助手 --limit 50       # 聊天记录
wxrpa search 会议 --limit 20            # 搜关键词
wxrpa contacts 高 --limit 10            # 搜联系人
wxrpa decrypt                           # 只解密 + 建索引
```

`--json` 加在任何命令后面,输出给程序吃。

本机实测(一个真实账号):

```
stats: chats=387  contacts=5141  message_tables=363  messages=178866
解密+建索引 8.8 秒(含一个 260MB 的消息分片)
search "会议" -> 8 条,2.4 秒
```

解密出来的东西放在 `~/.wxrpa/<账号>/dec/`,是标准 SQLite,你可以直接拿别的工具开。

### 4.x 的库长什么样

逆向出来的,都对着真实库验过:

- 文件头 16 字节是随机盐,不是 `SQLite format 3`
- 每页 4096 字节,尾部 80 字节 = IV(16) + HMAC-SHA512(64)
- 第 1 页前 16 字节是明文盐,加密载荷从 offset 16 开始
- `enc_key = PBKDF2-SHA512(口令, 盐, 256000, 32)`
- `mac_key = PBKDF2-SHA512(enc_key, 盐 ⊕ 0x3a, 2, 32)`
- 页校验 = `HMAC-SHA512(mac_key, 密文载荷 ‖ IV ‖ 页号(小端4字节))`
- **每个会话一张表**,表名 `Msg_` + `md5(username)`,散在 `message_N.db` 分片里
- 消息体 `message_content` 是 zstd 压的(魔数 `28 b5 2f fd`)

源码在 `wxrpa/store.py`。

## 密钥从哪来

**这是目前唯一的粗糙处,先说清楚。**

微信存库的口令是**每台机器一份、不随库重写变化**的 32 字节。拿到它就能解开全部库(每个库的盐不同,口令相同)。

三条路:

1. **你有密钥** → `wxrpa --key <64位hex> ...`,或设 `WXRPA_KEY`,或写一行到 `~/.wxrpa/key.txt`。**这条现在是可用的**,本仓库所有数据库相关的实测都是走这条。
2. **`wxrpa key` 自动找** —— 会扫 `Weixin.exe` 内存找密钥特征。**4.1.x 上目前不工作**:老版本(4.0.x)内存里缓存的是 ASCII 形式的 `x'<64hex密钥><32hex盐值>'`,4.1.7.27 已经不再这么存了——本机扫了 1.3GB 内存,这个特征一次都没命中;换成扫结构特征指针(`key_v4.py` 那套)拿到 5666 个候选,两种模式全验过,一个都不对。所以这条路我留着代码但**不敢说能用**。
3. 拿不到就先用别的工具取一次(社区里那类工具就是干这个的),然后按第 1 条喂进来。

## 给 agent 用(MCP)

```
wxrpa mcp
```

工具:

| 名字 | 干什么 |
|---|---|
| `wx_status` | 微信进程和窗口 |
| `wx_send_text` | 发文本(非侵入) |
| `wx_send_file` | 发文件/图片 |
| `wx_read_screen` | 读**当前屏幕可见**的消息(OCR,兜底) |
| `wx_db_stats` / `wx_db_chats` / `wx_db_read` / `wx_db_search` / `wx_db_contacts` | 读本地库(要密钥) |
| `wx_moment_post` | 发朋友圈——**没实现**,见下 |

## 哪些做了,哪些没做

**实测通过**:

- **真的发出去过消息**,不是只跑到"准备发"。给「文件传输助手」连发多条,每次的复核方式都独立于发送逻辑本身:
  重新抓图找到这条文本的指纹,**并且左侧会话列表的预览也同步更新成这条消息**(双证)。
  实测单条耗时:开会话 2.8 秒 + 发送 27 秒;**操作前 / 中途 / 结束后三次对比前台窗口,全程没变**。
- `PostMessage` 点击和打字操作微信:窗口被别的应用完全盖住、微信不在前台时照样生效
  (这一点 `SendInput` 和 `UIA InvokePattern` 都做不到,后者反而会把微信抢到前台)。
- 会话列表滚动找人、点开、**回读会话标题核对**(核对不过直接中止,不发)。
- 4.x 数据库解密:session / contact / message_0(260MB)全部解出,HMAC 逐库校验通过。
- 结构化查询:387 会话 / 5141 联系人 / 178866 条消息,含 zstd 解压和 XML 富文本摘要。

**只是一半的**:

- WAL 合并:代码写完了,本机这几个库的 `-wal` 里没有已提交帧,**只跑到"解析正确、0 帧"**,
  没验到真合并。

**没做 / 没验**:

- **发朋友圈、点赞、评论**:能非侵入地进到朋友圈、读到动态列表(`mmui::SNSContentView`,原生视图不是 WebView),
  但**动态上的「赞 / 评论」要鼠标悬停才出现,投递的 `WM_MOUSEMOVE` 没把它悬出来**。
  没搞定之前不放接口出去 —— 一个"点了但不知道点没点上"的点赞太危险。
- **发语音消息**:PC 端没有"按住说话",要发语音气泡得把音频喂进虚拟录音设备再让微信录,
  这条链没搭。发普通音频文件请用 `send-file`。
- **发文件 / 图片**:`send_paths` 写好了(post 模式走 `WM_DROPFILES`),但**没实测**。
- **密钥自动提取**(见上一节)。
- 微信小版本升级后 `Msg_` 表的字段可能变,`real_sender_id → Name2Id` 这个映射也只在本机这个版本上验过。

## 边界和免责

- 只对**你自己本机、你自己账号**的数据有意义。库是加密的,但解出来就是明文聊天记录,别乱传。
- 操作客户端那半用的是消息投递,本质还是模拟用户操作。批量发消息被风控是使用者自己的事。
- 非官方项目,跟腾讯无关。微信一升级这些内部结构就可能失效——**失效了请提 issue,别在别人账号上试**。

MIT