README.md
Hermes WeChat SendMsg — LSPosed Module + AccessibilityService
针对 WeChat 8.0.72 的 Android 模块,包含两套发送实现:
- ✅
HermesAccessibilityService(生产路径) — 监听广播com.hermes.wechat.SEND_MSG,纯 UI 自动化:搜索联系人 → 输入文本 → 点发送按钮。当前唯一稳定可用的发送方式。 - ❌
HermesWeChatModule(已废弃,保留代码作记录) — LSPosed 入口,hookExtContentProviderBase/AESUtil后反射调用u01.r1.a → m1.a()。在 WeChat 8.0.72 上主线程 NetScene 提交持续 NPE 失败,Send result: true是误报,消息不进message表。
功能
- A11y 自动化发送(主路径) —
HermesAccessibilityService模拟用户在微信主界面搜索联系人、点进聊天、写文本、点发送按钮 - Auth Bypass / AESUtil / MsgInfo hook(历史遗留) —
HermesWeChatModule内的 LSPosed hook 对生产路径没有影响,可选保留 - ContentProvider 暴露 —
HermesWeChatProvider把content insert翻译成广播,主要给非 root 的调用方用
项目结构
lsposed-wechat-sendmsg/
├── app/build.gradle # App 模块构建配置
├── app/src/main/
│ ├── AndroidManifest.xml # 模块声明 + Provider 暴露
│ ├── assets/xposed_init # 模块入口类名
│ └── java/com/hermes/wechat/xposed/
│ ├── HermesWeChatModule.java # Xposed 入口:Hook + 广播接收器
│ └── HermesWeChatProvider.java # ContentProvider:外部 API
编译
Mac 本地编译
# 1. 安装 Java(如尚未安装)
brew install openjdk@17
export JAVA_HOME=/opt/homebrew/opt/openjdk@17
# 2. 安装 Android SDK
mkdir -p ~/android-sdk/cmdline-tools
cd ~/android-sdk/cmdline-tools
curl -O https://dl.google.com/android/repository/commandlinetools-mac-11076708_latest.zip
unzip commandlinetools-mac-11076708_latest.zip
mv cmdline-tools latest
export ANDROID_HOME=~/android-sdk
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
# 3. 接受许可并安装必要组件
yes | sdkmanager --licenses
sdkmanager "platform-tools" "build-tools;34.0.0" "platforms;android-34"
# 4. 编译 APK
cd lsposed-wechat-sendmsg
export ANDROID_HOME=~/android-sdk
./gradlew assembleRelease
# 输出:app/build/outputs/apk/release/app-release-unsigned.apk
# 签名:
keytool -genkey -v -keystore hermes-debug.keystore -alias hermes -keyalg RSA -keysize 2048 -validity 10000 -storepass hermes123 -keypass hermes123 -dname "CN=Hermes"
$ANDROID_HOME/build-tools/34.0.0/apksigner sign --ks hermes-debug.keystore --ks-pass pass:hermes123 --key-pass pass:hermes123 --in app/build/outputs/apk/release/app-release-unsigned.apk --out app/build/outputs/apk/release/app-release.apk
安装
A11y 路径(生产,必做)
- 安装本模块 APK:
adb install app/build/outputs/apk/release/app-release.apk - 启用 AccessibilityService(关键,最容易踩的坑):
bash adb shell "su -c 'settings put secure enabled_accessibility_services com.hermes.wechat.xposed/com.hermes.wechat.xposed.accessibility.HermesAccessibilityService; settings put secure accessibility_enabled 1'"或手动:设置 → 辅助功能 / 无障碍 → Hermes WeChat SendMsg → 启用 - 验证:
bash adb shell "dumpsys accessibility | grep -A3 Hermes" # 应看到 Bound services / Enabled services 都包含 HermesAccessibilityService
A11y service 会在重启、微信更新、本模块更新、用户在设置里关闭后失效,发送将静默失败——把启用检查纳入保活脚本。
LSPosed 模块路径(可选,目前无功能贡献)
如果同时希望 LSPosed hook 生效(虽然反射发送已坏,但 hook 本身对 A11y 没影响):
- 确保 Magisk 已安装且 Zygisk 已启用
- 安装 LSPosed Zygisk 版(或 Vector 2.0+)
- LSPosed Manager → 模块 → 启用 HermesWeChatSendMsg → 作用域选择 微信(com.tencent.mm)
- 强行停止微信,重新打开
使用
发送文本消息(推荐方式:直接广播)
adb shell "am broadcast -a com.hermes.wechat.SEND_MSG \
--es toUser yibooo \
--es toUserDisplayName 火星人 \
--es content '你好,这是测试消息'"
字段说明:
toUser— 接收者 wxid(如wxid_xxxxxx、yibooo、filehelper)。注意:A11y 流程不直接用这个值发送,但留着用于校验toUserDisplayName— 必须传:WeChat 里的 nickname(如火星人、文件传输助手)。A11y 用它来在搜索框里输入并定位联系人。如果只传 wxid 通常搜不到content— 消息内容
备用:ContentProvider insert
adb shell content insert \
--uri content://com.hermes.wechat.xposed.provider/send \
--bind toUser:s:yibooo \
--bind content:s:"你好"
这条路径会双广播(同时触发 LSPosed 反射 + A11y),LSPosed 那条会失败但不影响最终结果;A11y 这条把消息真正发出去。但因为 content insert 不传 toUserDisplayName,A11y 会用 toUser 当 nickname 去搜,搜不到的情况下发送失败——所以推荐用 am broadcast 显式传 displayName。
查询发送状态
adb shell content query \
--uri content://com.hermes.wechat.xposed.provider/status
返回 pending 或 true/false。
查看模块日志
# A11y 路径(看这个判断实际是否发送)
adb logcat -s HermesA11y:*
# LSPosed 路径(已废弃,仅供参考)
adb shell su -c "cat /data/adb/lspd/log/verbose_*.log | grep HermesWX | tail -20"
正常 A11y 成功日志:
HermesA11y: Received send request: to=yibooo searchName=火星人 content=...
HermesA11y: Root package=com.tencent.mm
HermesA11y: Already in correct chat, typing directly (或 "Not in chat, starting search")
HermesA11y: Setting chat text: ...
HermesA11y: Clicking send button (by ID)
HermesA11y: State reset
技术细节
进程拓扑
外部调用方(adb / hermes / shell)
│
│ am broadcast com.hermes.wechat.SEND_MSG
▼
Android system broadcast manager
│
├──────────────────────────┐
│ │
▼ ▼
HermesAccessibilityService HermesWeChatModule (LSPosed)
(模块 APK 进程) (注入在微信主进程)
│ │
│ AccessibilityNodeInfo │ 反射调用 u01.r1.a → m1.a()
▼ ▼
微信主进程 UI(前台) 【已坏:主线程 NPE 被 swallow】
│
▼
微信走自己的发送流程 → 服务器 → message 表
两个广播 receiver 并行触发,A11y 那条成功、LSPosed 那条静默失败。整个生产路径只依赖 A11y。
A11y 用到的 UI 节点(WeChat 8.0.72)
| 用途 | resource-id |
|---|---|
| 主界面搜索按钮 | com.tencent.mm:id/jha |
| 搜索输入框 | com.tencent.mm:id/d98 |
| 聊天输入框容器(FrameLayout,内含 EditText) | com.tencent.mm:id/bkk |
| 发送按钮 | com.tencent.mm:id/bql |
| 聊天页标题(用于校验进入了正确的会话) | com.tencent.mm:id/obn |
微信版本升级后这些 ID 会变化,需要重新 uiautomator dump 验证。
LSPosed Hook 点(历史记录,目前无生产作用)
| 目标类 | 方法 | 作用 |
|---|---|---|
ExtContentProviderBase |
h() → return 1 |
绕过 appId + UID + 签名校验 |
ExtContentProviderBase |
b() → return true |
绕过登录状态检查 |
AESUtil |
b(long) → 返回原值 |
跳过加密,明文传递 wxid |
AESUtil |
a(String) → 返回原值 |
跳过解密 |
MsgInfo (f9) |
c1(String) |
监控消息内容变更,记录日志 |
LSPosed 反射发送的调用链 u01.r1.a → builder.e → builder.h(0) → builder.a() → m1.a() 在 WeChat 8.0.72 上 m1.a() 主线程提交触发 NPE 失败。已确认无法修复(怀疑 WeChat 在 NetScene 链路加了反作弊校验)。代码仍保留在 HermesWeChatModule.java 中作为反编译记录。
故障排查
| 现象 | 可能原因 | 解决 |
|---|---|---|
am broadcast 返回 0 但 yibooo 没收到 / message 表无新行 |
最常见:A11y service 未启用 | adb shell "settings get secure enabled_accessibility_services",为 null 用上文命令重新启用 |
HermesA11y 日志 Root package=com.termux 后退出 |
广播触发时微信不在前台 | 先 adb shell am start -n com.tencent.mm/.ui.LauncherUI 再发 broadcast |
Search button not found |
当前不是 LauncherUI / nickname 错 | 确认 toUserDisplayName 是 WeChat 里实际的昵称 |
No clickable search result found |
搜不到该 nickname | 在微信里手动搜一下验证 |
[HermesWX] Send result: true 但 message 表没新行 |
LSPosed 反射路径的误报(已知 bug) | 忽略 LSPosed 日志,看 HermesA11y 日志判断真实状态 |
| 微信 UI 节点 ID 找不到(升级后) | WeChat 版本变化导致 resource-id 变 | adb shell uiautomator dump 后重新核对 |
| 模块未出现在 LSPosed Manager | APK 未正确安装或签名问题 | 重新安装模块 APK |
安全提示
- 本模块仅用于个人设备上的自动化测试和学习研究
- 微信账号存在被封风险,建议在测试用小号上操作