('QQ协议整理QQ协议整理文档的内容主要来自网络资料,特别感谢致力于QQ协议试探分析的朋友们。本文档整理有关QQ的命令,数据包格式等。由于QQ协议未对外公开,采用了信息加密技术以及随着版本升级总有所改动(大体上不会有太多变化),本文档仅供参考!!一QQ应用数据包头:QQ数据报头(除掉UDP或TCP等基本网络协议头,需要注意:TCP传输的QQ数据包,需要去掉包头2个字节,此两个字节代表数据包携带应用层数据的长度,下列所有QQ包均指UDP数据包应用层或者TCP数据包应用层去掉首部两个字节后的数据):所有QQ包的前7个字节是包头,包头可以识别QQ包的内容。包头的格式为:(单位字节)012345678(B)0x02发送者标识或版本号QQ命令编号命令序列号//////////表一:标准头格式第0字节:QQ包标识:0x02。(令牌请求报为0x16,下面所有数据报指0x02标识的报)第1-2字节:发送者标识。如果是0x010x00,表明是由服务器发送。客户端的标识与所使用的使用的QQ版本有关,例如QQ2003(0808)的标识为0x0A0x1D。具体的协议的格式与这个字段所标识的客户端版本有关。第3-4字节:命令编号。具体的命令编号含义在下面会给出。如果这个字段是0x000x01,那么这是一个注销请求包。如果这个字段是0x000x22,而发送者标识是0x010x00,那么这是一个登录应答包。如果这个字段是0x000x22,而发送者标识是其它(例如0x0A0x1D),那么这是一个登录请求包。第5-6字节:命令序列号。客户端和服务器都有各自的当前发送序列号。每初始发出一个指令的时候,使用当前的序列号,然后把当前序列号加一,如果超过0xFFFF,就绕回。如果是响应对方发出的命令,则使用这个命令的序列号。例如,客户端当前的序列号为0x1110,它向服务发送一个0x0016命令,它使用0x1110这个序列号,服务器收到以后,返回一个序列号为0x1110的0x0016命令响应。下一次,客户端又发送一个0x0026命令,这一次它使用加一了的序列号0x1111,服务器也响应0x1111序列号的一个0x0026命令响应。如果这是服务器要向客户端发送0x0017命令,它使用它自己的当前序列号,比如说0x2220,客户端收到以后,也响应一个序列号为0x2220的0x0017命令应答。我们可以通过序列号来判断发出的指令是否已经得到了应答,如果没有,可以重发。服务器对收到的命令的序列号顺序没有要求。服务器也不会一定按照发出的顺序给予应答。因此QQ的数据包头可以如下定义:(下列数据结构不能数据对齐)#pragmapack(1)/QQ数据包固定头部/typedefstructqq_head{unsignedcharhflags;/固定数据0x02(十六进制)/unsignedshortversion;/使用的协议版本号,网络字节序/unsignedshortcmd;/命令,表示本数据包的性质,网络字节序/unsignedshortsequence;/序列号,参照的TCP方式,具体含义间上文,网络字节序/}qq_head_t;/UDP数据包头部/typedefqq_head_tudp_qq_head_t;/TCP数据包头部/typedefstructtcp_qq_head{unsignedshortpacklen;//qq_head_thead;}tcp_qq_head_t;#pragmapack()包尾:所有的包都以0x03作为包尾。在包头和包尾中间的包数据则不同类型的包有所不同。QQ的命令:(本地字节序)QQ命令字,即QQ报头数据结构中的cmd项,位于数据报头的3-4两字节,是一系列的表示但前数据包内容作用的标识。在本文中用枚举的方式把网络上已经分析出来的部分命令列举如下:typedefenum{QQ_CMD_LOGOUT=0x0001,/注销登录/QQ_CMD_KEEP_ALIVE=0x0002,/在线保持信息/QQ_CMD_REG_NEW_ID_2=0x0003,/更换用户登录/QQ_CMD_UPDATE_INFO=0x0004,/更新用户信息/QQ_CMD_SEARCH_USER=0x0005,/搜索用户/QQ_CMD_GET_USER_INFO=0x0006,/获取用户信息/QQ_CMD_ADD_FRIEND_WO_AUTH=0x0009,/不需认证方式添加好友/QQ_CMD_DEL_FRIEND=0x000a,/删除好友/QQ_CMD_BUDDY_AUTH=0x000b,/需要认证的方式添加好友/QQ_CMD_CHANGE_ONLINE_STATUS=0x000d,/设置(隐身、示忙等)状态/QQ_CMD_REG_NEW_ID_1=0x0011,/注册新ID/QQ_CMD_ACK_SYS_MSG=0x0012,/确认收到系统消息/QQ_CMD_SEND_IM=0x0016,/发送消息/QQ_CMD_RECV_IM=0x0017,/收到消息(服务器发起)/QQ_CMD_REMOVE_SELF=0x001c,/在对方好友列表上删除自己/QQ_CMD_LOGIN=0x0022,/登录/QQ_CMD_GET_FRIENDS_LIST=0x0026,/获取好友清单/QQ_CMD_GET_FRIENDS_ONLINE=0x0027,/获取在线好友/QQ_CMD_GROUP_CMD=0x0030,/群操作指令/QQ_CMD_RECV_MSG_SYS=0x0080,/收到系统消息(服务器发起)/QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS=0x0081,/收到好友状态改变消息/}QQ_CMD_T;上面的命令对应解释的正确与否,因环境、时间、技术等原因没有进行逐个证实。但是重要的命令:注销,登录,收发消息四个命令是确认的。在这再次感谢网络上未谋面的朋友的努力分析。QQ内容加密算法QQ的消息(本文中所有的QQ消息均指聊天内容,其他如视频,文件传输等不在列)采用TEA。TEA(TinyEncryptionAlgorithm)加密算法是在1994年由英国剑桥大学的DavidWheeler和RogerNeedham所发明的一种加密方法。大概来说,它是使用128bit密钥加密64bit数据产生64bit输出的一种算法。这种算法的可靠性是通过加密轮数而不是算法的复杂度来保证的。具体的算法可以参考:http://www.ftp.cl.cam.ac.uk/ftp/papers/djw-rmn/djw-rmn-tea.html。实现可以参考:http://abcn.net/crypto.htm。QQ使用16轮的加密(这是最低限,推荐应该是32轮)。QQ在使用这个算法的时候,由于需要加密不定长的数据,所以使用了一些常规的填充办法和交织算法(也就是说,把前一组的加密结果和后一组的进行运算,产生新的结果)。具体的填充算法是:原始字符串加上8个字节再加上填充字符数应该是8的倍数(至少填充2个字节)。填充后的字符串是这样组织的:第一个字节,为填充字符数减2OR上0xA8。后面是填充字节。然后是待加密的数据,最后是7个0。填充的字节一般是0xAD,但再0A1dD版本中,会使用随机的填充字符串。一般,我们会用解密后最后是否7个零来判断是否正确的解密。QQ使用的16轮TEA算法C语言实现参考附录《附录——16轮TEA》部分相对重要的命令分析根据公安等需求,以及技术上的原因,过滤引擎和还原项目中主要关注注销,登录,收发消息四个命令。首先,根据QQ数据报的流向将数据包分为C2S(客户端到服务器)和S2C(服务器到客户端)。区分数据方向的方法是根据QQ报头数据结构的version字段,如果是0x010x00,表明是S2C。其他则表明是C2S。具体见节中对1-2字段的分析。基于C2S和S2C两种方向QQ的头部稍有不同,C2S在标准的头后面紧跟4字节的C端QQ号码,其后则是加密的数据,由此定义如下的数据结构#pragmapack(1)/UDP数据包C2S的QQ头部/typedefstructudp_qq_head_c2s{udp_qq_head_thead;/udp数据报标准头部/size_tqq_number;/数据发出端的QQ号码/}udp_qq_head_c2s_t;/TCP数据包C2S的QQ头部/typedefstructtcp_qq_head_c2s{tcp_qq_head_thead;/tcp数据报标准头部/size_tqq_number;/数据发出端的QQ号码/}tcp_qq_head_c2s_t;/UDP数据包S2C的QQ头部/typedefudp_qq_head_tudp_qq_head_s2c_t;/TCP数据包S2C的QQ头部/typedeftcp_qq_head_ttcp_qq_head_s2c_t;#pragmapack()在这些头部之后,除去结尾标识0x03的数据采用16轮TEA算法加密。7字节包头格式,见上表一4字节发----送客户端QQ号16字节本数据报解码密钥-----------------------16字节本数据报解码密钥---------------------------------------16字节本数据报解码密钥--------16字节QQ两次MD5后使用TEA算法加密随机数据密文-------16字节QQ两次MD5后使用TEA算法加密随机数据密文------------------------------------16字节密文---0x00IP地址(可能全部是0)端口(可能全部是0)0x000x000x000x000x000x000x000x000x000x000x000x000x3A0x300x1F0x9B0x690x600xA80x320x730xB20x220xA0xA650x6C0x090xF80x01登录状态其他信息可能是---------------------登录机器信息,不确定长度0x031、登录命令:0x22,(假定UDP协议,一些所有报均指UDP协议传送的数据)登录请求数据报属于C2S,除去udp_qq_head_c2s_t头部之后,紧跟的16个字节是对本数据报剩下部分除结尾标识进行TEA加密的密钥,QQ服务器收到此数据报后,使用本密钥对其解码,下面的数据样本就是对其解码后的数据。本命令的分析数据摘自《协议分析网——QQ协议分析之TCPF包数据分析》,并基本完全参考其分析的结果。本分析是基于QQ2003(0808)内部代码0A1D的版本。从QQ2003到目前最新版的QQ2006文本通讯方面的协议和加密方式基本没有改变。012345678(B)表二:解码后登录请求协议发送方:客户端样本:(使用与数据相同颜色对其用途含义注释,以下皆同)000:4A355D6EAEDBFA9C008:96BE197EA3E2B248(关键数据部分,暴力破解可以得到QQ密码,见下文详解)016:0000000000000000(固定值)(早期版本为IP和端口号,现在好像固定为0)024:0000000000000000032:0000003A309B6960(固定值,每次基本一样,估计是固定的字节填充)040:A83273B2221FAA65048:6C09F8010A3A0D30(登录模式:0A为正常方式,28为隐身)056:92CD77AB42B9BC64064:9F1757D4C3(登录机器标识,可能用来检验登录令牌,确保前期登录令牌用于同一机器)用户QQ密码的MD5的MD5作为密钥,对空字串进行加密的结果。0A1D版的TEA算法采取了随机PADDING的方式,所以这个数字每次看起来都不同。但是解密以后总是空字符串。因此可以通过暴力的方法在离线情况下产生不同的密码构造密钥对其解码,如果解码成功,则可以得到QQ的密码,服务端采用本方法验证登录密码。整个登录数据报被关注的数据就是此部分。012345678(B)7字节包头格式,见上表一登录结果sessionkey(16字节通讯解密密钥由随机数字大小写字母组成)-----sessionkey(16字节通讯解密密钥由随机数字大小写字母组成)-----登陆的QQ号码客户端IP客户端端口---------------其他不关心信息,不确定长度---------------其他不关心信息,不确定长度0x03表二:解码后登录成功应答协议,本数据报使用密码两次MD5解码响应方:服务器样本成功登录的样本:(红色密钥部分使用QQ密码的MD5的MD5作为密钥解密16字节原内容得到)000:0061425845556B58(00登录成功,响应报第一字节表示登录结果,下文将给出其他标识)008:7A425736786E4941(登录成功,后续通讯内容的密钥,C2S和S2C均用此密钥,失败则不同)016:5901825D9040E7A7(登录的QQ号码)024:E30FA07F0000011F(前四个字节为客户端IP,后两个字节为对应端口)032:403F5122DA030A5B040:8350D29155AEFC3A(其它一些信息,不太关注)048:5BD4E93197C58513056:646B300ACEF1333D064:8DC2CF1F403DACF9072:8E1F4000001CBB67080:00CB49E6FFB6FB01088:97416E9630487648096:EFB81D1E5AEAEBE9104:AB004A23D2000000112:0000000000000000120:0040E7A7E33F5122128:9100000000000000136:00本回应数据中重要数据就是后续通讯的解密密钥。密钥是一个由字符数字组成,例如上面的密钥即是:aBXEUkXzBW6xnIA。登录请求的其他一些相应标识:01转向,01后面紧跟4字节QQ号,4字节的新服务器IP和2字节的新服务端口02密码错误,02后跟错误提示信息我们可以通过使用01标识让QQ不停转向,转到一个假地址上而阻止QQ登录,来阻断QQ通讯。2、注销命令:0x01客户端(连续发送4次),此命令表明QQ下线,主要关注的是样本中密码的MD5的MD5,不过这一点需要验证!012345678(B)7字节包头格式,见上表一-----------------------------------密码的两次MD5--------------------------------------------------密码的两次MD5---------------------------0x03表三:注销请求协议(是否需要解码需要确认,应该用sessionkey解码)样本:000:4280D89A5A03F812008:751F504CC10EE8A5(QQ密码的MD5的MD5)3、发送消息命令:0x16发送消息命令由客户端发向服务器,由服务器根据数据报中的目的地转发给最终接受者。012345678(B)表四:普通发送消息协议7字节包头格式,见上表一4字节发----送客户端QQ号4字节发送端QQ号码4字节接-------------------受端QQ号2字节QQ版本4字节发送端QQ----------号码4字节接受端QQ号码16字节QQ号码+sessionkey的MD516字节QQ号码+sessionkey的MD516字节QQ号码+sessionkey的MD50x000x0B2字节----QQ序号发送时间。为自1970年1月1日起经过的秒数0x00头像代码0x000x000x000x010x000x000x000x00消息回复-----------------文本消息不定长----------------------消息结尾(0x200x00)消息的字体颜色等属性(未计算长度)0x03样本:000:0001829001825D90(发送方QQ号)(接收方QQ号)008:0A1D000182900182(QQ版本)(发送方QQ号)016:5D909F229C779EB5(接收方QQ号)024:0C68600F133706F4(发送方QQ号+sessionKey的MD5Digest)032:EA2C000B4DB53F65(固定值)(消息的序列号)040:3844006000000001(发送时间。为自1970年1月1日起经过的秒数)(固定值)(头像代码)(固定值)(消息特性标识。旧版0x00,新版0x01)048:0000000001616161(固定值)(消息类型。0x01,普通消息。0x02,自动回复消息)(消息内容“aaa”)056:20000A0000000086(消息结尾标识)064:02CBCECCE50D(消息的字体颜色等属性)此命令在QQ内容见空中非常重要!通过分析本命令可以得到当前QQ的聊天对象,以及聊天内容。本命令关注聊天对象(接收方QQ号),即好友,和聊天内容(去掉头,偏移53字节到空格及数值0不定长内容),另外可以通过检验消息中的MD5来验证解密密钥的正确性(由于QQ的TEA的愚笨性,能正确解密,密钥就正确,因此估计是多此一举)4、接受消息命令:0x17接受消息命令由服务器发向客户端。数据包括普通消息,群消息等。消息类型如下:(消息代码位于解码后的18、19两字节)0009普通消息(关注)002b群消息(关注)0021加入群通知0022被从群删除通知0023请求批准加入群通知0024加入群请求批准通知0025加入群请求拒绝通知0026创建群通知0030系统通知消息012345678(B)7字节包头格式,见上表一4字节发----送客户端QQ号4字节发送端QQ号码服务端转--发消息流水线号4字节发送者的IP地址(转发则示服务端IP)--端----口2字节消息类型代码2字节QQ版本号4字节发送端QQ号码-----------4字节接受端QQ号码16字节QQ号码+sessionkey的MD516字节QQ号码+sessionkey的MD516字节QQ号码+sessionkey的MD50x000x0B2字节消----息序列号发送时间。为自1970年1月1日起经过的秒数0x00头像代码0x000x000x000x000x010x000x000x000x00消息回复-----------------文本消息不定长----------------------消息结尾(0x200x00)消息的字体颜色等属性(未计算长度)0x03表四:普通接受消息协议普通消息(0009)样本:000:01825D9000018290(发送方QQ号)(接收方QQ号)008:000949BB3D8DC2EB(服务器转发消息的流水号)(发送者的IP地址和端口,转发的消息是服务016:1F4000090A1D0182器的地址和端口)(消息类型代码)(发送者QQ版本号,2003)024:5D9000018290AAD6(发送方QQ号)(接收方QQ号)032:544790046D768DD0(发送方QQ号+sessionKey的MD5Digest)040:4DCB64B8877A000B(固定值)048:006B3F6539320060(消息的序列号)(发送时间。为自1970年1月1日起经过的秒数)(固定值)(头像代码)056:0000000100000000(固定值)(消息特性标识。旧版0x00,新版0x01)(固定值)064:0162626220000A00(消息类型。0x01,普通消息。0x02,自动回复消息)(消息内容:bbb)(消息结束标识)072:0000008602CBCECC(消息字体颜色等属性)080:E50D群消息(002b)样本:000:0C04A9F401825D90(内部群号)(接收者的QQ号)008:000D1A8CDA125FC6(服务器转发消息的流水号)(服务器的地址和端口)016:1F4000200C04A9F4(消息类型代码)(外部群号)024:020139A476000000(代表临时群)(群消息发送者QQ号)(固定值)032:013F7CEF88000000(消息的序列号)(发送时间)040:00001268690D0A20(固定值)(后续消息长度)(消息数据:hi)(代表回车换行)048:0009000000008602(消息结束标识)056:CBCECCE50D(消息字体颜色等属性)',)