# WeChat 交互服务 — 发送与跟踪 本目录提供从 **Mac** 和 **Pixel 手机** 两个端点与微信进行交互的能力:发送消息、实时跟踪收发消息。 底层依赖自研的 **LSPosed/Xposed 模块**(`HermesWeChatSendMsg`),通过 Hook 微信内部 API 实现消息发送,并拦截日志实现消息跟踪。 --- ## 整体架构 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 用户 / hermes agent │ │ │ │ Mac 端 │ Pixel 手机端 (Termux/Debian) │ │ ┌──────────────────────┐ │ ┌──────────────────────────┐ │ │ │ wechat-sender.js │ │ │ android-wechat-sender.js │ │ │ │ wechat-tracker.js │ adb │ │ android-wechat-tracker.js│ │ │ └──────────┬───────────┘──────┘ └────────────┬─────────────┘ │ │ │ │ │ │ │ adb shell su -c │ su -c │ │ │ "content insert ..." │ "content ..." │ │ │ "cat /data/adb/lspd/..." │ "tail -f ..." │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Pixel 10 Pro Fold (Rooted) │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ │ │ HermesWeChatSendMsg (LSPosed/Vector Module) │ │ │ │ │ │ ┌──────────────┐ ┌──────────────────┐ │ │ │ │ │ │ │ ContentProvider│─────▶│ Broadcast Intent │ │ │ │ │ │ │ │ (Provider) │ │ com.hermes.wechat│ │ │ │ │ │ │ └──────────────┘ │ .SEND_MSG │ │ │ │ │ │ │ │ └────────┬───────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ▼ ▼ │ │ │ │ │ │ ┌───────────────────────────────────────────┐ │ │ │ │ │ │ │ 微信主进程 (com.tencent.mm) │ │ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ │ │ │ │ Hook 点: │ │ │ │ │ │ │ │ │ │ • ExtContentProviderBase.h() → 1 │ │ │ │ │ │ │ │ │ │ • ExtContentProviderBase.b() → true│ │ │ │ │ │ │ │ │ │ • AESUtil.b/a → 明文 wxid │ │ │ │ │ │ │ │ │ │ • MsgInfo.c1() → 消息日志 │ │ │ │ │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ │ │ │ │ 广播接收器 → NetSceneSendMsg │ │ │ │ │ │ │ │ │ │ u01.r1.a() → Builder → m1.a() │ │ │ │ │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ └───────────────────────────────────────────┘ │ │ │ │ │ └────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ ``` --- ## 模块原理 ### Hook 点(WeChat 8.0.72) | 目标类 | 方法 | 作用 | |--------|------|------| | `ExtContentProviderBase` | `h()` → return 1 | 绕过 appId + UID + 签名校验 | | `ExtContentProviderBase` | `b()` → return true | 绕过登录状态检查 | | `AESUtil` | `b(long)` → 返回原值 | 跳过联系人 ID 加密 | | `AESUtil` | `a(String)` → 返回原值 | 跳过联系人 ID 解密 | | `MsgInfo` (f9) | `c1(String)` | 监控消息内容变更,记录日志 | ### 消息发送调用链 ``` 外部请求 │ ├── content insert ──▶ ContentProvider ──▶ Broadcast (com.hermes.wechat.SEND_MSG) │ │ └── am broadcast ────────────────────────────┘ │ ▼ 微信主进程 BroadcastReceiver │ ┌────────────────────┴────────────────────┐ │ │ ▼ ▼ sendTextMessage() sendTextMessageDirect() (官方 ContentProvider) (反射内部 API) │ │ │ u01.r1.a(toUser) → Builder │ │ builder.e(content) │ │ builder.h(0) │ │ builder.a() → u01.m1 │ │ m1.a() // 必须在主线程调用 │ │ │ └─────────────────────────────────────────┘ │ ▼ 微信服务器 ``` ### 跨进程通信 模块代码运行在 **微信主进程**(通过 LSPosed 注入),ContentProvider 运行在 **模块 APK 自身进程**。两者通过 Android 广播通信: ``` hermes / adb shell content → 模块 Provider 进程 → 发送广播 │ 微信主进程(注入的模块) │ 广播接收器 → NetSceneSendMsg │ 微信服务器 ``` --- ## 文件清单 | 文件 | 用途 | 运行端 | |------|------|--------| | `wechat-sender.js` | 发送消息(adb) | Mac | | `wechat-tracker.js` | 跟踪消息(adb) | Mac | | `android-wechat-tracker-sqlcipher.js` | **主推** 跟踪消息(sqlcipher 轮询 DB) | Pixel | | `android-wechat-sender-frida.js` | **主推** 发送消息(Frida daemon 队列) | Pixel | | `android-wechat-sender.js` | 备用发送消息(am broadcast / content insert) | Pixel | | `android-wechat-tracker.js` | 备用跟踪消息(tail -f LSPosed 日志) | Pixel | | `auto-reply.js` | Pixel 自动回复 plugin(hermes-agent API) | Pixel | | `index.js` | 统一入口,自动检测环境 | 通用 | | `test-phone.js` | 手机端一键测试 | Pixel | | `deploy-to-phone.sh` | 推送到手机 | Mac | | `SKILL.md` | hermes agent skill 文档 | 通用 | | `wechat-reader.js` | 读取解密后的 SQLite DB | Mac | | `wechat-importer.js` | 导入联系人到知识图谱 | Mac | --- ## 前置条件 ### 1. 手机环境 - Pixel 10 Pro Fold(或其他已 root Android 设备) - Magisk 30.7+,Zygisk 已启用 - LSPosed/Vector 2.0+ 框架已安装 - 微信 8.0.72 - Termux 或 Debian chroot(hermes agent 运行环境) ### 2. 模块安装 ```bash # 在 Mac 上编译(详见 lsposed-wechat-sendmsg/README.md) cd lsposed-wechat-sendmsg ./gradlew assembleRelease # 签名并安装 adb install app/build/outputs/apk/release/app-release.apk # 在手机上: # 1. 打开 Vector Manager → 模块 → 启用 HermesWeChatSendMsg # 2. 作用域中选择「微信(com.tencent.mm)」 # 3. 强行停止微信,重新打开 ``` ### 3. 验证模块工作 ```bash adb shell su -c "logcat -s HermesWX:D | grep 'Send broadcast receiver registered'" # 应看到: [HermesWX] Send broadcast receiver registered ``` --- ## Mac 端使用 ### 发送消息 ```js const { sendTextMessage, sendBatch } = require('./wechat-sender'); // 单条 const r = await sendTextMessage('filehelper', 'Hello from Mac'); console.log(r); // { ok: true, uri: 'content://.../send/0' } // 批量 await sendBatch([ { toUser: 'filehelper', content: 'msg1' }, { toUser: 'wxid_xxx', content: 'msg2' }, ], 2000); ``` ### 跟踪消息 ```js const { WechatTracker } = require('./wechat-tracker'); const tracker = new WechatTracker(); tracker.on('message', msg => { console.log(`[${msg.type}] ${msg.talker}: ${msg.content}`); }); tracker.startPolling(3000); // 轮询模式 // tracker.startStream(); // 流式模式(更实时) ``` --- ## 手机端使用 ### 一键部署 ```bash cd server/services/wechat ./deploy-to-phone.sh /data/data/com.termux/files/home/hermes-wechat ``` ### 发送消息 ```js const { sendTextMessage, sendTextMessageBroadcast } = require('./android-wechat-sender'); // 方式1:ContentProvider(与 Mac API 一致) await sendTextMessage('filehelper', 'Hello from Pixel'); // 方式2:直接广播(更可靠) await sendTextMessageBroadcast('wxid_xxx', 'Test'); ``` ### 跟踪消息 ```js const { AndroidWechatTracker } = require('./android-wechat-tracker'); const tracker = new AndroidWechatTracker(); tracker.on('message', msg => console.log(msg)); tracker.startPolling(3000); ``` ### 运行测试 ```bash cd /data/data/com.termux/files/home/hermes-wechat node test-phone.js filehelper "hello from pixel" ``` --- ## 统一入口 ```js const wechat = require('./index'); // 自动检测环境:Mac 用 adb,Android 用 su console.log(wechat.platform); // 'mac' | 'android' // 发送 await wechat.sendTextMessage('filehelper', 'test'); // 跟踪 const tracker = new wechat.WechatTracker(); tracker.startPolling(3000); ``` --- ## API 参考 ### 发送 | 函数 | 参数 | 返回值 | 说明 | |------|------|--------|------| | `sendTextMessage(toUser, content)` | string, string | `{ok, uri, error}` | 通过 ContentProvider | | `sendTextMessageBroadcast(toUser, content)` | string, string | `{ok, error}` | 直接广播 | | `queryStatus()` | — | `{status, error}` | 查询发送结果 | | `sendBatch(messages, delayMs)` | Array, number | Array | 批量发送 | ### 跟踪 | 方法 | 说明 | |------|------| | `fetchRecent(n)` | 拉取最近 N 条 | | `startPolling(ms)` | 轮询模式 | | `startStream()` | 流式模式(tail -f) | | `stopPolling()` / `stopStream()` | 停止 | ### 事件 | 事件名 | 数据 | |--------|------| | `message` | `{type, talker, msgType, msgId, content, raw, timestamp}` | | `sendResult` | `{success, raw}` | | `sendRequest` | `{toUser, raw}` | | `error` | `Error` | | `close` | — | --- ## 故障排查 ### 模块层面 | 现象 | 原因 | 解决 | |------|------|------| | `content insert` 无响应 | 广播未注册 | 检查 logcat 中 `Send broadcast receiver registered` | | `Send result: false` | 内部 API 调用失败 | 确认 WeChat 版本匹配,检查类名混淆 | | `m1.a() return type` 异常 | 微信版本升级 | 重新反编译 APK,更新 `CLS_SEND_MSG_FACTORY` | | 模块未出现在 Vector Manager | APK 未签名 | 重新签名安装 | ### Mac 端 | 现象 | 原因 | 解决 | |------|------|------| | `adb: no devices` | 手机未连接 | 检查 USB 调试和 adb 授权 | | `adb exit 255` | 未 root | 确认 Magisk 已授权 adb shell 的 su | ### 手机端 | 现象 | 原因 | 解决 | |------|------|------| | `exit 1: permission denied` | 未 root | 检查 Magisk root 状态 | | `content: not found` | 不在 Android 环境 | 确保在 Termux 或指定 `/system/bin/content` | | 发送成功但对方没收到 | 微信没在前台 | 确保微信主进程存活 | | 跟踪不到消息 | 日志级别不够 | Vector Manager → 日志 → 设置详细级别 | | `Background execution not allowed` | Android 10+ 限制 | 使用 `content insert` 替代 `am broadcast` | --- ## 安全提示 - 本模块仅用于个人设备上的自动化测试和学习研究 - 微信账号存在被封风险,建议在测试用小号上操作 - 不要在群聊中高频发送消息,避免触发风控 --- ## 相关文档 - [LSPosed 模块 README](../../wechat_plain/scripts/lsposed-wechat-sendmsg/README.md) — 模块编译、安装、Hook 点详情 - [SKILL.md](./SKILL.md) — hermes agent 快速上手指南