-
三种消息在使用层齐了(文字/图片/语音全走内部 API 全合成): - wechat_send.sh voice: 弃用旧 SEND_VOICE_INTERNAL(hot-swap 相关),改走 SEND_VOICE_CGI 全合成。SILK 须 WeChat 进程可读——动态取 WeChat uid(stat /data/user/0/com.tencent.mm), stage 进 /data/data/com.tencent.mm/files/ + chown + restorecon(/sdcard EACCES、 root cp 进沙盒需正确 owner+ctx)。 - wechat_hook_send.py: 新增 send_voice_cgi_via_hook(同上 staging + 广播 SEND_VOICE_CGI)。 - android_mcp.py: send_wechat_voice 改调 send_voice_cgi_via_hook,docstring 更新为全合成。 - skill_wechat_send/SKILL.md: 语音段改写为 SEND_VOICE_CGI 全合成用法。 真机验证:wechat_send.sh voice + MCP send_voice_cgi_via_hook 均 status=sent + hook svrMsgId>0(uploadvoice cgi 服务器接受)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
sendVoiceViaCgi 之前只上传+投递给接收方,发送方本地无记录。补上: - cgi 前把 SILK 写到 voice2/msg_<voiceId>.amr(进程内写,以 WeChat uid,避开 外部 root cp 被 SELinux categories 挡)供本地回放。 - w11.r0 Object 构造器插入 f9 语音气泡(voicemsg XML + voiceId 经 hookF9ImgPathInjector 注入)。 - convertTo hook 新增 sVoiceCgiInsert 标志:cgi 路已上传+投递,强制 status=4 (已发送),否则发送方气泡永远转圈「正在发送中」(hot-swap 路仍不强制,靠 H())。 真机 filehelper 对比验证:16:17(修复前)绿气泡转圈无时长 → 16:22(修复后)干净 「3" 语音条」已发送。接收方(火星人/Mac)收到能播 + 发送方本地正常显示 = 端到端 双向闭环。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
修好派发:裸 z2.b(g) 不 wire 回调 → 场景永不完成、dv6 空。正确派发 = modelbase.i.l()(注册响应消费者 d + 返回 pq5.g deferred)+ pq5.g.l(timeoutMs) 终端订阅触发 cgi。加 sVoiceCgiKeepAlive 强引用防 deferred 弱持有的 i 被 GC。 真机 filehelper 验证(纯合成,无录音/无 hot-swap): RESP try=1 svrMsgId(11)=6727180359918674774 VOICECGI-RESULT errType=0 errCode=0 errMsg=null respClass=r45.dv6 = 服务器接受请求(errCode=0) + 分配 msgId(>0) = 投递成功。 诊断 hook hookVoiceCgiResult(modelbase.i onSceneEnd 按签名定位) 确认 errCode。 广播 SEND_VOICE_CGI --es to --es src_path <SILK> --ei duration。SILK 须 WeChat 进程可读(用其自身 voice2 文件或 chown 到 WeChat uid;/sdcard 会 EACCES)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
按捕获的 wire 协议实现全合成语音(无录音、无 hot-swap): - 读 SILK → 按 6000 字节分块 → 每块建 r45.cv6 请求 pb([0]self [1]talker [2]offset [3]len [4]"newSendVoice_"+voiceId [6]dur [7]cu5(SILK切片) [8]end [11]msgsource [12]=4)→ 经 modelbase.o 13参构造器(绕过 modelbase.l 字段名 base≠tinker 不匹配) → modelbase.i.p(o)(按签名定位) → scene modelbase.g(m1) → z2.b(scene) 入队(同文字发送)。 - 广播 SEND_VOICE_CGI --es to --es src_path <SILK> --ei duration。 真机 filehelper 测试:反射全部解析成功,scene=com.tencent.mm.modelbase.g, z2.b 提交 1 块无异常(silk=2593B dur=2000)。投递确认待(设备屏幕 doze + 需第二账号);已知待补:[15] long 字段省略、本地 f9 气泡未插、cgi 响应 getLong(11) 未校。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
真机 hook 追踪确认本机语音走 jg0.x.w 内联 cgi 分支(非 CDN 引擎 addSendTask, 那是 send_use_cdn_upload=1 的机器才走)。内联路可 z2.b 全合成,复用文字同队列。 新增追踪 hook: - hookCdnTrace: h2.d(addSendTask)/l1.keep_onUpload*/jg0.x.u — 证实 CDN 路本机不触发。 - hookVoiceCgiCapture: hook modelbase.l.a() 过滤 uploadvoice,按类型定位字段(base≠ tinker 名,NoSuchFieldError 教训),dump 请求 pb r45.cv6 全字段。 捕获的 wire 协议(cgi /cgi-bin/micromsg-bin/uploadvoice, cmdid 127, req cv6/resp dv6): [0]self [1]talker [2]netOffset [3]本块SILK长 [4]"newSendVoice_"+voiceId [6]时长ms [7]custom cu5(SILK字节) [8]endflag [11]msgsource [12]=4 [15]long 分块=6000字节/片,末块 end=1 响应 dv6.getLong(11)>0=服务器msgId=投递。 scene modelbase.g extends m1 → z2.b(scene) 同文字。modelbase.o 有公开构造器可绕 过 modelbase.l 字段名不匹配。 下一步: sendVoiceViaCgi 实现分块 cgi + z2.b 全合成。详见 memory + WECHAT_SEND_API。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
图片 CDN 上传打通后,把发图能力接进使用层: - skill_wechat_send/SKILL.md: 图片段 🟢→✅,给出 SEND_IMAGE_INTERNAL 广播 + wechat_send.sh 封装用法,标注真机验证(filehelper + 火星人全图收到)。 - wechat_send.sh image: 弃用旧的 share intent + 手动选联系人(UI 模拟), 改走内部 API 广播 SEND_IMAGE_INTERNAL;先 stage 到 /sdcard 保证 WeChat 进程可读,再 fire-and-forget 到 <wxid>。真机验证 oj()+CDN submit 均 DONE。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
攻克图片发送最后一公里(LSPosed,微信 8.0.74,真机验证全分辨率送达): 根因: b80.u.oj(o70.k) 只做「插消息 f9 + 插 ImgInfo b0 + 建缩略图」并 返回 List<o70.l> CDN 上传描述符,自己不提交 CDN。旧代码拿到 res 就丢掉 list → 上传永不触发(缩略图渲染但全图转圈)。真实编排 pe5.f.a 才循环 list 逐图提交(b80.s 只是 prebuild service checkPreBuildImg,不含 oj)。 补上第二步(照搬 pe5.f.a): oj() 后对每个 o70.l: cdnSvc = n0.c(xs.d1.class) // v70.w MsgImgFeatureService g = new r70.g(l.e, compress, c01.z1.r()/*self wxid*/, talker, k70.i0{a=3}) cdnSvc.oj(g, l) // → 启动 CDN 上传协程 e80.c 真机: oj() DONE res=size=1 + CDN submit DONE items=1,无异常;filehelper 收到消息点开是全分辨率原图(有原图+保存按钮,不再转圈)。 坑: v70.w.oj 内部走 ViewModelProvider.get 须主线程调(广播 receiver 本就在 主线程);jadx 字段名末位字母=真实 dex 字段;XposedHelpers stub 无 getLongField 用原生反射。逆向靠拉 Tinker dex + jadx --single-class。 产物: WECHAT_SEND_API.md §3 完整两步实现 + API 表;backups 源码快照。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
逆向微信 8.0.74 内部发送 API(LSPosed,无 UI 模拟): - 文字(中英文): w11.r0(type=1) Object-ctor + z2.b NetSceneQueue,真机验证送达。 中文走 text_b64 base64 通道避免 shell 损坏 UTF-8。避开 dk5.s5.Ni(实为发名片)。 - 图片: hook 真实发送抓 o70.h/o70.k/o70.i 原样重放,攻克消息构建—— 能建 type=3 图片消息、缩略图渲染、进 pt0.e0 管线;全图 CDN 上传是最后一公里。 - 语音: jg0.x.w hot-swap(真机验证投递)。 - wxid 解析: EnMicroMsg.db SQLCipher 解密(key=MD5(imei+uin)[:7])查 rcontact。 - 坑: 真实代码在 Tinker 补丁 CL(hook 用 sTinkerCL);force-stop 不 flush 加密 WAL。 产物: WECHAT_SEND_API.md(完整逆向文档)+ skill_wechat_send/SKILL.md + backups/(WeChatHook.java 快照 + 构建/发送脚本)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>