name: wechathook-recovery description: WeChatHook 注入丢失恢复——日志轮转致闸口误判 + force-stop 重新注入。触发词:WeChatHook not injected、hook 掉了、闸口误判、check_wechat_ready false but WeChat running。
category: wechat
WeChatHook Recovery — Hook 注入丢失恢复
症状
check_wechat_ready() 返回 ready: false,reason="WeChatHook not injected (no hook entries in LSPosed log)",但微信进程在运行(pidof com.tencent.mm 有 PID)。
诊断链
# 1. 确认微信进程在
su -c 'pidof com.tencent.mm'
# 2. 确认 lspd daemon 在
su -c 'pidof lspd'
# 3. 检查所有 verbose log(不是只查最新一个)
su -c 'grep -a "WeChatHook" /data/adb/lspd/log/verbose_*.log | tail -5'
# 4. 检查模块是否在 WeChat 进程内存中
su -c 'cat /proc/$(pidof com.tencent.mm)/maps | grep -i wechathook'
# 5. 检查 LSPosed 模块 DB
su -c 'sqlite3 /data/adb/lspd/config/modules_config.db "SELECT mid, module_pkg_name, enabled FROM modules;"'
常见原因
1. 日志轮转误判(最常见)
check_wechat_ready() 只检查最新的 verbose log。LSPosed 日志会轮转(~4MB 限制),"BroadcastReceivers registered" 记录可能在前一个日志中。闸口误判但 hook 实际在线。
验证:搜所有 verbose log 而不仅是最新:
su -c 'grep -a "BroadcastReceivers registered" /data/adb/lspd/log/verbose_*.log | tail -3'
如果找到记录 → 闸口误判,可以发(广播 result=0 验证)。
2. WeChat 进程重启后 hook 未重新注入
WeChat PID 变了(旧 PID 有 hook 记录,新 PID 没有)。LSPosed 在进程重启时未重新注入模块。
恢复步骤:
# Force-stop WeChat(触发 LSPosed 在下次启动时重新注入)
su -c 'am force-stop com.tencent.mm'
# 等待 3 秒
sleep 3
# 用户手动打开微信(Android 16 禁止程序化启动)
# 验证:
su -c 'pidof com.tencent.mm' # 新 PID
su -c 'grep -a "BroadcastReceivers registered" $(ls -t /data/adb/lspd/log/verbose_*.log | head -1) | tail -1'
# 看到新的注册记录 → 恢复成功
⚠️ force-stop 可能踢掉平板登录态。打开微信后如需重新登录,走 wechat-pad-login-repair。
症状 2:hook 在线、能发消息,但收信中断(2026-09-20 实测)
闸口返回 ready: true、pidof com.tencent.mm 有 PID、hook 日志活跃、发消息 HighLevel send OK,
但群里一条消息都收不到(微信 DB 不再新增 isSend=0 的行)。
判据(全部满足 = 收信链路断了,不是"群里没人说话"):
# 1. DB 级:最新若干条消息里,最后一条 isSend=0 的时间戳离现在多久(>1h 且所有群一致停滞即可疑)
cd ~/wechat-viewer && python3 ~/tmp/msg_liveness.py # 或直接 sqlcipher 查 message 表 ORDER BY createTime DESC
# 2. 逐个群比对当天消息数:正常群每小时 20-40 条,突然全体归零 ⇒ 不是用户安静
# 3. LSPosed 日志里找 hook 自己的异常堆栈(这是根因线索)
su -c 'grep -n "java.lang.Exception" /data/adb/lspd/log/verbose_*.log | tail'
# 栈里出现 com.example.wechathook.WeChatHook$N.afterHookedMethod + com.tencent.mm.storage.g9 /
# c01.w9.x / messenger.foundation / plugin.zero ⇒ hook 异常抛在微信的收信入库线程里
# 4. 排除法:CGI 心跳在不在(findersync/oplog/predownload_check)⇒ 排除"没网";
# dumpsys power 看 mLastWakeTime ⇒ 排除"锁屏 Doze 冻结"(屏幕点亮期间同样零收信就是真断)
2026-09-19 16:22 实例:9 个群(8×TGO + nmm)同时停在 16:22:29,之前 6 小时每小时 20–39 条;
convertTo 链路 33 条异常堆栈的最后一条 16:22:45;进程/闸口/发送/网络/CGI 全部正常。
即 hook 抛异常后微信的收信线程静默失效(发送链路不受影响)。
症状 2 的判据修正:别在夜间定罪(2026-09-20 08:00 轮实测,二次证伪)
初判「16:22 起收信全断」是错的,两轮实测都把它翻了:
- DB 级逐小时桶(
~/tmp/msg_liveness.py,走wechat_db直读 EnMicroMsg.db,绕开查看器 API 滞后)显示 09-19 傍晚/夜间一直在收:17:00=6、18:00=25、19:00=3、20:00=2、21:00=20、22:00=14、23:00=3、09-20 00:04=12、01:07=34。 ⇒ 01:19 轮那次数的是当时的 DB,看不到这些行 ⇒ 根因是「入库滞后」,不是「收信断」。 - ⚠️ 真实机制:微信写 EnMicroMsg.db 的入库可以滞后数小时(
createTime是发送时刻,但行是后来才写入的)。 钩子日志里最后一次收信写入 = 09-20 03:06:39–40,一批 5 条msgId=40096–40100、createTime却是 01:08 —— 正是「03:05 查当日 0 条 → 03:12 同命令 5 条」的来源(查看器 API 读数滞后只是同一现象的表层)。 ⇒ 「DB 里没有新 inbound 行」不构成「收信已断」的证据;必须过一段时间复读(≥2 次不同时刻)再判。 - 钩子日志同批仍伴随
afterHookedMethod异常栈(03:06:39–40,与写入同刻),但5 行消息照样写进去了 ⇒ 该异常发生在写库之后的回调里、未阻断写库;03:06:40 之后再无新异常、也无新写入 ⇒ 无新增证据。 - 查看器 API 会滞后(03:05 查当日 0 条 → 03:12 同命令 5 条)⇒ 单次读数不足以判「断」。
判据(否则一律不下结论):
su -c "sh ~/.hermes/skills/wechat/wechathook-recovery/scripts/hook_inbound_timeline.sh 8"
cd ~/wechat-viewer && python3 ~/tmp/msg_liveness.py # DB 级逐小时桶(权威)
# ① 逐小时桶「白天活跃时段也全程零」⇒ 可疑;「白天有、夜里稀」⇒ 正常
# ② 最后一次收信写入/最后一条 isSend=0 的 createTime 落在【夜里 01:00–08:00】且只静默这几小时 ⇒ **不定罪**
# ③ 钩子仍有 ANYCGI 事件 ⇒ 会话在线(但只说明「能连」,不说明「能收」)
# ④ **先确认设备已唤醒**(2026-09-20 09:00 轮新增):`su -c "dumpsys power | grep mWakefulness"` = `Dozing`
# 或 `su -c "dumpsys window | grep mDreamingLockscreen=true"` = 1
# ⇒ 微信在 Doze/锁屏期**不落库**,「DB 无新 inbound 行」与「真断」**不可区分**
# ⇒ 结论只能写「**不可判(设备未唤醒)**」,**禁**写成「收信仍断」;等设备点亮/唤醒后再复查
# (09-20 09:02 实测:全群静默 7.9h,但整轮 `mWakefulness=Dozing` ⇒ 当时任何结论都不成立)
- 必须跨日/多次复查(≥2 次不同时刻的同型读数)才可升级为真故障;升级前禁 force-stop。白天判据可复用
~/.hermes/skills/cron/cron-handoff-lifecycle/scripts/inbox_last_inbound.py(9 个群逐一给最后收信时刻与静默时长)。
处置(2026-09-20 当时的选择,供参考):
- 恢复大概率要重启微信(force-stop + 用户手动打开),但按
wechathook-do-not-break, force-stop 会丢平板登录、需要火星人扫码 ⇒ 无人值守的 cron 轮内不要自己动手。 - 正确做法:留存证据(DB 时间戳 + 异常堆栈 + 排除项)→ 发微信给 yibooo 请其拍板 →
写便条给后续窗口(
~/tmp/sched_note_<date>_<HHMM>.txt)。过期日报补跑办法见便条。
实战案例
2026-07-29:闸口报告 "WeChatHook not injected"。诊断发现:
- WeChat PID 30619(当前)≠ 29621(日志中 hook 注入的 PID)
- 最新 verbose log 有 999 条 WeChatHook 行但是旧 PID 的
- 新 PID 的 /proc/30619/maps 中无 wechathook → 根因:WeChat 被重启过,hook 未重新注入 → 修复:force-stop + 手动打开微信 → 新 PID 19525,BroadcastReceivers 重新注册 → 验证:发送 15 张图片全部 result=0