SmartQQ最新登录协议分析

原创 Dean 博文,程序相关 二维码阅读
2017-11-30 14:44

最近无意间了解到itchat一个Python写的微信机器人框架,真的是颇有感触,虽然有消息说微信为了避免机器人的滥用准备下线微信网页版,但是其实现原理还是很值得学习的,所以在学习之余,准备拿SmartQQ试试。

首先,了解一下SmartQQ,SmartQQ既Web版的qq,其网址是:http://w.qq.com/

我们访问一下SmartQQ的地址,界面是这样的:

页面很简单,重要的就是那个二维码了,然后我们打开浏览器的控制台,切换到network这个tab,清掉之前所有的请求记录,然后重新刷新页面:

可以看到简简单单的一个页面发出的请求还是不少的,那么哪些是与登录相关的呢?先排除掉那些静态资源文件js、图片啥的,剩下的链接依然不少,肯定还是有一部分是可以剔除掉的,那么怎么剔除呢?我的想法是重点关注这些链接中Response Headers中有set-cookie的,为什么呢?因为response headers中存在设置cookie的行为说明后端有session的设置,说明后端在标示你当前的状态,登录授权基本上也是这样做的,接着我们发现了第一个set-cookie的地址:

https://xui.ptlogin2.qq.com/cgi-bin/xlogin?daid=164&target=self&style=40&pt_disable_pwd=1&mibao_css=m_webqq&appid=501004106&enable_qlogin=0&no_verifyimg=1&s_url=http%3A%2F%2Fw.qq.com%2Fproxy.html&f_url=loginerroralert&strong_login=1&login_state=10&t=20131024001

设置了好多的cookie,先不管这些cookie干什么用,总之肯定只有用的,而这个地址中的参数经过观察也都是一些固定值。

我们接着往下看,发现了这么一个地址,这个链接并没有设置cookie,难道他不重要?当然不是,相反他非常重要,因为这个正是我们需要扫描的二维码

https://ssl.ptlogin2.qq.com/ptqrshow?appid=501004106&e=2&l=M&s=3&d=72&v=4&t=0.49805414076819&daid=164&pt_3rd_aid=0

设置了一个cookie,参数依然没有什么特殊的,现在有了二维码我们就可以扫描了,那么qq怎么知道你是否有没有扫描二维码呢?肯定还有一个检测二维码扫描状态的,接着我们找到了

https://ssl.ptlogin2.qq.com/ptqrlogin?u1=http%3A%2F%2Fw.qq.com%2Fproxy.html&ptqrtoken=1290714642&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1512012184387&js_ver=10232&js_type=1&login_sig=8UqNXX0ItQBAYM3-QX1wQAKRPy*CsnFVWuk9HAkK1kdSK-w5YUXfUSpbbsRMFhT7&pt_uistyle=40&aid=501004106&daid=164&mibao_css=m_webqq&

仔细观察这个了解的参数,我们发现大部分参数值是固定的或者可以动态生成,但是ptqrtoken,login_sig这两个字段显然是需要获取传递的,那么这两个值是怎么来的呢?

先说login_sig这个字段,好像在那儿见过,我们在访问第一个链接的时候设置了很多cookie,其中有一个pt_login_sig的字段,对比一下发现他们的值完全一样,login_sig我们知道了,顺着这个思路我们发现了请求二维码时设置的一个cookie,qrsig这个字段。但是比对发现qrsig和ptqrtoken并不相等,那是不是这两个就没关系呢?既然不相等,那么就可能是通过一定的方法转化而来,通过追踪二维码请求的发起源,我们找到了这么一段代码:

原来qrtoken是qrsig通过这个hash33方法转换后得来,我们找到hash33这个方法的声明并保存下来:

function hash33(t) {
	for (var e = 0, i = 0, n = t.length; i < n; ++i)
		e += (e << 5) + t.charCodeAt(i);
	return 2147483647 & e
}

接着我们扫描,通过不断尝试我们发现检测二维码扫描状态的接口返回结果ptuiCB('66','0','','0','二维码未失效。(413151880)', '')第一个参数代表的是状态,第三个参数代表的是跳转的链接,状态的码有:

0 扫描成功

65 二维码已过期

67 二维码已扫描,待确认

扫描成功后,我们就可以拿到一个回调地址:

http://ptlogin2.web2.qq.com/check_sig?pttype=1&uin=826554003&service=ptqrlogin&nodirect=0&ptsigx=f6d4ca15b6833f79959361cb00c48da386cc086566cf487634dec4d168297f6660a2445d7c939df3ca84ebcd26faac66c97ee1f05dda98cdc9d33df3ecd8e97e&s_url=http%3A%2F%2Fw.qq.com%2Fproxy.html&f_url=&ptlang=2052&ptredirect=100&aid=501004106&daid=164&j_later=0&low_login_hour=0®master=0&pt_login_type=3&pt_aid=0&pt_aaid=16&pt_light=0&pt_3rd_aid=0

该地址在设置了cookie之后做了一次302跳转,我们在写程序的时候需要阻止掉本次跳转,不然cookie设置不了,结果就是登录会失败。接着获取调用http://s.web2.qq.com/api/getvfwebqq?ptwebqq=&clientid=53999199&psessionid=&t=1512021281389获取vfwebqq,这个是用来获取好友列表的时候使用的,参数也都是固定值。

然后二次登陆,调用http://d1.web2.qq.com/channel/login2,二次登录后会得到psessionid,uin和另一个vfwebqq,这个vfwebqq和上面那个vfwebqq是不一样的,其实到这里已经成功登录进来了,后面的获取好友列表和发送消息就不多说了,抓个包看一看,什么都懂了。

写在最后,在之前一直觉得这种登录复杂的完全没法理解,其实在了解之后,发现也就那么回事儿,实现源码就不贴出来了,虽然用python简单的写了一个小机器人,但是代码写的太烂,不好意思发出来,各位看官可以根据自己的情况选择熟悉的编程语言来实现。

本文地址:https://www.deanhan.cn/smartqq.html
版权声明:本文为原创文章,版权归 Dean 所有,欢迎分享本文,转载请保留出处!
  • 支付宝二维码 支付宝
  • 微信二维码 微信