AnonForward

AnonForward 为 QQ/TIM 多选转发菜单增加一次性的“匿名转发”,同时提供 QAuxiliary 外部插件和独立 LSPosed 模块。

当前实现采用上传前改写:QQ 先生成完整的 SsoSendLongMsg,共享核心在发送前改写其中的 MultiMsg Protobuf。图片、表情和嵌套 action 保持原始结构,身份与可追踪字段被替换。QQNT 入口只处理轻量的 MultiMsgInfo 列表,外层 JSON、XML 及 zlib LightApp 统一在发包线程改写。

项目结构

  • core:协议解析、匿名状态机、菜单注入和所有 Hook 逻辑,不依赖 QAuxiliary 或 Xposed API。
  • app:QAuxiliary 外部插件入口和配置应用。
  • standalone:独立 LSPosed/Xposed 入口、HookBridge 实现和模块说明应用。
  • qaux-api-stubs:只供 QAux 插件编译,使用 compileOnly,不会进入独立模块。

当前处理内容

  • senderUin 替换为 1094950020
  • senderUid 替换为 u_B-xbHgFtPzMTjvfvZNVuqw
  • 群号替换为 284840486
  • 同一身份在一次转发中使用同一“匿名用户N”昵称
  • 结构化 At 转换成普通文本 @匿名用户N
  • srcMsg 保留正文与媒体,替换发送者、消息 ID 和序号
  • 清空 forward.avatar 等头像字段
  • 递归处理嵌套 MultiMsg、压缩 XML 与 LightApp JSON
  • 外层 com.tencent.multimsg 预览同步匿名化
  • 清理气泡、字体、挂件、VIP/群荣誉及扩展昵称、名片、头衔等元数据
  • 移除扩展消息 ID,替换上传记录的 msgRandom;引用和嵌套副本使用一致的合成索引

构建

项目需要 JDK 17+ 与 Android SDK。一次构建两份产物:

.\gradlew.bat assembleProducts

APK 输出:

outputs/AnonForward-QAux-<版本>-debug.apk
outputs/AnonForward-LSPosed-<版本>-debug.apk

更新版本

版本号统一保存在根目录 gradle.properties:

anonVersionCode=<递增整数>
anonVersionName=<语义版本号>

使用脚本设置新版本;省略 VersionCode 时会自动加一:

.\tools\set-version.ps1 -VersionName 0.3.3

更新后立即构建两份 APK:

.\tools\set-version.ps1 -VersionName 0.3.3 -Build

QAuxiliary 外部插件

  1. 安装 AnonForward-QAux-*.apk。
  2. 打开“匿名转发”应用,复制包名和证书 SHA-256。
  3. 在 QAuxiliary 的“实验性功能 → 加载外部插件”中添加包名和证书SHA256,均在应用首页有显示
  4. 启用外部模块并彻底重启 QQ。
  5. 在 QQ 中多选消息并点击转发。
  6. 在“逐条转发”“合并转发”之后选择“匿名转发”。该入口会复用原合并转发流程,并只匿名化本次操作。

独立 LSPosed 模块

  1. 安装 AnonForward-LSPosed-*.apk。
  2. 在 LSPosed 中启用“匿名转发(LSPosed)”。
  3. 作用域选择 QQ 或 TIM。
  4. 强行停止并重新启动目标应用。
  5. 在多选转发菜单中使用“匿名转发”。

独立模块可以与 QAuxiliary 本体同时启用。请勿同时启用 QAux 外部插件版本和独立 LSPosed 版本;核心包含进程级所有者保护,检测到重复运行时会跳过后加载的一份。

调试

日志同时写入 Android Logcat 和 LSPosed 模块日志:

AnonForward

关键成功日志:

AnonForward hooks installed
Intercepted QQNT forward entry
Observed native SSO command=trpc.group.long_msg_interface.MsgService.SsoSendLongMsg
Sanitized SsoSendLongMsg bodies=N
Sanitized outgoing multimsg Ark preview
Replaced outer multimsg preview

当前限制

媒体资源

媒体元素目前按原始数据保留,因此原始文件哈希和 QQ 媒体资源标识仍可能关联到原消息。强匿名模式需要增加“下载后重新上传媒体”的流程(不过个人认为这些内容需要拥有QQ内部权限的人才能倒查出来源,所以不影响使用)。

Releases

v1.0.3

Stable

9/16/2026, 12:28:09 PM

1.0.3

  • 补齐外层匿名卡片在新增、更新和普通消息历史读取中的本地预览保护。
  • 归一化 Ark/XML 的标题、摘要、提示文本和预览昵称,保留资源定位及外层发送/接收信息。
  • 对已标记匿名记录的 MultiForwardActivity 定向处理页面标题和 key_chat_name。
  • 增加外层卡片作用域、重启读取、MsgsRsp、预览幂等和回调异常测试。

1.0.2

  • 清理上传记录中的气泡、字体、VIP/挂件元数据及 ExtraInfo 的昵称、名片、头衔和通知文本。
  • 清理本地匿名副本的 VAS、群荣誉和附加账号信息;保留非装扮属性和媒体对象。
  • 移除 ElemFlags2 中遗漏的原消息 ID,替换协议 msgRandom,并统一引用与嵌套副本的合成索引。
  • 对重复的敏感单值字段去重;敏感结构解析失败时阻止整条上传,避免部分匿名化后继续发送。
  • 增加协议隐私、引用关联、媒体保真、样式副本和历史原始包回放测试。

Assets

2