文档章节

QQ登录分析

liinux
 liinux
发布于 2016/06/26 00:44
字数 1705
阅读 82
收藏 0
点赞 0
评论 0

0x01 QQ模拟登录实现之愚公移山(流程算法实现)


中我们分享了QQ帐号密码登录的流程和基于JS引擎实现的密码加密方式,我们用一种简单实用的方式实现了“能用”。

但是对于一个做安全爱好者,有时候我们需要深入一些,整个加密的流程和算法,我们是不是自己可以实现一套?所以,本文的重点,是对TX密码处理流程的分析。

密码处理流程

总体说明

了解了登录流程,我们在要分析和实现模拟登录需要考虑一个问题,密码是如何处理的?

要了解密码是如何处理的,我们先要了解以下3种算法:MD5,RSA,TEA。其中MD5是hash算法,比较常用;RSA是一种非对称加密算法,大家也比较了解。这里需要说明一下TEA算法。

TEA算法Tiny Encryption Algorithm,是一种分组加密算法,实现比较简单。TEA算法使用64位的明文分组和128位的密钥,需要进行 64 轮迭代。

不过TX_TEA算法对传统的TEA算法进行了一些修改,具体的原理可以参考登录的JS。这里简单说明下:TX只使用了16轮迭代;TX_TEA加密的是数据流,并且采用的是反馈随机交织填充方式。

加密流程

加密总流程图

基本上看懂这个流程图,就明白QQ密码的加密流程了。

浅蓝色的是来源数据,绿色是一些密码的处理方法(加密、HASH、替换)。

来源数据:

密码:password

saltsalt,来源于check接口的返回

verifycode: 来源于check接口的返回

rsaKeyjs源码里面可以获取

数据说明:

·         rsaData: rsa(md5(pwd), rsaKey)

·         hex_verifycode: verifycode 的16进制

最后进行tea算法tea(v, k)

·         v是 (rsaDataLen + rsaData + salt + verifycodeLen + hex_verifycode) 的byte数组

·         k是 md5(md5(pwd) + salt) 的byte数组

结果进行base64编码

Replace是做一个简单的替换,对以下3个字符进行替换

/ -> -

+ -> *

= -> _

最后得出加密的密码,长度为216的字符串,形式参考如下:

1

37Hro2-AgR4d8ZkU1L-6FqYhTUdhywhLlD2WihfVZGqZmz5R1RlwBsYPNowY0ZHJxcISmwpW0e7ppcoEDTGYyM5*6ZPJNUnZnb4h4Ke*qIBnFlTkiYFUhUwvXgOEvfIDTgCZIWsiFT6EauXujkB2i5yNFobx9aN5vw2xFyE1E2VoF*LV952q0mQO-HiooQZfMocl13kxFgxtVQaSRpm7Rg__

参考代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

def tx_pwd_encode(self, pwd, salt, verifycode):

    """

    js:getEncryption(t, e, i, n)

    t=pwd, e=salt 二进制形式, i=verifycode, n:default undefined

    # """

    salt = salt.replace(r'\x', '')

    e = self.fromhex(salt)

    md5_pwd = o = self.tx_md5(pwd)

    r = hashlib.md5(pwd).digest()

    p = self.tx_md5( r + e )

    a = rsa.encrypt(r, self.rsaKey)

    rsaData = a = binascii.b2a_hex(a)

 

    # rsa length

    s = self.hexToString( len(a)/2 )

    s = s.zfill(4)

 

    # verifycode先转换为大写,然后转换为bytes

    verifycodeLen = hex(len(verifycode)).replace(r"0x","").zfill(4)

    l = binascii.b2a_hex( verifycode.upper() )

 

    # verifycode length

    c = self.hexToString( len(l)/2 )

    c = c.zfill(4)

 

    # TEA: KEY:p, s+a+ TEA.strToBytes(e) + c +l

    new_pwd = s + a + salt + c + l

    saltpwd = base64.b64encode(

            tea.encrypt( self.fromhex(new_pwd), self.fromhex(p) )

    ).decode().replace('/', '-').replace('+', '*').replace("=", "_")

代码传送门:
https://github.com/LeoHuang2015/qqloginjs/blob/master/autologin_account.py

0x02 QQ模拟登陆实现之草船借箭(客户端快速登录实现)


我们在对QQ进行爬取和扫描的时候,很多时候需要考虑到登录的情况,如果使用用户名密码的方式,可能因为一些风控规则,当我们多次登陆时就要求图片验证码,而使用快速登录就能很好的规避这种情况。

流程梳理

客户端快速登录方式是用户在PC端已经登录了QQ客户端软件,如果用户再打开Web页面进行登陆,不用再输入用户名和密码,只需要选择已经登录的帐号,点击确认登录即可。

快速登录的本质上是使用clientkey置换token。

QQ客户端登陆后会生成一个长224的clientkey认证字符串,每次登陆都会变化,参考如下:

1

000156DCEB4E0068663F53B8B402784291BB6E74C482BFB6367FF48FB970443E9B9682359E8F1F92D5A814B097D12D938B96B30742DDE5CDA8E453EB7CD31A5121416637D945615C661285F5306884D959184AB1E4F7CFA83BC9FAF069C1E5878320ECF79EF8751320763492752A1433

早期快速登录的实现方式是各个浏览器使用插件,如IE的 ActiveX控件支持的,firefox是插件,通过插件植入clientkey。

后续支持非插件的形式,每次动态的访问QQ客户端绑定的本地server(localhost.ptlogin2.qq.com)获取clientkey,然后再用clientkey去置换token。

整体流程

客户端快速登录主要分为两种情况:

一种是插件模式,直接使用clientkey置换token登陆;

另外一种是费插件模式,或者clientkey出现一些异常情况,通过请求server把clientkey设置到cookie,然后再置换token登陆。

流程分析

clientkey存在且正常/插件模式

1.组件加载&获取用户头像信息

同帐号和密码登陆,只是这里获取已经登陆QQ客户端的用户头像和昵称。

获取登陆信息,用户
http://ptlogin2.qq.com/getface

返回:帐号、头像地址(有多个客户端登陆的帐号,请求多个)

2.登陆

用户点击登陆,实际上是一个clientkey置换token的过程。

请求会带上clientkey进行认证
http://ptlogin2.qq.com/jump

如果client不正确,则会登陆失败,后续登陆不会信任原来的clientkey,会走clientkey不存在/异常的流程。

clientkey不存或者异常/没有安装插件

1.组件加载&获取用户信息&获取用户头像信息

由于clientkey这里会多一步获取用户信息的流程

参考url:

1

2

3

4

http://localhost.ptlogin2.qq.com:4300/pt_get_uins

?callback=ptui_getuins_CB

&r=0.5314265366275367

&pt_local_tk=0.3291951622654449

返回,账号信息,客户端类型,昵称等信息

PS:这里如果获取不到会进行重试,一共5次,比如http的端口依次是4300,4302,4304,4306,4308。

然后再获取用户头像信息(同上)。

2.登陆

获取clientkey

参考URL:

1

2

3

4

5

http://localhost.ptlogin2.qq.com:4300/pt_get_st

?clientuin=1802014971

&callback=ptui_getst_CB

&r=0.11057236711379814

&pt_local_tk=0.3291951622654449

返回:设置clientkey到cookie,返回回调方法

1

var var_sso_get_st_uin={uin:"1802014971"};ptui_getst_CB(var_sso_get_st_uin);

然后进行登陆置换
http://ptlogin2.qq.com/jump

返回:设置cookie

1

ptui_qlogin_CB('0', 'http://www.qq.com/qq2012/loginSuccess.htm', '');

设置完cookie后,再请求ptlogin2.qq.com域的如下url来完成对ptlogin2.qq.com域和qq.com域的认证cookie的设置,同时删除clientuin和clientkey这两个cookie值。

模拟实现

我们需要模拟实现的快速登录,需要走非插件模式的流程,流程本身比较简单,也没有比较复杂的算法,如下:

·         获取签名

·         获取客户端QQ号码

·         用户名和环境检测

·         获取clientkey

·         置换token

这里有两个安全点需要注意:

1.  Token校验:请求的pt_local_tk会和cookie中的pt_local_tk校验;

2.  Referrer验证:referer限制了QQ域。

参考代码:

1

2

3

4

5

6

7

8

def get_client_uins(self):

    '''

    get client unis info

    need: token check & referer check

    '''

    tk =  "%s%s" %(random.random(), random.randint(1000, 10000) )

    self.session.cookies['pt_local_token'] = tk

    self.session.headers.update({'Referer':'http://ui.ptlogin2.qq.com/'})

具体实现参考代码:
https://github.com/LeoHuang2015/qqloginjs/blob/master/autologin_quick.py

© 著作权归作者所有

共有 人打赏支持
liinux
粉丝 2
博文 2
码字总数 2676
作品 1
西安
程序员
QQ传输协议分析

一、 实验目的:   在虚拟机下NAT模式下通过Wireshark抓包,分析QQ的传输模式。了解QQ在传输信息过程中用到的协议。分析在Nat模式下,信息传输的穿透性。 二、 实验环境:   Win7 专业版...

暖冰 ⋅ 2015/11/19 ⋅ 0

QQ2010协议技术详细分析QQ登陆过程

来自#博客园#文章,七月份的时候突然对QQ协议产生了些兴趣,于是这几个月有空就研究QQ协议,目前对QQ2010的协议已经分析得差不多了。 QQ登录分为UDP和TCP登录,还支持代理登录。默认是UDP登录...

杨昊亚 ⋅ 2012/12/27 ⋅ 1

QQ2010协议技术详细分析QQ登陆过程

来自#博客园#文章,七月份的时候突然对QQ协议产生了些兴趣,于是这几个月有空就研究QQ协议,目前对QQ2010的协议已经分析得差不多了。 QQ登录分为UDP和TCP登录,还支持代理登录。默认是UDP登录...

杨昊亚 ⋅ 2012/12/27 ⋅ 0

模拟登录QQ空间求助~

在分析超强QQ农牧助手,打算用PY写一个挂机程序~ 现在到登录的时候,发现同样是登录,通过抓包软件看到QQ农牧助手发出的HTTP头和我的HTTP头包含信息,除了一个PVID是随机数,ptvfsession是每...

Jooooooker ⋅ 2012/08/18 ⋅ 12

黑色产业链分析丨QQ盗号粘虫

QQ盗号粘虫 此类病毒主要通过两个渠道传播:一是伪装成QQ刷钻工具、游戏外挂,另一种是伪装成各种QQ好友发送的文件、主要以办公文件为主。 粘虫窗口 专门从事QQ盗号黑色产业的不法分子会对偷...

皆明 ⋅ 01/11 ⋅ 0

Discuz! 云平台已支持Discuz! 7.2版本

来自Discuz!官方消息,Discuz! 云平台已经支持多个版本,包括Discuz! X2/X1.5.1以及Discuz! 7.2。尤其是对于Discuz! 7.2版本的支持,将使得国内更多论坛可使用Discuz! 云服务。为了方便站长升...

红薯 ⋅ 2011/11/21 ⋅ 0

Chrome有了直接调用QQ微博官方API的扩展

相信有很多网友都喜欢使用QQ微博和Chrome浏览器。但每次发微博,都是要先登录QQ微博点多次才能搞定一条微博信息。有没有想过一键微博?甚至懒人的鼠标只希望选中一段话,都不想复制粘贴怎么办...

红薯 ⋅ 2010/11/23 ⋅ 6

wemall 开源微商城与最终商业版

wemall4.0.1商业版更新oauth等,下次更新计划商业版app,wemall平台上线,详情请关注www.inuoer.com。QQ交流2群:150157872 一.商业授权费:客服QQ:786699892 二.可用于餐饮,生鲜,水果,超...

einsqing ⋅ 2015/04/27 ⋅ 1

如何开发高大上的微商城

wemall4.0.1商业版更新oauth等,下次更新计划商业版app,wemall平台上线,详情请关注www.inuoer.com。QQ交流2群:150157872 一.商业授权费:客服QQ:786699892 二.可用于餐饮,生鲜,水果,超...

wemall ⋅ 2015/10/28 ⋅ 1

liinux/ghost-login

#Ghost-login 此处所说的模拟登录不是指利用网站本身提供的认证API接口进行登录,主要是通过分析前端代码,摸清登录认证原理、核心加密代码,然后程序模拟,来实现自动登录网站的过程; 专门...

liinux ⋅ 2016/09/12 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring Cloud构建微服务架构服务注册与发现

Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、...

明理萝 ⋅ 30分钟前 ⋅ 0

占位slot

一、为什么我们需要slot 假如我们有个需要,子组件中需要显示一段html内容,显示什么不是由子组件决定,而是由父组件传递什么决定,我们该怎么做 很挫的做法,我们使用组件间的数据传递 父组...

金于虎 ⋅ 30分钟前 ⋅ 0

Linux集群 NTP 时间同步

基于CentOS 7 规划 比如有2台机器 IP 主机名 说明 192.168.103.51 cdh51 本地NTP服务端 192.168.103.52 cdh52 本地NTP客户端 安装NTP服务 每台机器都安装ntp yum -y install ntp NTP服务端(...

囚兔 ⋅ 32分钟前 ⋅ 0

国际版链克口袋 获取方法

1 月16日,网心科技玩客云团队在官网发布了停止链克口袋转帐服务的通知。通知中表示迅雷将于1月25日在AppStore和官网,正式发布链克口袋新版本,新版本不支持迅雷及迅雷合作伙伴开发的应用场...

xiaogg ⋅ 33分钟前 ⋅ 0

Raft中Batching和pipelining到底是什么?

Raft supports batching and pipelining of log entries, and both are important for best performance. Many of the costs of request processing are amortized when multiple requests a......

黑客画家 ⋅ 34分钟前 ⋅ 0

Mybatis-Plus 之BaseMapper 方法详解

/** * Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能 * 这个 Mapper 支持 id 泛型 * @author hubin * @Date 2016-01-23 */public interface BaseMapper<T> ...

干干 ⋅ 34分钟前 ⋅ 0

JVM笔记9-Class类文件结构

摘要: 1.Class类文件结构   Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class 文件之中,中间没有添加任何分隔符,这使得整个 Class 文件中...

传授知识的天使 ⋅ 38分钟前 ⋅ 0

MySQL数据库之sleep线程过长如何处理?

  什么是sleep线程?   sleep线程长时间保持可客户端与服务端的连接状态   导致sleep过多的原因:   使用太多持久连接(高并发系统中 不适合使用持久连接)   程序中 没有及时关闭MyS...

老男孩Linux培训 ⋅ 39分钟前 ⋅ 0

转发和重定向的区别

转发在服务器端完成的;重定向是在客户端完成的 转发的速度快;重定向速度慢 转发的是同一次请求;重定向是两次不同请求 转发不会执行转发后的代码;重定向会执行重定向之后的代码 转发地址栏...

冯莉莉莉莉 ⋅ 39分钟前 ⋅ 0

go语言实现http proxy的关键一步

go语言自带包ReverseProxy 实现了proxy的功能。 但我希望proxy进程能够在代理的同时,完整的把请求和请求体记录在日志里。 仅使用ReverseProxy 包的话,uri记录没问题,但body只能被读取一次...

xuanzilie ⋅ 45分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部