概述
之前写过一篇QQ8.1.3防撤回原理,每次更新后,都需要适配被混淆的类名。
今天更新了最新版QQ(8.8.17
),发现使用到的类名都未被混淆,不过包结构有了一定变化(可能是重构了?),需要重新适配。
于是尝试使用objection
分析撤回提示的实现,并编写Xposed
模块。
防撤回
与之前一样,设置com.tencent.mobileqq.app.message.QQMessageFacade.a(ArrayList, boolean)
方法的返回值为空即可
显示撤回提示
定位到关键类com.tencent.mobileqq.msg.api.impl.MessageFacadeImpl
,其中提供有QQMessageFacade
类的接口,包括删除消息、增加消息等功能。
其中增加消息有以下两个函数:
1 | // com.tencent.mobileqq.msg.api.IMessageFacade |
通过以前对旧版qq的分析可知,撤回消息的流程为:删除本地消息记录-创建撤回提示-增加撤回提示到本地
因此,使用objection
hook addMessage
函数,打印参数和调用栈:
1 | android hooking watch class_method com.tencent.mobileqq.msg.api.impl.MessageFacadeImpl.addMessage --dump-args --dump-backtrace |
首先使用另一个qq发送消息,发现调用的是第一个函数addMessage(MessageRecord, String)
使用另一个qq撤回消息,日志如下:
撤回私聊消息
1 | com.tencent.mobileqq.msg.api.impl.MessageFacadeImpl.addMessage(Native Method) |
撤回群聊消息
1 | com.tencent.mobileqq.msg.api.impl.MessageFacadeImpl.addMessage(Native Method) |
注意到无论是撤回私聊还是群聊消息,都是调用com.tencent.mobileqq.msg.api.impl.MessageFacadeImpl.addMessage(com.tencent.mobileqq.data.MessageRecord, java.lang.String, boolean, boolean, boolean, boolean)
,(参数值为false,true,true,false
):
而该方法最终调用的是BaseQQMessage.a(MessageRecord,String,boolean,boolean,boolean,boolean)
函数
因此,我们构造完MessageRecord
后,依葫芦画瓢,调用该函数即可。
PS:此处是为了与正常流程保持一致,其实根据另一个addMessage
函数,调用BaseQQMessage.a(MessageRecord,String)
也是可以的。
无限打开闪照
定位到关键类com.tencent.mobileqq.pic.api.impl.PicFlashImpl
有以下两个函数:isFlashPicMsg
(判断消息是否为闪照)、isFlashPicMsgReaded
(判断闪照是否已读)
1 | // com.tencent.mobileqq.pic.api.IPicFlash |
hook前者,固定返回false,可实现闪照作为图片打开。
hook后者,固定返回false,可实现无限打开闪照。
考虑到实际使用时,需要判断发送的图片是否为闪照,选择hook后者(FlashPicHelper.b
)。