Skip to content

fzlzjerry/wechat-antirecall

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wechat-antirecall

macOS 微信 4 防撤回补丁工具。工具只会处理 patches.json 中已知的 WeChat 构建号;遇到未知版本会拒绝写入,避免猜地址造成损坏。

1、使用前建议先读完“快速开始”和“恢复备份”。安装会修改 /Applications/WeChat.app 内的二进制并重新签名,务必先完全退出微信。

2、遇到问题请先查看 安装故障排查(FAQ) 、使用故障排查(FAQ)、搜索 issues 解决

3、提issues 请备注 版本号、构建号、使用环境

快速开始

最安全的流程是:先确认版本,再 dry-run,最后用 release 可执行文件安装。

swift run wechat-antirecall versions --app /Applications/WeChat.app
swift run wechat-antirecall install --with-tip --dry-run --app /Applications/WeChat.app
swift build -c release
sudo .build/release/wechat-antirecall install --with-tip --app /Applications/WeChat.app

--with-tip 已弃用。4.1.10+(如 268849/268850)建议改用 --runtime-tip 自定义撤回提示(见自定义撤回提示),它通过运行时 hook 处理你 自己撤回的消息;--with-tip 仍可用,主要作为没有 runtime-tip 支持的旧版本后备。

安装时会在被修改的二进制旁边自动创建备份,例如:

wechat.dylib.wechat-antirecall-backup-20260505-143000

恢复命令见 恢复备份

支持版本

构建号 架构 支持能力 补丁目标
268575 arm64 静默防撤回、提示模式、多开、屏蔽更新 Contents/MacOS/WeChatContents/Resources/wechat.dylib
268596 arm64 静默防撤回、提示模式、屏蔽更新 Contents/Resources/wechat.dylib
268597 arm64 静默防撤回、提示模式、自定义提示、屏蔽更新 Contents/Resources/wechat.dylib
268599, 268601, 268602 arm64 静默防撤回、提示模式、自定义提示、屏蔽更新 Contents/Resources/wechat.dylib
268831 arm64 静默防撤回、提示模式、自定义提示 Contents/Resources/wechat.dylib
268849 arm64 静默防撤回、提示模式、自定义提示(内联 hook)、屏蔽更新(未回归) Contents/Resources/wechat.dylib
268850 arm64 同 268849(+1 热修,补丁点逐字节一致) Contents/Resources/wechat.dylib
268851 arm64 同 268849/268850(再 +1 热修,补丁点逐字节一致) Contents/Resources/wechat.dylib

可下载的微信 4.1.9 安装包:

微信 4.1.9 及 4.1.10 的防撤回补丁目标在 Contents/Resources/wechat.dylib,不是主二进制。工具会先单独重签被 patch 的 dylib,再重签整个 app,避免运行到被修改代码页时触发 Code Signature Invalid

选择模式

  • 静默防撤回:默认模式。不显示撤回提示,原消息保留在聊天中。
  • 提示模式(--with-tip,已弃用):保留微信原本的撤回提示,同时阻止删除原消息。 已弃用,建议在支持的版本上改用 --runtime-tip--with-tip 是纯字节补丁、 没有运行时 hook,对你自己撤回的消息会留下重复的撤回提示且无法处理; --runtime-tip 通过运行时 hook 处理这种情况。--with-tip 仍可使用,主要作为 没有 runtime-tip 支持的旧构建(如 268575268596)的后备。单独用 --with-tip 安装时会打印弃用提示。
  • 自定义提示:加 --runtime-tip。支持构建号 268597268599268601268602268831268849268850268851,会安装 libWeChatAntiRecallRuntime.dylib 并注入 LC_LOAD_DYLIB268597268831 复用微信自带的派发桩挂载;268849 没有派发桩,改用内联 hook(静态改写 parseRevokeXML 入口为 adrp/ldr/br,运行时再由 dylib 建 trampoline 并写回 跳转槽)。
  • 全版本多开:使用 clone 命令复制出独立 App,例如 WeChat 1.appWeChat 2.app。 这个流程不依赖 patches.json 的构建号地址。
  • 历史多开补丁install --multi-instance 仍保留,当前仅(微信 4.1.9) 构建号 268575 支持。
  • 屏蔽更新:加 --block-update。仅支持矩阵中标注“屏蔽更新”的构建号; 如果只想屏蔽更新,不改防撤回,用 --update-only

构建号 268831 目前支持静默防撤回、提示模式和自定义提示,不支持 --block-update--multi-instance 补丁。

构建号 268849(微信 4.1.10)支持静默防撤回、提示模式、--runtime-tip 自定义提示和 --block-update 屏蔽更新,不支持 --multi-instance 多开。

自定义提示(内联 hook)的安全特性与 --with-tip 不同,需要单独说明:

  • 该构建去掉了运行时 hook 所需的派发桩,所以 --runtime-tip 改用内联 hook。 安装时会静态改写 parseRevokeXML 入口(0x488c4c4)的 3 条指令为 adrp x16,SLOT; ldr x16,[x16]; br x16,SLOT 落在 wechat.dylib__DATA 尾部零填充区(0x952bf00)。运行时 dylib 在加载时建立 trampoline(重放原 3 条指令再跳回 0x488c4d0)并把 hook 函数指针写入 SLOT。
  • 入口改写和 dylib 注入由 --runtime-tip 一并完成,二者只会同时安装;缺少 dylib 时 SLOT 不会被赋值,函数会跳空指针导致崩溃。因此不要手动只打入口 补丁。restore 恢复 wechat.dylib 备份会同时撤销入口补丁、SLOT 与注入, 二者一起回滚。
  • hook 引擎本身(指令编码、trampoline、跳转槽派发)有单元测试覆盖;入口补丁 点已对真实二进制 dry-run 校验。但“撤回时确实走到自定义文案”需要真实撤回 事件才能确认,尚未在 268849 上做运行时回归——首次使用请用一条真实撤回消息 验证。

屏蔽更新的 9 处补丁点与已验证的 268601 对应的是同一组函数:其中 8 处除 地址重定位外字节完全一致,1 处(0x1d2a2c)为同一函数、入口之后有改动,但 补丁是在函数入口写 ret、改动部分被直接跳过。需要注意:4.1.10 另带 Sparkle (SPUUpdater)更新通道,本补丁不覆盖;更新拦截也尚未在 268849 上做运行时 回归。安装后请手动“检查更新”确认是否被拦截——一旦更新漏过并自动升级,会把 包括防撤回在内的所有补丁还原。

构建号 268850268851 都是 268849 的连续热修:全部 12 个补丁点与 SLOT 零填充 槽位都逐字节一致(已对各自的 wechat.dylib 逐地址核对原始字节),配置直接复用 268849,能力与注意事项相同。

--runtime-tip 会自动启用提示模式,不需要再加 --with-tip--update-only 不能与 --with-tip--runtime-tip--multi-instance 同时使用。

clone 生成的副本默认使用独立 CFBundleIdentifier,并移除 weixinwechatxweixin URL Scheme,避免系统回调随机落到副本。 每个副本通常需要单独登录。

历史 --multi-instance 补丁安装完成后,可以用下面命令启动新实例:

open -n /Applications/WeChat.app

也可以使用多开启动器:WeChatMulti

标准安装流程

1. 检查当前微信

# 退出当前打开的微信
pkill -x WeChat
swift run wechat-antirecall versions --app /Applications/WeChat.app

如果输出 current WeChat build is not supported by patches.json,不要继续安装。

2. dry-run

dry-run 不会改文件,用来确认补丁地址能命中。

swift run wechat-antirecall install --dry-run --app /Applications/WeChat.app
swift run wechat-antirecall install --with-tip --dry-run --app /Applications/WeChat.app
swift run wechat-antirecall install --with-tip --block-update --dry-run --app /Applications/WeChat.app
swift run wechat-antirecall install --update-only --dry-run --app /Applications/WeChat.app

需要历史 268575 多开补丁时:

swift run wechat-antirecall install --with-tip --multi-instance --dry-run --app /Applications/WeChat.app
swift run wechat-antirecall install --with-tip --block-update --multi-instance --dry-run --app /Applications/WeChat.app

3. 安装

安装前请先完全退出微信。不要在微信仍运行时写入补丁。

swift build -c release
sudo .build/release/wechat-antirecall install --with-tip --app /Applications/WeChat.app

常用安装组合:

sudo .build/release/wechat-antirecall install --app /Applications/WeChat.app
sudo .build/release/wechat-antirecall install --with-tip --app /Applications/WeChat.app
sudo .build/release/wechat-antirecall install --with-tip --block-update --app /Applications/WeChat.app
sudo .build/release/wechat-antirecall install --update-only --app /Applications/WeChat.app
sudo .build/release/wechat-antirecall install --with-tip --multi-instance --app /Applications/WeChat.app

patchinstall 的别名。完整参数可以运行:

swift run wechat-antirecall help

全版本多开 / App 克隆

clone 不修改原始 /Applications/WeChat.app,而是复制出独立 App bundle。 默认生成 2 个副本:

swift run wechat-antirecall clone --dry-run --app /Applications/WeChat.app --output-dir /Applications
swift build -c release
sudo .build/release/wechat-antirecall clone --app /Applications/WeChat.app --output-dir /Applications

默认结果:

/Applications/WeChat 1.app
/Applications/WeChat 2.app

默认副本身份:

com.tencent.xinWeChat.antirecall.clone1
com.tencent.xinWeChat.antirecall.clone2

常用参数:

  • --count <n>:设置副本数量,默认 2
  • --name-prefix <name>:设置副本名前缀,默认 WeChat
  • --keep-url-schemes:保留 weixinwechatxweixin URL Scheme。 默认会移除,避免 LaunchServices 回调冲突。
  • --replace:目标副本已存在时,把旧副本改名为时间戳备份后再创建。
  • --skip-resign:跳过重签名,只建议测试临时 fake app 时使用。

副本的自定义提示配置优先读取当前副本 bundle id 对应的容器 plist。 如果副本没有配置,不会回退读取原始 com.tencent.xinWeChat 的自定义提示短语。

自定义撤回提示

自定义提示由两部分组成:

  1. tip-phrase 写入当前用户的微信容器偏好配置。
  2. install --runtime-tip 把运行时 hook 安装进 WeChat app。

tip-phrase 必须用普通用户执行,不要加 sudo

swift run wechat-antirecall tip-phrase get
swift run wechat-antirecall tip-phrase preview "已拦截 {from} 于 {time} 撤回的一条消息" --from 张三
swift run wechat-antirecall tip-phrase set "已拦截 {from} 于 {time} 撤回的一条消息"
swift run wechat-antirecall tip-phrase reset

短语规则:

  • 最长 120 个字符。
  • 不能包含换行。
  • 不能包含 CDATA 结束标记 ]]>
  • {from} 会替换成发送者备注或昵称。
  • {time} 会替换成撤回时间,格式为 HH:mm
  • {content} 会替换成被撤回消息的内容:文字消息显示原文,图片/语音/视频/文件 等媒体消息显示类型占位符(如 [图片][语音])。建议把 {content} 放在短语 最后,例如 已拦截 {from} 于 {time} 撤回:{content}
  • 未配置时默认显示 已拦截一条撤回消息
  • 自己撤回的消息不会套用自定义提示,保持微信原生的“你撤回了一条消息 / You recalled a message”。自定义提示只用于拦截别人的撤回。

{content} 的取值与限制:

  • 撤回事件本身的 XML 不包含原消息内容,内容来自消息接收时缓存的预览。因此:
    • 只有在补丁版微信运行期间收到的消息才有缓存;微信重启后、或在 dylib 加载前 收到的消息被撤回时,{content} 取不到内容,会显示为空(连同前面的分隔符一起 省略,不会留下孤立的“撤回:”)。
    • 媒体只显示类型占位符,不含缩略图或文件名。
    • 过长的原文会被截断,保证整条提示不超过 120 字。
  • 目前 {content} 的内容捕获只在构建号 268849268850268851(微信 4.1.10)上提供; 其余 runtime-tip 版本仍可使用 {content} 占位符,只是取不到内容时按空处理。

配置文件位置:

~/Library/Containers/com.tencent.xinWeChat/Data/Library/Preferences/com.tencent.xinWeChat.plist

安装运行时 hook:

swift build -c release
.build/release/wechat-antirecall install --runtime-tip --dry-run --app /Applications/WeChat.app
sudo .build/release/wechat-antirecall install --runtime-tip --app /Applications/WeChat.app

268599268601268602268849268850268851 的 runtime hook 会先确认 XML 是 <revokemsg> 撤回事件, 再读取和改写撤回提示字段。视频、链接等非撤回 XML 不会进入撤回消息字段读取路径。

修改短语后请完全退出并重新打开微信。已启动的 WeChat 进程可能持有旧的 偏好缓存,重启后 runtime 会重新读取容器 plist。

调试探针

撤回调试探针默认关闭。只有在需要继续分析撤回 XML 或消息元数据时再打开。

swift run wechat-antirecall tip-phrase probe get
swift run wechat-antirecall tip-phrase probe on
swift run wechat-antirecall tip-phrase probe off

probe on 会把 msgTypenewmsgid、撤回提示和 XML 片段写入 macOS Console。日志可能包含聊天相关元数据,收集完请及时关闭。

重新安装或切换模式

如果已经安装过旧补丁,想从静默模式切到提示模式,或重新安装 runtime,可以加 --no-backup 覆盖当前补丁:

sudo .build/release/wechat-antirecall install --with-tip --app /Applications/WeChat.app --no-backup
sudo .build/release/wechat-antirecall install --runtime-tip --app /Applications/WeChat.app --no-backup
sudo .build/release/wechat-antirecall install --update-only --app /Applications/WeChat.app --no-backup

--no-backup 只是不再创建新备份,不能绕过权限、签名或 App Management 限制。

验证签名

微信 4.1.9 的常规防撤回或屏蔽更新:

codesign --verify --strict --verbose=2 /Applications/WeChat.app/Contents/Resources/wechat.dylib
codesign --verify --deep --strict --verbose=2 /Applications/WeChat.app

如果安装了 --multi-instance,还会修改主二进制,可额外检查:

codesign --verify --strict --verbose=2 /Applications/WeChat.app/Contents/MacOS/WeChat

安装 --runtime-tip 后可以额外检查 runtime dylib:

codesign --verify --strict --verbose=2 /Applications/WeChat.app/Contents/Resources/libWeChatAntiRecallRuntime.dylib
codesign --verify --strict --verbose=2 /Applications/WeChat.app/Contents/Resources/wechat.dylib
codesign --verify --deep --strict --verbose=2 /Applications/WeChat.app

恢复备份

恢复前请先退出微信。

sudo .build/release/wechat-antirecall restore \
  --binary Contents/Resources/wechat.dylib \
  --backup /Applications/WeChat.app/Contents/Resources/wechat.dylib.wechat-antirecall-backup-YYYYMMDD-HHMMSS \
  --app /Applications/WeChat.app

如果要恢复 --multi-instance 涉及的主二进制备份,改用:

sudo .build/release/wechat-antirecall restore \
  --binary Contents/MacOS/WeChat \
  --backup /Applications/WeChat.app/Contents/MacOS/WeChat.wechat-antirecall-backup-YYYYMMDD-HHMMSS \
  --app /Applications/WeChat.app

恢复 wechat.dylib 备份后,runtime 的 load command 会随备份一起消失。 Contents/Resources/libWeChatAntiRecallRuntime.dylib 即使还在目录里,也不会再被加载。

安装故障排查(FAQ)

1、权限不足

如果看到类似错误:

error: "wechat.dylib" couldn't be copied because you don't have permission to access "Resources".

不要直接用 swift run ... install 安装。请先构建 release,再用 sudo 执行 .build/release/wechat-antirecall

swift build -c release
sudo .build/release/wechat-antirecall install --with-tip --app /Applications/WeChat.app

--no-backup 不能解决权限问题,后续 patch 和重签名仍然需要写入 app bundle。

sudo 仍然写不进去

先确认 sudo 是否真的能写目标目录:

sudo sh -c 'id -u; touch /Applications/WeChat.app/Contents/Resources/.wechat-antirecall-write-test && rm /Applications/WeChat.app/Contents/Resources/.wechat-antirecall-write-test'

如果第一行输出 0,但 touch 仍然报 Operation not permitted,通常是 macOS 隐私权限拦截。到:

  • System Settings -> Privacy & Security -> App Management
  • 必要时再到 Full Disk Access

给当前运行命令的应用授权,例如 Terminal、iTerm、VS Code、Cursor 或 Codex。 改完后退出并重新打开终端,再重新执行安装命令。

2、微信仍在运行

工具提示 WeChat 仍在运行 时,请先完全退出微信再安装或恢复。这个检查是为了 避免旧进程在执行到被修改代码页时被 macOS 以 Code Signature Invalid 终止。

3、找不到 runtime dylib

如果 --runtime-tip 提示找不到 libWeChatAntiRecallRuntime.dylib,先运行:

swift build -c release

也可以显式指定 dylib:

sudo .build/release/wechat-antirecall install --runtime-dylib .build/release/libWeChatAntiRecallRuntime.dylib --app /Applications/WeChat.app

使用故障排查(FAQ)

1、打开 微信 频繁弹权限申请窗

设置 - 隐私与安全性 - 完全磁盘访问权限(或者重复弹窗的对应权限): 选择微信,点列表底部 - 删除,再点列表底部 + 选择 微信, 添加后会弹出生效提示窗,选择 退出并重新打开 生效

2、升级到 macOS 26 / 27 后,装了补丁的微信打不开(点了没反应 / 图标弹一下就退)

微信 单独授予完全磁盘访问权限即可:

设置 - 隐私与安全性 - 完全磁盘访问权限 - 点 + 选择 /Applications/WeChat.app - 打开开关 - 再开微信。 (即使现在打不开也能这样添加。打开后若提示,选 退出并重新打开 生效。)

原因:安装补丁会用 ad-hoc 签名重签微信,这会抹掉微信原本的签名身份和 entitlements。微信把数据存在 ~/Documents/app_data,而 Documents 是 macOS 的 TCC 保护目录。新版 macOS(26/27)启动时会拒绝这个“没有身份、没有 授权”的补丁版微信访问该目录,于是微信启动即退(终端里能看到它打印 lstat: No such file or directory 然后退出,没有崩溃报告)。授予完全磁盘 访问权限后,微信就能访问自己的数据目录,正常启动。

注意:

  • 补丁每次重签后主程序的 cdhash 会变,所以重新打补丁、或微信自身升级后, 可能需要把列表里的旧 微信 删掉重新添加一次(同上一条 FAQ 的删除再添加流程)。
  • 自检小技巧:如果在终端里直接跑 /Applications/WeChat.app/Contents/MacOS/WeChat 能起来、但双击/Dock 起不来, 基本就是这个权限问题——终端方式蹭到了终端自己的完全磁盘访问权限。

维护 patches.json

patches.json 来自 WeChatTweak / 社区 fork 的 Mach-O patch 思路,并补充了 微信 4 的防撤回、提示模式、多开和屏蔽更新目标。

示例:

{
  "version": "268596",
  "targets": [
    {
      "identifier": "revoke",
      "binary": "Contents/Resources/wechat.dylib",
      "entries": [
        {
          "arch": "arm64",
          "addr": "47647a0",
          "expected": "E00F0034",
          "asm": "7F000014"
        }
      ]
    }
  ]
}

说明:

  • binary 省略时默认是 Contents/MacOS/WeChat
  • expected 支持单个十六进制字符串或字符串数组。
  • 提示模式会同时接受原始字节和已安装静默补丁的字节,方便直接切换模式。
  • 显式请求 --with-tip--block-update 时,当前构建号必须提供 revoke-tipupdate 目标;工具不会静默降级。

参考

友链

About

antirecall for macos wechat 4 or later

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors