0%

QQ8.1.3防撤回(Xposed模块)的原理

概述

开发一个适配QQ 8.1.3的防撤回插件,并显示撤回通知。

原理

1. 防撤回

设置com.tencent.mobileqq.app.message.QQMessageFacade.a(ArrayList.class, boolean.class)方法的返回值为空即可

1
2
//在beforeHookedMethod中执行
param.setResult(null);

2. 获取必要信息

上一个方法的第一个参数(ArrayList)内容(toString)形如:

1
[RevokeMsgInfo[istroop= 1, shmsgseq= 356, frienduin= 1234568, fromuin= 12345678 msguid= 0, time= 1568796904, senduin= null, longmsgid= 0, longmsgcount=0 longmsgindex=0]

istroop为1时,frienduin是群号,否则为好友qq。

在某个版本后,toString的结果中frienduin被截断,所以解析字符串的方法行不通了。

可以通过反射来获取需要的字段值。

3. 显示撤回提示

这个功能的实现比较复杂,需要获取和生成一些类对象。

首先通过反射获取到QQAppInterface实例(QQMessageFacade的字段)
然后调用QQAppInterface.getCurrentAccountUin方法获取自己的qq
再通过反射将RevokeMsgInfo字段取出,为构造撤回提示做准备。
然后通过MessageRecordFactory构造MessageRecord
然后使用ArrayList将其打包。
最终调用com.tencent.mobileqq.app.message.QQMessageFacade.a(ArrayList.class, int.class)方法来显示撤回提示。

具体可以参考QQ净化的防撤回实现

4. 进行一些操作

过滤

判断是否为自己撤回的信息,如果是则不做处理。

获取群成员名

通过调用ContactUtils的函数来获得。

为什么要适配

因为QQ版本不同,有些类名经过了混淆。
适配的关键在于找出混淆后的类名。
可反编译dex后,根据特征(字符串、函数参数、类结构等)查找smali。

防撤回功能涉及以下两个被混淆的类:

1
2
String MessageRecordFactory = "avay";
String ContactUtils = "azcx";

参考

QQUnrecalled
QQPurify