QQXML消息:发送“超大”表情包

发布于 2020-04-17  9.25k 次阅读


本文于 2020年4月21日 6:35 更新,注意查看最新内容

前言

昨天面试回来(别问,问就是凉了),在回家的路上看到群里发了一个特别大的表情,我知道肯定又是QQ出现什么体验性的BUG了,于是由此展开摸索。

思路

这类对用户没有危害,但及其装X的行为一般都是“小学生”做的,所以我立马想到了一个地方:葫芦侠。

这里稍微介绍一下葫芦侠,早年做修改器,后来转型社区,后因为管理不善,社区出现众多“锁机”软件,因此闻名。

在葫芦侠的社区通过对关键词提炼,我找到了相关的代码,但因为本身对XML不了解,最终效果却是不尽人意。

于是又转度娘,对全网进行搜索,可能是因为关键词的问题,并没有找到好的解决方案。

几经尝试,我突然发现始作俑表情的代码可以复制,于是直接拿来分析,最终解决问题。

方法

准备:

手机Root(如未Root,可以使用类似太极一类的免Root框架或者虚拟机

安装Xposed框架、QNotified模块(相关下载链接可以直接度娘搜索,或者基安搜索,或者在关于页面加QQ群下载

操作:

软件安装完成后,在框架中激活模块,再打开QQ-设置,在模块的设置页面打开长按发送按钮发送XML消息,再复制下面代码到聊天框,长按发送按钮即可。

代码:

<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<msg serviceID="5" templateID="1" action="" brief="[素质]" sourceMsgId="0" url="" flag="0" adverSign="0" multiMsgFlag="0">
    <item layout="0" advertiser_id="0" aid="0">
        <image uuid="B1659C6E4810BD039796985165CE2654.jpg" md5="54b9a21af79fa6935e9bdd1667ac642a" GroupFiledid="0" filesize="2964" local_path="/storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/MobileQQ/chatpic/chatimg/13a/Cache_-3e0e5904d24d413a" minWidth="400" minHeight="1200" maxWidth="400" maxHeight="1200" />
    </item>
    <source name="" icon="" action="" appid="-1" />
</msg>

更换图片

这个代码是直接复制别人的代码,图片也是别人之前引用好的,假设我想更换显示的图片怎么办?

我当时的排查思路是先找可变参数,它们分别是local_path、md5、uuid。

我首先尝试更改了local_path,发现图片照常显示(事实上,如果英语好一点,应该就能知道,这个参数不会是控制图片的参数,local是局部的意思,path是路径,local_path设置的是局部路径,什么是局部路径,通过原有的路径,我猜测,很有可能是这张图片在手机上的路径,所以它不是更换图片的参数)。

尝试更改md5的时候,发现原有的图片不再显示,由此可以得知如果要更换显示的图片,只需要将想要替换的图片的Md5值填上去,XML卡片上显示的就是你想要显示的图片。

秒传机制

这里不得不提一下“秒传”机制,为什么这里我替换Md5值,图片就会更改,我并没有引用图片资源的地址,为什么我第一次上传一个文件需要1个小时,第二次再上传这个文件,可能只要几秒钟。

原因就在于,第一次上传时,服务器是没有这个文件的,当我第二次上传时,服务器会判断上传文件的Md5值,假设服务器上有这个文件的Md5值,说明该文件已经存在服务器上,服务器就会把文件的地址直接指向你的用户,这样避免了带宽的浪费,也节省了时间和存储。

窥屏探测

之前接触了一款酷Q插件,叫谁在窥屏,可以探测现在谁在看群,跟早年见过的一张图片看对方IP差不多,虽然我知道是通过XML消息实现的,但一直没明白其原理,这次倒腾这个超大表情,我大概是明白了。

通过XML消息发送一个自己服务器上的图片资源,当用户看到该条消息时,势必会去请求服务器的图片(点对点请求,不经过企鹅服务器),这个时候必然会有服务器的日志记录访问者的相关消息,这样一来,谁看了消息(群聊),谁有没有看消息(私聊),就都知道了 :idea:

至于为什么是用XML的方式发送的JSON,我表示也很迷 :!:

{
  "app": "com.tencent.mobileqq.reading",
  "desc": "",
  "view": "singleImg",
  "ver": "1.0.0.60",
  "prompt": "",
  "appID": "",
  "sourceName": "",
  "actionData": "",
  "actionData_A": "",
  "sourceUrl": "",
  "meta": {
    "singleImg": {
      "mainImage": "https://s1.ax1x.com/2020/03/19/8yUKXR.jpg",
      "mainUrl": ""
    }
  },
  "text": "",
  "sourceAd": ""
}

必要说明

首先,频繁发送XML消息,会导致账号被封,其次该效果目前只有安卓机的QQ正式版才会显示(已知TIM不显示),望周知!

其它卡片

红包代码

{
  "app": "com.tencent.cmshow",
  "desc": "",
  "view": "game_redpacket",
  "ver": "1.0.3.5",
  "prompt": "[QQ红包] 恭喜发财",
  "appID": "",
  "sourceName": "",
  "actionData": "",
  "actionData_A": "",
  "sourceUrl": "",
  "meta": {
    "redPacket": {
      "destUrl": ".2.15844517927.com",
      "msg": "龙鲲博客",
      "posterUrl": "\/xydata\/cmshow\/gameRedPacket\/2749\/bde0aed576c524d0544a079df0d36a30.png"
    }
  },
  "config": {
    "forward": 1
  },
  "text": "",
  "extraApps": [],
  "sourceAd": ""
}

天气预报:

{
  "app": "com.tencent.weather",
  "desc": "天气",
  "view": "RichInfoView",
  "ver": "0.0.0.1",
  "prompt": "[应用]天气",
  "appID": "",
  "sourceName": "",
  "actionData": "",
  "actionData_A": "",
  "sourceUrl": "",
  "meta": {
    "richinfo": {
      "adcode": "",
      "air": "1",
      "city": "地点",
      "date": "3月1日 周日",
      "max": "最大温度",
      "min": "最小温度",
      "ts": "15158613",
      "type": "202",
      "wind": ""
    }
  },
  "text": "",
  "extraApps": [],
  "sourceAd": ""
}

回执消息:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<msg serviceID="107" templateID="1" action="viewReceiptMessage" brief="[回执消息]" m_resid="x0DwAEdLtzd2WJ15N2KHqOgjsp6eHn9TKKypawugshhvbhAju3TdnXtbrK7gDjhI" m_fileName="6688764403224599306" sourceMsgId="0" url="" flag="3" adverSign="0" multiMsgFlag="0">
  <item layout="29" advertiser_id="0" aid="0">
    <type>1</type>
  </item>
  <source name="" icon="" action="" appid="-1"/>
</msg>

推荐联系人:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<msg serviceID="1" templateID="1" action="plugin" actionData="AppCmd://OpenContactInfo/?uin=QQ号" a_actionData="mqqapi://card/show_pslcard?src_type=internal&amp;source=sharecard&amp;version=1&amp;uin=QQ号" i_actionData="mqqapi://card/show_pslcard?src_type=internal&amp;source=sharecard&amp;version=1&amp;uin=QQ号" brief="快来看" sourceMsgId="0" url="" flag="2" adverSign="0" multiMsgFlag="0">
  <item layout="0" mode="1">
    <summary> 腾讯官方特别推荐</summary>
    <hr hidden="false" style="0"/>
  </item>
  <item layout="2" mode="2">
    <picture cover="mqqapi://card/show_pslcard?src_type=internal&amp;source=sharecard&amp;version=1&amp;uin=QQ号" w="0" h="0"/>
    <title color="#FF4900">⁣龙鲲博客</title>
    <summary color="#6495ed">昵称:龙鲲</summary>
  </item>
  <source name="官方认证" icon="https://qzs.qq.com/ac/qzone_v5/client/auth_icon.png?_tcvassp_0_=640shp" action="web" appid="-1"/>
</msg>

消息清屏:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<msg serviceID="5" templateID="1" action="" brief="清   屏" sourceMsgId="0" url="" flag="0" adverSign="0" multiMsgFlag="0">
  <item layout="0" advertiser_id="0" aid="0">
    <image uuid="B1659C6E4810BD039796985165CE2654.jpg" md5="B1659C6E4810BD039796985165CE2654" GroupFiledid="0" filesize="2964" local_path="/storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/MobileQQ/chatpic/chatimg/13a/Cache_-3e0e5904d24d413a" minWidth="1000000" minHeight="1000000" maxWidth="1000000" maxHeight="1000000"/>
  </item>
  <source name="" icon="" action="" appid="-1"/>
</msg>

以上代码均来源于网络,如有疑问,请自个解决 :smile:


这短短的一生,我们最终都会失去。