Skip to content

支持微信 4.x 防撤回(build 268880 / 4.1.10,patch wechat.dylib) - #1039

Open
zengtianli wants to merge 1 commit into
sunnyyoung:masterfrom
zengtianli:feat/wechat-4.1.10-antirevoke
Open

支持微信 4.x 防撤回(build 268880 / 4.1.10,patch wechat.dylib)#1039
zengtianli wants to merge 1 commit into
sunnyyoung:masterfrom
zengtianli:feat/wechat-4.1.10-antirevoke

Conversation

@zengtianli

Copy link
Copy Markdown

背景

微信 4.x 把消息撤回逻辑从主二进制搬进了 Contents/Resources/wechat.dylib(strip 过的 C++ 内核)。当前工具按写死的路径 patch Contents/MacOS/WeChat,在 4.x 上打不到任何撤回代码,所以每个 4.x 构建号都报 unsupported。

本 PR 在不改动 3.8.x 行为的前提下加上 4.x 支持。

改动

  • Config.Target 新增可选 binary(bundle 相对路径,缺省 Contents/MacOS/WeChat);Config.Entry 新增可选 expected(打补丁前的原始字节,单个 hex 串或数组)。现有 config 条目都不带这两个字段 → 解析和行为与之前完全一致。
  • Patcher 写前校验字节:已是目标值 → 幂等跳过;与 expected 不符 → 直接报错拒写(打错版本不会被盲写搞坏),而不是无脑覆盖。
  • Command.patch 按 target 的 binary 分组分别打补丁resign 先单独 ad-hoc 签被改的 dylib,再 --deep 签整个 App,避免运行到被改代码页时 Code Signature Invalid
  • config.json 新增 build 268880(微信 4.1.10)revoke target:wechat.dylib 0x48831a0cbz w0 E00F0034b 7F000014

补丁点来源

parseRevokeXML 入口附近有条 cbz w0,w0 是"是否执行撤回"的判定;把它改成无条件 b(目标地址不变)后永远跳过删除逻辑,消息保留、静默无提示。

地址通过 parseRevokeXML 的几何特征定位(入口 stp 序言 + entry+0x270cbz w0 + entry+0xA04str x0,[x19,#0x168]),在整个 arm64 切片里唯一命中,经反汇编与原始字节逐一核对,并已在真实微信 4.1.10 上实测撤回被拦生效

逆向方法参考 fzlzjerry/wechat-antirecall

范围

本 PR 只加 268880 的防撤回。多开在 4.x 上没有可字节 patch 的开关(需整包复制 App),阻止更新未包含在内。其它 4.x 构建号可照 config 里的模式继续补(几何特征跨版本稳定)。

swift build -c release 通过。

… 4.1.10)

WeChat 4.x moved the message-revoke logic out of the main executable and
into `Contents/Resources/wechat.dylib` (a stripped C++ core). The existing
flow patches `Contents/MacOS/WeChat` by a hardcoded path, so it no longer
touches any revoke code on 4.x — every 4.x build reports "unsupported".

This adds 4.x support without changing 3.8.x behavior:

- Config.Target gains an optional `binary` (bundle-relative path; defaults
  to `Contents/MacOS/WeChat`). Config.Entry gains an optional `expected`
  (original bytes, single hex string or array).
- Patcher now verifies bytes before writing: idempotent skip if already
  patched, hard error on mismatch (refuses to corrupt the wrong build)
  instead of blind-writing.
- Command.patch groups targets by their binary and patches each; resign
  ad-hoc signs each patched nested dylib first, then `--deep` signs the app,
  to avoid `Code Signature Invalid` on the modified page.
- config.json: add build 268880 (WeChat 4.1.10) revoke target at
  wechat.dylib 0x48831a0 (cbz w0 `E00F0034` -> b `7F000014`).

All existing config entries omit `binary`/`expected`, so they decode and
behave exactly as before.

The 268880 address was located by the `parseRevokeXML` geometric signature
(entry `stp` prologue + `cbz w0` at +0x270 + `str x0,[x19,#0x168]` at
+0xA04) — a unique hit across the arm64 slice, verified by disassembly and
raw bytes, and confirmed working on a real 4.1.10 install. Reverse-
engineering method credit: github.com/fzlzjerry/wechat-antirecall.

Scope: only anti-revoke for 268880. Multi-open has no byte-patch on 4.x
(needs app cloning); update-block is not included here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant