欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

QQ2006 正式版协议分析

程序员文章站 2022-09-02 22:19:47
 本篇文章源自《黑客防线》2007年10月刊转载请注明版权 作者:BinSys=================================== 本文的分析环境为Wi...

 本篇文章源自《黑客防线》2007年10月刊
转载请注明版权

作者:BinSys
===================================
 
本文的分析环境为Windows XP SP2 +QQ2006正式版+Snifer Portable 4.7.5,所有涉及代码部分均为VB描述,因为啥?别的不会了!嘻嘻。
QQ协议概述
QQ基本通信协议是一套基于TCP/IP协议的自己开发的二进制应用层网络协议,基本通信协议支持TCP以及UDP两种方式,而且两种方式基本数据结构大同小异,只是TCP多了一个数据包(以下简称包)长度描述的头部信息。QQ基本协议采用应答机制,也就是说发送的每一个包服务器都会回应对应的包的执行结果,服务器发送的每一个包你也要回应(登出包除外,它没回应。),这也许是因为UDP协议的不可靠性吧。
QQ协议的加密算法
QQ基本协议目前为止用了两种公开的加密算法:十六轮的TEA(Tiny Encryption Algorithm)和MD5。QQ密码密钥是先把QQ密码的字符串用MD5加密得到一个16字节的Byte数组,再把此数组作为明文用MD5加密,之后得到的是一个16字节的Byte数组备用,即QQ密码密钥。(在这里我可吃了好多苦,网上的都说是二次MD5,我就把密码的一次MD5 结果作为字符串再用MD5加密,怎么都和QQ2006的加密结果不一样,后来看了IceQQ的加密类才发现的。)TEA是一种小型的可逆加密算法,但是TX使用了独特的填充反馈机制。如果整个明文不是8的倍数,还要在头部用16字节的随机数填充,然后在尾部补0,直到是8的倍数。QQ数据明文被分成N个8字节的明文单元,用TEA以16字节的密钥依次加密每个单元产生8字节的密文,密文再参与下一单元的加密。由于头部填充了随机字节,所以即使是同一明文的密文,也会因随机数的不同以及反馈机制而不同。
QQ协议分析
QQ的大体登录过程用VB伪代码可以表示如下(0X0091等为命令编号,将在下文解释)。注意,本文各命令测试用的QQ号不同,所以包内QQ号字段会变化,但不影响协议分析。

Step0 QQ客户端→(0X0091)→服务器
Step1 QQ客户端←(0X0091)←服务器
If  0X0091返回=可以请求登录令牌 Then
Goto Step3
Else
更新返回的服务器地址
Goto Step0
End If
Step3 QQ客户端→(0X00BA)→服务器
Step4 QQ客户端←(0X00BA)←服务器
Step5 QQ客户端→(0X0022)→服务器
Step4 QQ客户端←(0X0022)←服务器
Select Case 0X0022返回
Case 登录成功
Goto Step5
Case 重定向
更新返回服务器地址
Goto Step3
Case 密码错误
重新输入密码
Goto Step3
End Select
Step5 QQ客户端→(0X0002)→服务器
然后就是一遍一遍的发送心跳包(告诉服务器自己在线),想登出时发送登出包。

QQ0F5F协议发送包头部为:“02 0F 5F 00 BA 17 4A 25 DF 2F BF”,共10字节,分别表述如下。
第0字节:02;基本包标志;1字节,固定。
第1~2字节:0F 5F;协议版本;2字节,根据协议版本变化。
第3~4字节:00 BA;命令;2字节,根据不同命令变化,请求包与对应的回复包这里相同。
第5~6字节:17 4A;包序列号;2字节,请求包与对应的回复包这里相同。
第7~10字节:25 DF 2F BF;QQ号的十六进制。我的测试号码为635383743;4字节。
QQ0F5F协议接收包头部与发送包相比少了第7~10字节,第1~2字节有时为“0X01 0X00”,其他不变,共7字节。发送包与对应的回复包命令和序列号相同。所有包尾为0X03,1字节。服务器与客户端各自有自己的包序列号,各自先初始一个,然后每次发一个包用当前序列号,再将序列号加1以备下次使用。当为0XFFFF时清零(0X0000)。例如客户向服务器发送命令0X0091,包序列号为0X0410,那么服务器返回命令为0X0091、包序列号为0X0410的包。下一次客户又发了一个命令为0X00BA、包序列号为0X0410+1,即0X0041的包,服务器返回命令为0X00BA、包序列号为0X0041的包的处理结果。下面是我的测试包,具有唯一性。
(1)0X0091命令(客户端发起)
这是TX新加入的,我理解的意思是询问服务器本QQ号是否可以在这里登录,因为TX的服务器有很多,不只是有域名的那几个,可能分管不同版本、不同地区、不同号段。具体格式如下。
发送:
02 0F 5F 00 91 01 11 25 DF 2F BF 75 60 28 8C 5D 30 74 A7 52 50 12 CE 54 C2 00 47 05 E6 E2 C6 23 3A B3 F7 51 9D A7 EC CA 28 0B B5 C4 B1 12 88 A4 01 DC 01 E0 D7 25 6F 5F F3 E0 E6 03
共计60字节,其中第0~10字节为头部,11字节;第11~26字节为初始密钥(随机产生),16字节;第27~58字节为加密的数据,32字节;第59字节为包尾,1字节。密文(第27~58字节)用初始密钥解密后为“00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00”,共16个 0X00,这个固定。
服务器返回1:
02 0F 5F 00 91 01 11 C8 38 BD F8 EA 72 0D 1C 1C F0 E7 72 39 F6 84 F2 03
共24字节,其中第0~6字节为头部,7字节;第7~22字节为加密的数据,16字节;第23字节为包尾,1字节;密文(第7~22字节)用初始密钥解密后为“00 00”,表示可以发送请求登录令牌的包。
服务器返回2:
02 0F 5F 00 91 01 11 E3 0E 5A 51 8F F9 96 B4 6E DE A2 9F 9E EC AB 0D 93 4E 24 92 32 18 B4 A2 97 42 06 EF FE D4 F5 58 03
共40字节,其中第0~6字节为头部,7字节;第7~38字节为加密的数据,32字节;第39字节为包尾,1字节。密文(第7~38字节)用初始密钥解密后为“00 01 01 00 00 00 01 00 00 00 00 DB 85 3E 08”,共15字节。密文中的第0~10字节固定,我们可以凭借第0和第1字节是否全是0来判断是否需要重定向新的服务器;第11~14字节为服务器分配的新服务器地址,本例为219.133.62.8(按位转换成十进制),这是告诉客户端重新去另一个服务器试试(再向新的服务器发送0X0091命令)。

(2)0X00BA命令(客户端发起)
这个是请求登录令牌命令,格式如下。
发送:
02 0F 5F 00 BA 01 12 25 DF 2F BF 75 60 28 8C 5D 30 74 A7 52 50 12 CE 54 C2 00 47 3D E8 6D C2 D9 0F AA FB C8 F7 4E 4E 59 84 7F 56 58 7A A6 EB 0D 75 1D 05 03
共52字节,其中第0~10字节为头部,11字节;第11~26字节为本包密钥,16字节;第27~50字节为加密的数据,24字节;第51字节为包尾,1字节。密文用初始密钥解密后为“01 00 05 00 00 00 00”,固定,共7字节。
服务器返回:
02 0F 5F 00 BA 01 12 2B 64 8C 2A 0F 89 7D 4C 38 19 84 3D 34 63 7E F1 15 5B 2E 8F 70 F0 74 16 1D 41 7B 7D A1 29 0E CD D5 3E B8 37 2D 8C 1B 82 56 94 D3 BC 07 FD 12 4A 03
共56字节,其中第0~6字节为头部,7字节;第7~54字节为加密的数据,48字节;第55字节为包尾,1字节。密文用本包密钥解密后为“01 00 05 00 00 20 66 86 D4 BC 1E 0A C1 56 D0 00 FE E6 50 3B C5 60 FF 5B 79 20 7E F9 E2 42 02 7C 78 98 33 BA 55 C7”,共38字节。密文的第0~4字节固定为“01 00 05 00 00”,5字节;第5字节“20”为登录令牌长度(十六进制),1字节;第6~37字节为登录令牌,32字节。

(3)0X0022命令(客户端发起)
这个是请求登录的命令,里面有一些你的密码等数据。
发送:
02 0F 5F 00 22 F2 22 25 DF 2F BF 72 5D 24 89 5A 2D 71 ……省略,详见杂志相关……AF A2 90 A8 1A 19 1E E4 F7 03
共492字节,其中第0~10字节为头部,11字节;第11~26字节为本包密钥,16字节;第27~490字节为加密的数据,24字节;第491字节为包尾,1字节。密文用本包密钥解密后如下:
7E B4 7B D3 95 89 78 5B 60 21 2……省略,详见杂志相关……00 00 00 00 00 00 00 00 00 00 00 00
共448字节,其中第0~15字节表示用TEA以密码二次MD5的结果为密钥加密一个只有1字节00的数组,服务器只看能否解密,并不关心内容。第16~50字节固定,含义未知。第51字节每天都变化,规则未知,但用06总是可以登录成功。第52字节为登录模式,正常是0X0A,隐身是0X28。第53~77字节固定,全00,含义未知。第78~93字节固定,含义未知。第94字节固定,为登录令牌长度(十六进制)。第95~126字节为登录令牌。
服务器返回登录成功:
02 0F 5F 00 22 F2 22 1A 94 D7 61 7C A……省略,详见杂志相关……69 AA DA 89 94 BC 1D 03
共208字节,其中第0~6字节为头部;第7~206字节为加密的数据;第207字节为包尾。密文用QQ密码二次MD5作密钥解密后如下:
00 4B 67 32 58 67 50 6A 69 65……省略,详见杂志相关……00 00 00 00 00 00 00 00 00 00 00 00 08 02 04 08 08 08 08 08 04 02
共184字节,第0字节为0x00表示登录成功,我们依靠这个字节判断登录成功与否。第1~16字节为会话的SessionKey,以后所有的包的解密密钥都是它。第17~20字节为登录的QQ 号。第21~24字节为服务器测试到的你的IP。第25~26字节为服务器测试到的你的端口。第27~30字节为服务器测试到自己的你的IP。第31~32字节为服务器测试到自己的你的端口。第33~36字节为本次登录时间,从1970-1-1开始的毫秒数,计算时应乘以1000。第37~38字节未知。第39~62字节为认证令牌,作用未知。第63~66字节为未知服务器IP1。第67~68字节为未知服务器端口1。第69~72字节为未知服务器IP2。第73~74字节为未知服务器端口2。第75~82字节未知。第83~114字节为client key,用于登录QQ家园之类的地方。第115~126字节未知。第127~130字节为上次登录IP。第131~134字节为上次登录时间,计算时应乘以1000。第135~183字节未知。

服务器返回重定向(其实只要用了0x0019命令得到了正确的服务器地址,则一般不会出现这个回复):
02 0F 5F 00 22 F2 22 30 11 CA F4 53 30 1A A6 4A 53 21 93 DB 6A E5 F2 50 77 59 2A FA 70 38 21 0E 50 51 7C 90 89 53 63 03
共40字节,第0~6字节为头部;第7~38字节为加密的数据