• 加了 hookGenericImgCdnSubmit 被动观察 v70.w.oj()(普通消息发图真正
    CDN 上传入口,已在 wechat-image-send-internals.md 逆向过),测试贴图号
    提交是否复用这条通道。真机确认:全程零触发,发布依旧真实成功
    (chksm 变化),第四个假说证伪。
    
    至此 js1.m.c()/bizh5webtransfer、m11.l0.d1()、wxartrappsvr/route、
    v70.w.oj() 四条最合理候选全部用真机数据排除。hookAnyCgiCapture 已是
    全局通用观察点,纯靠猜类名排除法收益递减,建议下次改查小程序沙箱
    自身 JS bridge 层(wx.uploadFile/wx.request 的 native 实现,appbrand
    包下,全新方向)。
    
    顺带记录一个流程坑:设备中途自己息屏落锁,wm dismiss-keyguard 对有
    密码锁的设备无效,需要用户物理解锁,不能也不该尝试绕过。
    yibo authored
     
    Browse File »
  • 改用 adb input tap + screencap 自主驱动"我的作品→贴图号→发表"全流程,
    不再需要用户手动操作,缩短每轮迭代成本。真机验证坑:可折叠机
    screencap 默认拿错屏幕,需显式 -d <display-id>。
    
    给 hookAnyCgiCapture 加了 r45.zt5(wxartrappsvr/route)专属 dump——
    之前通用扁平字段扫描器看不到它的 LinkedList<re7> payload,误判成
    "无内容"。真机确认这条路全是小程序 SDK 埋点上报(页面性能/console log
    转发/事件上报),跟提交发布无关,第三个候选证伪。
    
    意外发现:图片编辑步骤本身是个独立小程序(appid wx0b2ec076ec39c786,
    page_path pages/image_editor/image_editor),此前一直当作纯 H5
    webview——这是下次调查该跟进的新方向。核心提交调用仍未定位。
    yibo authored
     
    Browse File »
  • 改用文字/图片/语音发送同一套 LSPosed 机制(Zygote fork 时挂钩,非 Frida
    spawn/attach),彻底避开了此前两次搞坏微信主进程的问题——全程真机验证零
    故障。
    
    追踪链路 js1.m.c()(brandservice/webview transfer 汇聚点) → wire cgi
    bizh5webtransfer,真机确认全程只有只读态 mp.weixin.qq.com 调用,没有
    提交语义。进一步反编译 LuggageUploadMediaFileManager 追出图片走独立 CDN
    服务 m11.l0.d1(),同样零触发。两个最有希望的候选均被真机数据证伪,真正
    的提交调用点仍未定位,可能是完全独立的第三条路径。
    
    三个新增 hook(hookBrandservicePublishTransfer/hookAnyCgiCapture/
    hookBrandserviceCdnUpload)均已装进 WeChatHook.java,base+Tinker CL
    全覆盖,可复用于下一轮排查。
    yibo authored
     
    Browse File »

  • 红点通知需 atuserlist,深逆向未到底,跟原生引用气泡一起后面做。已确认:
    - 纯文字@不触发红点;atuserlist 不在 message 行(convertTo cv 无此列)
    - r0 第5参 obj≠msgSource(当它传会 NPE g9.q5,obj 是"消息key查f9")
    - 微信 UI 发送链路≠我们合成的 r0+z2.b:hook z2 自学习扫 atuserlist 字段零命中
    
    已部署脚手架(WIP,生产不传 at 无影响,自动回复照常):
    - SEND_MSG_INTERNAL 支持 --es at → 构造 msgsource
    - trySendWithRetry/sendViaHighLevel 加 msgSource 参数
    - hookAtDiscovery 自学习 z2 派发点 + sAtFieldPath 持久化(目前学不到)
    
    详见 memory wechat-group-at-atuserlist。⚠️ 重编译 hook 会强退微信=要重登,
    继续挖前一次想全要抓什么。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • 微信在 native __system_property_get 读 ro.product.model,绕过所有 Xposed
    Java hook,登录记录显示真机 "Pixel 10 Pro Fold" 触发预警。
    
    - hookDeviceSpoof: SystemProperties.get 改模式匹配 ro.product.*.model
      + hook Settings.{Global,Secure,System}.getString(device_name/bluetooth_name)
      + hook BluetoothAdapter.getName() + 诊断日志(定位真实读取源用)
      → 真机验证这些 Java hook 全零命中,证实微信走 native 读
    - 真正生效: wechat-model-spoof.sh 用 Magisk resetprop 改系统属性层
      (装到 /data/adb/post-fs-data.d/,开机持久化),native 读也拿伪装值
      → 登录记录变 "samsung SM-X700",Pixel 泄露消失
    - 代价:全机生效(getprop 也变),放弃"仅微信进程内",native 读无法 per-app
    
    详见 memory wechat-pad-login-device-spoof。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • 风控踢下线+实名验证的真正根因 = 登录状态下改设备指纹(不是平板登录本身)。实证:
    火星人在线时,测开关 33 秒内 Pixel→SM-X700→Pixel 翻转两次+重启两次 → 指纹横跳被踢。
    修正之前「平板登录固有高风险别做」的过重判断:登录后设备身份保持稳定即可持续。
    
    - DEVICE_SPOOF 从编译期常量改为运行时 flag 文件 /data/data/com.tencent.mm/files/.wcspoof
      (默认不存在=OFF=干净 Pixel,最低风控风险)。4 个 pad 登录 hook 全由该 flag 门控。
    - wechat_spoof_toggle.sh: 一键翻转 flag,【绝不自动重启微信】(早期自动 force-stop
      重启=登录态下身份突变=踢,已删)。改后由用户在没账号在线时手动重启微信生效,脚本大字警告。
    - 部署到设备 ~/ + ~/.shortcuts/(Termux:Widget 桌面按钮)。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    yibo authored
     
    Browse File »
  • WeChatHook.java pad-login 注释 + LESSONS.md 加「Hermes 修复交接」段,指向
    wechat-pad-login-repair skill(诊断+no-rebuild 修复+Case B 升级)。memory
    wechat-pad-login-device-spoof / hermes-pixel-mcp-integration 同步。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    yibo authored
     
    Browse File »
  • 订正旧结论:平板登录被拒根因是 **Pixel 机型不在微信平板白名单**(bk.B/Q 设备型号
    校验 + 服务端副设备机型校验),**与账号「体验资格」无关**——实测同一个小火子老账号
    (当初被归咎为体验资格过期那个)伪装成三星 Galaxy Tab S8(SM-X700) 后平板登录成功。
    
    4 个 hook(缺一不可):
    - hookDeviceSpoof(主进程): setStaticObjectField(android.os.Build,…)=samsung/SM-X700/
      gts8wifi + hook SystemProperties.get 返回 ro.product.*=同款 + ro.build.characteristics
      =tablet。DEVICE_SPOOF 开关。伪装仅微信进程内(getprop 仍显 Pixel)。
    - hookInTabletEnv: bk.A/B→true 兜底。
    - hookLoginHistoryUIInitView/hookLoginUIInitView: LoginPasswordUI/LoginHistoryUI.onCreate
      强制「以平板登录」按钮(字段 N) setVisibility(VISIBLE)+挂 m4 点击。
    
    关键 Tinker CL 坑: 登录 UI 跑在 Tinker CL,登录 hook 必须也注册到 sTinkerCL——否则
    onCreate hook「注册了但 0 次触发」(N VISIBLE 计数 0),退出登录后到 LoginPasswordUI
    (对的页)但没按钮。加 sTinkerCL 注册后日志出 N VISIBLE + m4 attached,按钮即现。
    
    rebuild stub 补 setStaticObjectField/getStaticObjectField。逆向+DEX 分布见
    wechat_pad_login/LESSONS.md。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • 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>
    yibo authored
     
    Browse File »
  • 修好派发:裸 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>
    yibo authored
     
    Browse File »
  • 按捕获的 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>
    yibo authored
     
    Browse File »
  • 真机 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>
    yibo authored
     
    Browse File »
  • 攻克图片发送最后一公里(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>
    yibo authored
     
    Browse File »

  • 逆向微信 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>
    yibo authored
     
    Browse File »

  • **WeChatHook.java — 语音发送四个关键 fix**:
    - 跳过 H():DB INSERT 在 r0 构造器内已完成,H() 只触发 CDN 上传,
      服务端拒绝后会删消息;skip H 彻底解决消息消失问题
    - status=4 双写:ContentValues + f9.r1(4) 内存字段同时写,
      防止 K(0) 回调再次 convertTo 时读到 status=1 覆盖回转圈
    - sDatabaseF9 精准捕获:在 convertTo() hook 里捕获入库的 f9 对象
      放入 r0.i,修复旧逻辑取第三个 f9(内容为空)导致点击崩溃
    - K(0) 而非 I(0):onSceneEnd code=0 时调成功路径 K 而非失败路径 I,
      修复红色感叹号问题
    - fromusername 兜底:sMyWxid 为 null 时回退硬编码 wxid
    
    **tts_voice_send.sh(新)**:
    一行命令 TTS 发语音:edge-tts → ffmpeg(16kHz PCM) → silk-wasm(SILK V3) → adb push → SEND_VOICE_INTERNAL
    
    **wechat_send.sh(新)**:统一 text / image / voice 三种发送模式的 CLI
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    yibo authored
     
    Browse File »

  • Hermes 重编 APK 时连踩三坑导致平板登录失效:
    1. 用 XposedBridgeApi.jar 而非 LSPosed legacy JAR 编译 → 所有 hook NoSuchMethodError
    2. xposed_init 放在 APK 根目录而非 assets/ → daemon 验证失败每次重启自动删模块 DB 注册
    3. 换了 keystore → INSTALL_FAILED_UPDATE_INCOMPATIBLE
    
    修复:从 wechathook_v2_signed.apk(正确 legacy JAR 编译)提取 DEX 复用,重打包含正确
    assets/xposed_init,debug.keystore 签名,fix_lspd_final.py 重建 DB 注册。
    2026-07-04 重启后验证平板登录恢复正常,所有 tablet hook 日志无 NoSuchMethodError。
    
    新增文件:
    - wechathook_v2_signed.apk: 黄金基准 APK(legacy JAR 编译,DEX 可复用)
    - do_not_break.md: 给 Hermes 的禁止事项清单
    - hermes_task.md: 已在顶部加 DO NOT BREAK 警告 banner
    - analyze_wechathook.py: DEX 字节码分析工具(Tinker patch)
    - rebuild_wechathook.sh / update_wechathook_db.sh: Mac 侧重建脚本
    - termux_build.sh: Hermes 的手机侧 build script(有编译 JAR bug,留作参考)
    - wechat_send_internal/: Hermes 对 WeChat 内部发送 API 的研究产出(进行中)
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    yibo authored
     
    Browse File »