彼岸船夫

我是一只菜鸟,在繁华城市独自飞翔,为生活有时候很迷茫,苦苦坚持在无烟沙场,期待渡船远方

二维码扫码登陆过程分析

以pay.qq.com查询QQ账号Q币信息为例,了解一下网站的二维码登陆大致是如何实现的

首先打开腾讯pay.qq.com主页上的登陆就可以获取到二维码了,使用浏览器的F12分析请求过程

clip_image002

发现通过打开的https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=11000101&target=self&style=40&s_url=https://pay.qq.com/ipay/login-proxy.html可以获取到cookies,这个url就先记下来

clip_image004

继续往下,打开下面的url,响应回来的就是二维码了

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

那这些请求的参数是如何得到的呢,多次请求分析发现只有t是随机变化的,那就给个随机数吧

参数t的python生成方式(python生成的随机数多一位)

import random
a=str(random.random())
print(a)
print(a[:-1])

当用手机扫了二维码之后,会发现一直请求一个地址,而返回的内容就是判定二维码是否过期的结果。但是请求的url随二维码的更新而变化的

clip_image006

获取是否过期(通过请求的url发现如下规律)

https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://pay.qq.com/ipay/login-proxy.html&ptqrtoken=1300613866&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1514654333018&js_ver=10233&js_type=1&login_sig=pGo5iOnV6O*DY3BgsPM22zAvlWCnVl48PPjrmWIJtQKMHpvYCoWpavmP1JcdWn6g&pt_uistyle=40&aid=11000101&

https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://pay.qq.com/ipay/login-proxy.html&ptqrtoken=1641999182&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1514655242011&js_ver=10233&js_type=1&login_sig=pGo5iOnV6O*DY3BgsPM22zAvlWCnVl48PPjrmWIJtQKMHpvYCoWpavmP1JcdWn6g&pt_uistyle=40&aid=11000101&

https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://pay.qq.com/ipay/login-proxy.html&ptqrtoken=1460309603&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1514656150867&js_ver=10233&js_type=1&login_sig=pGo5iOnV6O*DY3BgsPM22zAvlWCnVl48PPjrmWIJtQKMHpvYCoWpavmP1JcdWn6g&pt_uistyle=40&aid=11000101&

这些url返回结果如下这样的形式

ptuiCB('66','0','','0','二维码未失效。(2079330212)', '')

那么,这次的url所附带的参数更多了,究竟是如何生成的,由于没有学习过JavaScript,但是猜想这种交互式的网页一定有js控制的。

打开请求主页中所有的js链接,文件中都没有相关信息,于是重头分析请求过程,发现请求了一个url里面返回大量函数,里面有且仅有一个ptqrtoken变量

https://imgcache.qq.com/ptlogin/ver/10233/js/c_login_2.js?max_age=604800&ptui_identifier=000E010D989AA31CE07BA6E98F56BC76012729B221D540BFF0DE375CAC8A

clip_image008

这个url返回的代码里面找到getSubmitUrl函数如下:

clip_image010

三个参数ptqrtoken、action、login_sig。两个参数都在函数中说明了,login_sig同样在这段返回的代码里面,事实上就是cookies里面的pt_login_sig

clip_image012

 

于是乎可以试着构造一个这样的url,判断二维码是否有效。响应的代码里面跟三个参数有关的代码如下

函数的具体实现—ptqrtoken生成

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

函数的具体实现—action生成

,pt.plogin={account:"",at_account:"",uin:"",salt:"",checkState:!1,lastCheckAccount:"",needVc:!1,vcFlag:!1,ckNum:{},action:[0,0],passwordErrorNum:1,isIpad:!1,seller_id:703010802
action.join(“-”)+”-”+(new Date-0)

函数的具体实现—login_sig生成(这个是http响应时返回的)

login_sig=pt.ptui.login.sig

 

用javascript测试下实现函数功能的代码(不懂js所以先试下运行出来是什么结果)

1ptqrtoken

<script type="text/javascript">
document.write(isNaN(123)+ "<br />")
function test(t){
for(var e=0,i=0,n=t.length;i<n;++i)
e+=(e<<5)+t.charCodeAt(i);
return 2147483647&e;
}
document.write(test("l5ReOk*DhvMzPYYjfqWzkYjwSs52j6lzw1Oy6SaMsUNywLorCwuRuP8TbGfzSf*a"))
</script>

2action

document.write(new Date-0);
document.write("<br/>")
var t=new Date()
action=[0,0]
document.write(action.join("-")+"-"+t.getTime())

 

知道了逻辑,用python重写javascript的函数来实现同样功能

ptqrtoken的生成

t1="l5ReOk*DhvMzPYYjfqWzkYjwSs52j6lzw1Oy6SaMsUNywLorCwuRuP8TbGfzSf*a"
def test(t):
i=0
e=0
n=len(t)
fori in range(n):
e=e+(e<<5)
e=e+ord(t[i])
print(e)
print(2147483647&e)
test(t1)

action的生成就只是一个时间函数

import time
print(int(time.time()*1000))

 

继续往下分析连续请求该Url响应用户的扫码登陆状态,发现扫码成功后,也会返回cookies

带着cookies请求个人账户主页https://my.pay.qq.com/account/index.shtml?aid=pay.index.header.acct&ADTAG=pay.index.header.acc

发现返回的内容还是没有Q币的信息,说明内容还是由javascript动态生成

image

返回的js里面是没有Q币信息的

clip_image015

继续分析下面请求的url

clip_image017

发现了这个 https://my.pay.qq.com/cgi-bin/personal/balance_query_sortflow.cgi?items=qd,qb&_=0.9267836264725212

clip_image019

于是返回的json,qb_balance就是个人账户的Q币

 

import requests
import time
import random
def ptqrtoken_str(qrsig):  #三个函数就是url的三个参数生成
    i=0
    e=0
    n=len(qrsig)
    for i in range(n):
        e=e+(e<<5)
        e=e+ord(qrsig[i])
        e=2147483647&e
    return e

def action_str():
    a=int(time.time()*1000)
    b='0-0-'+str(a)
    return b

def pt_loginsig_str(ckiesget):
    st=ckiesget.headers['Set-Cookie']
    return st[st.find('pt_login_sig=')+13:st.find('pt_login_sig=')+77]
    
url_getcookies="https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=11000101&target=self&style=40&s_url=https://pay.qq.com/ipay/login-proxy.html"
s=requests.session()     #requests的session可以自动管理cookies
ckget=s.get(url_getcookies)

t=str(random.random())
url_getqr="https://ssl.ptlogin2.qq.com/ptqrshow?appid=11000101&e=2&l=M&s=3&d=72&v=4&t="+t[:-1]+"&pt_3rd_aid=0"
qrget=s.get(url_getqr)


f=open('tmp.png','wb') #将二维码保存为图片手动打开来扫码^_^
f.write(qrget.content)
f.close()


for i in range(1,7): #简单的循环返回二维码是否失效,循环结束前扫码就获得了cookies
    time.sleep(3)
    qrsig=qrget.headers['Set-Cookie'].split(';')[0][6:]
    url_check_timeout="https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://pay.qq.com/ipay/login-proxy.html&ptqrtoken="+str(ptqrtoken_str(qrsig))+"&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action="+action_str()+"&js_ver=10233&js_type=1&login_sig="+pt_loginsig_str(ckget)+"&pt_uistyle=40&aid=11000101&"
    timeoutget=s.get(url_check_timeout)
    print(timeoutget.status_code)
    print('----------------text---------------')
    print(timeoutget.text)
print(timeoutget.headers)

happy3=s.get("https://my.pay.qq.com/cgi-bin/personal/balance_query_sortflow.cgi?items=qd,qb&_="+str(random.random()))
print(happy3.text)

    

posted on 2018-01-23 00:11  彼岸船夫  阅读(6217)  评论(0编辑  收藏  举报

导航