QQ空间登录协议逆向分析|账号密码登录

QQ空间协议登录分析|账号密码等参数加密算法的获取以及分析

JS/爬虫逆向玩转qq空间协议保姆级教学—账号密码登录篇

从0实现qq空间账号密码登录协议,qrsig、login_sig、ptqrtoken、p等参数以及算法逆向还原

只要依次按照本文数据包的顺序保存更新好参数和Cookie,成功逆向加密算法之后,通过顺序进行GET请求即可实现QQ空间登录

文章结尾附qq空间协议登录实现代码

目录

一、逆向时间

二、抓包、参数分析

2.1数据包1—二维码包

2.2数据包2—登录状态包

2.3数据包3—验证码包

2.4数据包4-登录包

三、算法逆向

3.1ptqrtoken算法

3.2密码p算法

四、python代码实现

4.1ptqrtoken算法代码

4.2密码p算法代码

 4.3发包代码


一、逆向时间

逆向时间

逆向时间为2024-9-18 是最新的QQ空间协议逆向分析文章


二、抓包、参数分析

2.1数据包1—二维码包

直接GET请求所有参数固定      https://ssl.ptlogin2.qq.com/ptqrshow?appid=549000912&e=2&l=M&s=3&d=72&v=4&t=0.0035106983314870943&daid=5&pt_3rd_aid=0&u1=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone

5ce39e37ad3c4864aaca6eede05dad23.png

二维码包Cookie会返回 qrsig 参数 这个参数是后续重要的参数

2.2数据包2—登录状态包

循环GET即可查询登录状态  https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone&ptqrtoken=1302498652&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1726673826887&js_ver=24090913&js_type=1&login_sig=nJL8y1akA3VvL6a*Ow5YWDHTGeDc-bGa6kOKPOXxcAvnoyf11FRaQMmh6iuwImpQ&pt_uistyle=40&aid=549000912&daid=5&=&o1vId=2b82096ccefcae244d20335bbe82233c&pt_js_version=e8983a1a

4fe5af5ce73c4df081773c16a91bd5c5.png

这里的第二个参数0意味着在进行账号密码登陆时不需要验证码 这里重要的是这两个标红参数,其他固定即可,

 ptqrtoken——用qrsig进行算法计算即可获得

 login_sig——GET请求一次下方qq空间的主页网站,在响应的Cookie中可找到

 同时还可得到Cookie:pt_clientip、pt_guid_sig、pt_local_token、pt_login_sig、pt_serverip、 pt_user_id、ptui_identifier、uikey

qq空间主页:https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https://qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&=&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone&pt_qr_app=手机QQ空间&pt_qr_link=https://z.qzone.com/download.html&self_regurl=https://qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=https://z.qzone.com/download.html&pt_no_auth=0 

2.3数据包3—验证码包

在输入账号密码后,可以抓到https://ssl.ptlogin2.qq.com/check这个包

GET请求  https://ssl.ptlogin2.qq.com/check?regmaster=&pt_tea=2&pt_vcode=1&uin=3592795816&appid=549000912&js_ver=24090913&js_type=1&login_sig=nJL8y1akA3VvL6a*Ow5YWDHTGeDc-bGa6kOKPOXxcAvnoyf11FRaQMmh6iuwImpQ&u1=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone&r=0.8028792184028488&pt_uistyle=40&daid=5&pt_3rd_aid=0&o1vId=2b82096ccefcae244d20335bbe82233c&pt_js_version=e8983a1a

响应结果ptui_checkVC('0','!AHD','\x00\x00\x00\x00\xd6\x25\xb6\xa8','d209e30814a3ed57d25582d156452fb6cc8b09549b7119366d6fdf1e7f51d80452e7e96375acf888f6ed439f61d2919dc848a8cbef2491ea','2','sj0KT*DVpTNcsfhRgPc2-yt2uXbB7fNBf81xpmiOLfX5YnV5hfuF8lZzETgNZ-B6blq8KxmJ1rs_','7073017071800088268')

在发送验证码包时,uin就是qq号,再从Cookie中读取login_sig即可

响应结果的参数如上所示,并且响应的Cookie中有以下参数confirmuin、ptdrvs、ptvfsession

ptdrvs——sj0KT*DVpTNcsfhRgPc2-yt2uXbB7fNBf81xpmiOLfX5YnV5hfuF8lZzETgNZ-B6blq8KxmJ1rs_

ptvfsession——d209e30814a3ed57d25582d156452fb6cc8b09549b7119366d6fdf1e7f51d80452e7e96375acf888f6ed439f61d2919dc848a8cbef2491ea

验证码:!AHD

uin2hex算法加密后的账号:\x00\x00\x00\x00\xd6\x25\xb6\xa8

2.4数据包4-登录包

https://ssl.ptlogin2.qq.com/login?u=3592795816&verifycode=!AHD&pt_vcode_v1=0&pt_verifysession_v1=d209e30814a3ed57d25582d156452fb6cc8b09549b7119366d6fdf1e7f51d80452e7e96375acf888f6ed439f61d2919dc848a8cbef2491ea&p=nzhWRFgmertBtuWg8UdNPAEP*1SvzBQUF*15oxH9lpmS3ezrwMD*fsXMsA5Z7*gtMrjc4YlvdAfQBsuS21ZhWDQBG6EVGEDmh0rl3D58Q8jQsw7aLZGfBSuvXYZUk*uynaf6Y8NRuCE1O1zRrIIDbmpaerkg*KrSKrJruJHaxfkYnsCnPJ5eiihFoNne0Wk6uHyv-fuDgY8KmbXBttHY8VE2CfRixzP0wxi*bs39aoQ8XR7CyzY9ILl6FXohv9MqOjM-dkQoySEQngZEp0shnjt1Or2*6KDRAaGCvwJiEFJJ10J82*jziPhEwlzPxOmVV0wmAcw48YKUL*PfFD-QGQ__&pt_randsalt=2&pt_ev_token=pg*GymwZf8Usl2nma7yn5-K*wGC2F7U7u3ghMabxYADisu74gpNpDiqQYXduQ3dh&u1=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=2-9-1726675195974&js_ver=24090913&js_type=1&login_sig=nJL8y1akA3VvL6a*Ow5YWDHTGeDc-bGa6kOKPOXxcAvnoyf11FRaQMmh6iuwImpQ&pt_uistyle=40&aid=549000912&daid=5&ptdrvs=sj0KT*DVpTNcsfhRgPc2-yt2uXbB7fNBf81xpmiOLfX5YnV5hfuF8lZzETgNZ-B6blq8KxmJ1rs_&sid=7073017071800088268&=&o1vId=2b82096ccefcae244d20335bbe82233c&pt_js_version=e8983a1a

e3b7b80ee6bf4cf6b696aa946e448ca6.png

参数 pt_ev_token、login_sig、ptdrvs都可在前面几个数据包的响应Cookie中获取

u——QQ号

pt_verifysession_v1——GET验证码包后,Cookie中的ptvfsession就是pt_verifysession_v1

p——密码密文

verifycode——验证码包返回的验证码 !AHD

通过登录包分析可知,请求数据包1-2-3并且保存所有Cookie后,只有p参数还有ptqrtoken需要逆向算法计算获得

2.5数据包5—登录返回包

e002d76b71124d6594f194196345a1f7.png

发送完整的登录包之后,在响应的内容中会出现一串 check URL  图片中重要参数已删减,只需要用之前的Cookie GET请求这个URL,即可成果登录QQ空间


三、算法逆向

3.1ptqrtoken算法

389cbdd8bad24839b15618dda5dfa6da.png

直接搜索ptqrtoken即可发现是通过hash33函数进行加密得到,参数就是qrsig

0ad6eda2f53c4576a88f7d1bc78abdd6.png

直接搜索hash33即可找到加密函数,函数参数t就是qrsig 

3.2密码p算法

ce2ece3fa9a94e528d3c296dd1d22741.png

先在登录包处查看堆栈,在loadScript、submit、匿名处下断点

019a90ef29534a819b07752e0bbf275f.png

可以看到密码p的密文是通过getEncryption这个函数得到的,一共有4个参数 ,注意其中的E.salt

64a2ff94d04440f2869af327507febbb.png

getEncryption函数 可以看到函数的参数

t——密码明文

e——E.salt

n——验证码包响应的验证码

o——空

916ee58393914697b99d2c520421a068.png

可以看到E.salt是通过账号进行uin2hex算法得到的,登陆时输入邮箱的话会把@qq.com替换为空 

479733f665dc4089a67ec3b7e1ad4967.png

 getEncryption函数 e参数算法  参数str为账号明文


四、python代码实现

4.1ptqrtoken算法代码

def hash33(t):  #参数:qrsig
    e = 0
    for n in range(len(t)):
        e = (e << 5) + ord(t[n])  
    return e & 2147483647  # 返回ptqrtoken

这个加密算法较为简单,直接扣下来即可 

4.2密码p算法代码

将p算法完整的js代码扣下来之后,使用python的subprocess库对js代码进行调用即可

 1dc34ab6624e45908f4886b441badd29.png

 使用args配合subprocess库,args[0]即为python代码传入的第一个参数,其他同理

40f28ab01c51422d97c7ae7c40c417fa.png

 vercode就是js代码中args[0]

测试结果: i267PnCDEUJb5h03dENIKxs8lQw7piqg*kUELiyl1L3s7QVsgk2LuM4HGtGJ0G0vc6q-u1aCHsdioDr4n9MQEeLx9WdtB5l4Y*hPMOUn5jQ5ygWyioefo1usP0kguKCzppaxBs0HCiMF0aI0DPSvxXtE8BPPaRaFV*h4rFdNNdeSs2AHF9STi44GUmwtUwxS0rb*MJ75InMO7bxgyP4d-o3mjgHO10mftu0EBJLl-WDn03LCWlhl3GCFyY3t0*gKMKMf*XULEjkA660vGOlB5Je*iLgivVQCWNEokL6JoIVjZp7IP1sy7h0IzAFX7Fy2fI2DKCsOjYKRLbQrq-HbDA__

 1dae3ec5bf904996858d935ce54431fc.png

密码算法正确性测试方法:写完前面所有数据包的话可以直接进行验证

也可以利用burp对登陆包进行拦截,拦截时使用假密码123456789

再用扣下来的代码生成真密码的密文,替换参数p,放行即可成功登录

 4.3发包代码

def get_initial_cookies(): #数据包1
    global global_cookies
    # 发送 GET 请求到指定的 URL 来获取初始 Cookie
    url = "https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https://qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&=&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https://qzs.qqzone.qq.com/qzone/v5/loginsucc.html?para=izone&pt_qr_app=手机QQ空间&pt_qr_link=http://z.qzone.com/download.html&self_regurl=https://qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http://z.qzone.com/download.html&pt_no_auth=1"

    headers = {
        "Host": "xui.ptlogin2.qq.com",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.9",
        "Accept-Encoding": "gzip, deflate, br, zstd",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1",
        "Cache-Control": "max-age=0"
    }

    # 发起 GET 请求
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        # 合并获取的 Cookie 
        global_cookies.update(response.cookies)
        return global_cookies, headers
    else:
        print(f"请求失败,状态码:{response.status_code}")
        return None, None
def get_qr_image_with_cookies(cookies, headers): #数据包2
    global global_cookies
    # 设置二维码请求的 URL
    qr_url = "https://ssl.ptlogin2.qq.com/ptqrshow?appid=549000912&e=2&l=M&s=3&d=72&v=4&t=0.39175954831717164&daid=5&pt_3rd_aid=0&u1=https://qzs.qzone.qq.com/qzone/v5/loginsucc.html?para=izone"

    # 为二维码请求设置新的请求头
    headers.update({
        "Host": "ssl.ptlogin2.qq.com",
        "Accept": "image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5",
        "Referer": "https://xui.ptlogin2.qq.com/",
        "Sec-Fetch-Dest": "image",
        "Sec-Fetch-Mode": "no-cors",
        "Sec-Fetch-Site": "same-site",
        "Pragma": "no-cache",
        "Cache-Control": "no-cache"
    })

    response = requests.get(qr_url, headers=headers, cookies=cookies)
    # 检查请求是否成功
    if response.status_code == 200:
        # 保存二维码图片到本地
        with open("qrcode_with_new_cookie.png", "wb") as f:
            f.write(response.content)
        print("二维码已成功保存为 'qrcode_with_new_cookie.png'")

        # 将新获取的 Cookie
        global_cookies.update(response.cookies)
    else:
        print(f"二维码请求失败,状态码:{response.status_code}")
def get_vercode(cookies, headers,qquin,loginsig): #数据包3
    global global_cookies
    global global_code
    global global_sid
    qr_url = "https://ssl.ptlogin2.qq.com/check?regmaster=&pt_tea=2&pt_vcode=1&uin="+qquin+"&appid=549000912&js_ver=24090913&js_type=1&login_sig="+loginsig+"&u1=https://qzs.qzone.qq.com/qzone/v5/loginsucc.html?para=izone&r=0.48032086977232935&pt_uistyle=40&daid=5&pt_3rd_aid=0&o1vId=989ddff17a71e99927948b1101c6592d&pt_js_version=e8983a1a"
    #设置新的请求头
    headers.update({
        "Host": "ssl.ptlogin2.qq.com",
        "Accept": "image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5",
        "Referer": "https://xui.ptlogin2.qq.com/",
        "Sec-Fetch-Dest": "image",
        "Sec-Fetch-Mode": "no-cors",
        "Sec-Fetch-Site": "same-site",
        "Pragma": "no-cache",
        "Cache-Control": "no-cache"
    })

    response = requests.get(qr_url, headers=headers, cookies=cookies)
    # 检查请求是否成功
    if response.status_code == 200:
        # 打印新获取的 Cookie
        content = response.content.decode('utf-8', errors='ignore')
        global_code=content.split(',')[1][1:-1] #验证码
        global_sid=content.split(',')[6][1:-2]  #sid
        global_cookies.update(response.cookies)
    else:
        print(f"请求失败,状态码:{response.status_code}")
def login(cookies, headers,verifycode,v1,p,login_sig,ptdrvs,sid): #数据包4
    p=p.replace("\n",'')
    global global_cookies
    print('-----------------开始登录-----------------')
    qr_url = "https://ssl.ptlogin2.qq.com/login?u="+global_cookies['ptui_loginuin']+"&verifycode="+verifycode+"&pt_vcode_v1=0&pt_verifysession_v1="+v1+"&p="+p+"&pt_randsalt=2&u1=https://qzs.qzone.qq.com/qzone/v5/loginsucc.html?para=izone&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=2-9-1726375321935&js_ver=24090913&js_type=1&login_sig="+login_sig+"&pt_uistyle=40&aid=549000912&daid=5&ptdrvs="+ptdrvs+"&sid="+sid+"&=&o1vId=989ddff17a71e99927948b1101c6592d&pt_js_version=e8983a1a"
    print('loginurl',qr_url)
    #设置新的请求头
    headers.update({
        "Host":"ssl.ptlogin2.qq.com",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
        "Accept": "*/*",
        "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
        "Accept-Encoding": "gzip, deflate, br, zstd",
        "Sec-GPC": "1",
        "Connection": "keep-alive",
        "Referer": "https://xui.ptlogin2.qq.com/",
        "Sec-Fetch-Dest": "script",
        "Sec-Fetch-Mode": "no-cors",
        "Sec-Fetch-Site": "same-site",
        "Pragma": "no-cache",
        "Cache-Control": "no-cache",
    })
    response = requests.get(qr_url, headers=headers, cookies=cookies)
    # 检查请求是否成功
    if response.status_code == 200:
        # 打印新获取的 Cookie
        content = response.content.decode('utf-8', errors='ignore')
        print(content)
        ckurl = content.split(',')[2][1:-1]
        state = content.split(',')[4][1:-2]
        name=content.split(',')[5][1:-2]
        print(ckurl,state)
        # 将获取到最终Cookie
        global_cookies.update(response.cookies)
        login_finish(global_cookies,headers,ckurl,state,name)
    else:
        print(f"请求失败,状态码:{response.status_code}")

在数据包4的响应中,会返回一个HTTPS的URL,只要利用Cookie使用GET请求访问一下URL即可成功登录

def login_finish(cookies, headers,url,state,name): #最终登录
    global global_cookies
    print('-----------------登录-----------------')
    print(state, name)
    qr_url = url
    print(qr_url)
    # 设置新的请求头
    headers.update({
        "Host": "ptlogin2.qzone.qq.com",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
        "Accept-Encoding": "gzip, deflate, br, zstd",
        "Sec-GPC": "1",
        "Connection": "keep-alive",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "none",
        "Pragma": "no-cache",
        "Cache-Control": "no-cache",
        "Priority": "u=0,i",
        "Upgrade-Insecure-Requests": "1"
    })
    response = requests.get(qr_url, headers=headers, cookies=cookies, allow_redirects=False)
    print(response.content)
    # 检查请求是否成功
    if response.status_code == 302:
        # 打印新获取的 Cookie
        content = response.content.decode('utf-8')
        print(content)
        global_cookies.update(response.cookies)
        print("登录成功--------->最终 Cookie:")
        for cookie in global_cookies:
            print(f"{cookie.name}: {cookie.value}")
    else:
        print(f"请求失败,状态码:{response.status_code}")
    print(state, name, "成功登录")
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小咖拉眯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值