摘要:腾讯 QQ 是物联网巨头腾讯公司的重要用户基础,具备丰富细致的业务功能。本文分析了腾讯 QQ 的业务情况,介绍了 QQ 所使用的的 TCPF 协议格式,并实际抓包分析了 PC 版 QQ 的登录和通信过程。
关键词:腾讯;QQ;网络流量分析;即时通讯;
1. 引言
腾讯公司于1998年11月成立,2004年在香港上市。腾讯公司在最近几年中与百度、阿里巴巴并称为互联网三巨头“BAT”,它上市14年,股价增长627倍(经后复权),在16年市值就突破2万亿港元,目前市值4.4万亿港元。发展至今,腾讯建立起了复杂的业务体系,包括十几条业务线、上百种产品,并在众多领域处于领导地位,是深刻改变了中国社会的最伟大、最受人尊敬、最强大的企业之一。
尽管业务众多,腾讯的根基在于社交媒体,即时通讯软件 QQ 是它的基础,高达9亿的高粘性庞大用户流量是腾讯的核心竞争力,为其他产业的发展提供了肥沃土壤。在1999年,腾讯模仿即时通讯软件 ICQ 开发了Opening ICQ,即 OICQ ,2000年 OICQ 更名为 QQ ,但通讯协议名称仍然是 OICQ 。腾讯 QQ 的通信一开始使用不加密的通信,现在已经使用**协商后加密消息传输。 QQ 的特点在于使用UDP协议来进行聊天消息通信,因为UDP协议资源消耗小,发送速度快,同时使用消息中转服务器保证可靠传输。
本文在第2节中分析腾讯 QQ 的业务情况,在第3节中分析其登录和聊天协议结构,最后在第4节中通过实际抓包实验来验证登录和消息发送的协议,并在第5节总结了本文内容。
2. 业务分析
2.1 业务应用情况
腾讯 QQ 作为中国大陆用户量最高的即时通讯软件,支持在线聊天、视频通话、点对点断点续传文件、共享文件、网络硬盘、自定义面板、QQ邮箱等多种功能,并可与多种通讯终端相连。
QQ 的业务应用极其广泛,可以通过它的发展历史[3]来总结概括。腾讯 QQ 在2003年推出“QQ游戏”,进一步优化了产业营销策略,同年 QQ 用户注册数升到2亿。2008年,腾讯推出 DNF 黑钻业务,开启会员Q豆增值服务,同年注册用户接近8亿,同时在线突破4000万。2013年, QQ 的测试版本推出了“剑鱼”全新音视频引擎,支持高清画质。2019年,腾讯上线了 QQ 小程序。2020年, QQ 的 PC 版更新了“群课堂”、“群作业”等功能,进一步优化了用户体验,解决了广大教育用户的紧急需要。
2019年12月, QQ 公开财报]1]数据显示月活跃账户达8.07亿,同比增长3.0%;智能终端月活跃账户数为6.998亿,同比增长2.5%;2020年5月,受疫情影响, QQ 家校群已助力超过1.2亿用户开展线上教育。
2.2 使用方法
腾讯 QQ 的功能非常完备,同时具有清晰易懂的用户界面,从官网下载安装包后安装到本地,即可在引导下完成可能的任何操作。而 QQ 最为方便和吸引人的功能可以参考官网[4]的展示,包括消息管理、信息共享、虚拟交友等功能。
2.3 基本模式
腾讯 QQ 的功能全面而细致,让用户能有很好的使用体验。除去会员、钱包等增值功能和空间、小程序等附加功能,腾讯 QQ 的基本使用模式包括基本功能、单人聊天和 QQ 群聊。
- 基本功能
下载、安装与注册、登录,均可根据官网和引导程序快速完成。登录后,可以添加与查找好友、进行好友管理和好友分组。 QQ 也提供安全与隐私保护等功能。 - 单人聊天
QQ 提供消息漫游功能,即可以在不同的设备上同步聊天记录。聊天窗口可以发送表情和图片、截图和录屏、录音、拨打语音和视频电话、发送文件和共享文件等。同时还有远程控制、消息撤回等高级功能。 - QQ群聊
QQ 群让多人可以同时聊天,方便开启会议、文件共享、信息通知等。作为群主和管理员, QQ 群主要有权限设置、成员管理、发布通知和发起投票等功能。作为群成员,主要有发送和查看消息与图片、接受通知、下载和发送文件、匿名聊天等功能。
3. 协议过程
腾讯 QQ 登录时使用基于HTTP的TLS安全握手协议,聊天时使用文字聊天协议族(TCPF, Text Chatting Protocol Family),它主要支持与其它QQ客户端进行文字聊天。TCPF建立在UDP协议之上,UDP数据包中的第一个字符02为这个协议族的标识。TCPF的服务器使用8000号端口,腾讯的QQ客户端软件一般从4000号端口开始尝试使用,但实际上,对客户端使用的端口号并没有限制。
3.1 TCPF 分类
TCPF包可以被分为5类:
- 登录请求包(LIP,LogIn Packet),它是由客户端向服务器发出登录请求的数据包。
- 登录应答包(LRP,Login Reply Packet),它是由服务器响应客户端登录请求的数据包。
- 注销请求包(LOP,LogOut Packet),它是由客户端向服务器发出注销登录请求的数据包,服务器对这个包不作应答。
- 客户端其它包(CSP,Client Sent Packet),它是由客户端向服务器发送的其它包。
- 服务器其它包(SSP,Server Sent Packet),它是由服务器向客户端发送的其它包。
3.2 TCPF包结构
这一部分主要参考了PC端QQ协议说明
所有TCPF包的前7个字节是包头,包头可以识别TCPF包的内容。包头的格式为:
- 第0字节:TCPF包标识:0x02。
- 第1-2字节:发送者标识。如果是0x01 0x00,表明是由服务器发送。客户端的标识与所使用的使用的QQ版本有关,如:版本QQ2013(8550)的标识为0x34 0x33。具体的协议的格式与这个字段所标识的客户端版本有关。
- 第3-4字节:命令编号。以QQ2013为例,如果这个字段是0x00 0x59,那么这是一个注销请求包。如果这个字段是0x08 0x25,而第12位为 0x00,那么这是一个登录应答包。如果这个字段是0x08 0x25,而第12位为 0x03,那么这是一个登录请求包。其它的命令代码表明是其它包,我们通过发送者标识来区分它是CSP还是SSP。
- 第5-6字节:命令***。客户端和服务器都有各自的当前发送***。每初始发出一个指令的时候,使用当前的***,然后把当前***加一,如果超过0xFFFF,就绕回。如果是响应对方发出的命令,则使用这个命令的***。例如,客户端当前的***为0x1110,它向服务发送一个0x0016命令,它使用0x1110这个***,服务器收到以后,返回一个***为0x1110的0x0016命令响应。下一次,客户端又发送一个0x0026命令,这一次它使用加一了的***0x1111,服务器也响应0x1111***的一个0x0026命令响应。如果这是服务器要向客户端发送0x0017命令,它使用它自己的当前***,比如说0x2220,客户端收到以后,也响应一个***为0x2220的0x0017命令应答。我们可以通过***来判断发出的指令是否已经得到了应答,如果没有,可以重发。服务器对收到的命令的***顺序没有要求。服务器也不会一定按照发出的顺序给予应答。
- TCPF包尾:所有的TCPF包都以0x03作为包尾。
3.3 登录协议
这部分主要参考SSL/TLS握手过程详解
QQ登录过程使用SSL安全套接层的TLS安全传输层协议,SSL/TLS 握手是为了安全地协商出一份对称加密的秘钥。SSL/TLS握手过程如下图所示:
- Client Hello
握手第一步是客户端向服务端发送 Client Hello 消息,这个消息里包含了一个客户端生成的随机数 Random1、客户端支持的加密套件(Support Ciphers)和 SSL Version 等信息。 - Server Hello
第二步是服务端向客户端发送 Server Hello 消息,这个消息会从 Client Hello 传过来的 Support Ciphers 里确定一份加密套件,这个套件决定了后续加密和生成摘要时具体使用哪些算法,另外还会生成一份随机数 Random2。至此客户端和服务端都拥有了两个随机数(Random1+ Random2),这两个随机数会在后续生成对称秘钥时用到。 - Certificate
这一步是服务端将自己的证书下发给客户端,让客户端验证自己的身份,客户端验证通过后取出证书中的公钥。 - Server Key Exchange
如果是DH算法,这里发送服务器使用的DH参数。RSA算法不需要这一步。 - Server Hello Done
Server Hello Done 通知客户端 Server Hello 过程结束。 - Client Key Exchange
上面客户端根据服务器传来的公钥生成了 PreMaster Key,Client Key Exchange 就是将这个 key 传给服务端,服务端再用自己的私钥解出这个 PreMaster Key 得到客户端生成的 Random3。至此,客户端和服务端都拥有 Random1 + Random2 + Random3,两边再根据同样的算法就可以生成一份秘钥,握手结束后的应用层数据都是使用这个秘钥进行对称加密。使用三个随机数是因为 SSL/TLS 握手过程的数据都是明文传输的,并且多个随机数种子来生成秘钥不容易被暴力**出来。 - Change Cipher Spec(Client)
这一步是客户端通知服务端后面再发送的消息都会使用前面协商出来的秘钥加密了,是一条事件消息。 - Encrypted Handshake Message(Client)
这一步对应的是 Client Finish 消息,客户端将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的。 - Change Cipher Spec(Server)
这一步是服务端通知客户端后面再发送的消息都会使用加密,也是一条事件消息。 - Encrypted Handshake Message(Server)
这一步对应的是 Server Finish 消息,服务端也会将握手过程的消息生成摘要再用秘钥加密,这是服务端发出的第一条加密消息。客户端接收后会用秘钥解密,能解出来说明协商的秘钥是一致的。 - Application Data
到这里,双方已安全地协商出了同一份秘钥,所有的应用层数据都会用这个秘钥加密后再通过 TCP 进行可靠传输。
4. 流量分析
本节抓取登录腾讯QQ的流量数据,根据抓取的网络流量分析登录和消息传输协议。
4.1 实验环境
- Windows 10 家庭版
- 腾讯QQ 9.3.3.27011
- Wireshark Version 2.6.4
4.2 登录协议
- 关闭浏览器等其他应用,开启 Wireshark Capture ,登录腾讯QQ,等待登录成功后关闭Capture。
- 通过win+R快捷键打开cmd命令行控制台,输入ipconfig,找到当前WLAN下的IP地址为192.168.1.102:
- 设置显示过滤规则为“tcp && ip.addr==192.168.1.102”,找到与QQ登录服务器开始交互的TCP数据包,即编号137的SYN数据包。
这里交互的服务器地址为116.128.163.211查询发现绑定过qq.com的域名,可以确认是腾讯的服务器地址: - 右键数据包,选择“follow”->“TCP stream”,找到登录QQ的TCP数据流:
- 分析No.137数据包,TCP报文的开头首先是数据链路层(Ethernet)报头:
f4:83????45:ee:6e:目的MAC地址
be:30:11:91:19:79:本机MAC地址
0800:IPv4协议 - 分析No.137数据包,网络层(IP)报头:
45:0100(Version 4)+0101(报头长度 20字节)
00:差异化服务域(differentiated services field)
00 34:总长度52字节
f3 be:标识位(62398)
04 00:标志位,非碎片化
80:生存周期(128)
06:协议(TCP)
2c a3:头部校验和
c0 a8 01 66:源地址192.168.1.102
74 80a3 d3:目的地址116.128.163.211 - 分析No.137数据包,传输层控制层(TCP)数据:
f4 47:源端口62535
01 bb:目的端口443
21 45 ed 33:***0
00 00 00 00:确认号0
80:头部长度32字节
02:标识号(SYN)
ff ff:窗口大小65535
90 32:校验和
00 00:紧急指针
剩余的是可选字段。 - 跟踪TCP数据流,发现本机向服务器发送[SYN]后,服务器向本机发送[SYN,ACK]报文,本机再次向服务器发送[ACK]报文,至此TCP三次握手完毕,开始正式通讯。
- 本机向服务器发送TLS报文,内容是Client Hello,这是一个登陆服务器的握手协议。传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。
- 服务器回复[ACK]并发送Server Hello,Server Hello以分段segment形式发送了好几个包,包括Certificate 和最后的 Server Key Exchange ,中间穿插本机对每个包的[ACK]应答:
查看最后一个certificate数据包,即151号报文,Wireshark显示它由3个TCP分段(147、149、151)组成,而SSL层是TLSv1.2加密的握手协议:
查看152号报文,交换Server参数,这里使用了Diffie-Hellman算法,需要交换算法参数 - 到此,**已协商完毕,客户端和服务器端互相通知Change Cipher Spec(表示之后使用加密传输),并使用Encrypted Handshake Message表示这是协商好**之后第一条加密消息,以验证交换的**无误。
- 本机在155号报文中交换客户端**,如下图所示,并通知服务器
- 服务器在156号报文中发送了Session Ticket,以保持一个会话,避免每次通话都要进行**协商:
- 本机客户端通过协商好的**加密了登录信息,发送Application Data给服务器,服务器回复[ACK]之后也发送加密的Application Data,确认登录成功。
TLS加密的应用数据报文如下: - 此时已经登录完毕,服务器端发送[FIN,ACK]结束会话,客户端回复[ACK]再发送[FIN,ACK]确认结束,服务器回复[ACK],TCP四次握手结束会话。
4.3 消息传输
- 登录 QQ 后开启Wireshark抓包,发送3条消息后停止抓包。
- 由于消息是通过 UDP 协议传输,设置显示过滤器为“udp.stream eq 1”,找到OICQ协议及其他消息:
- 查看第一条OICQ报文,即第22条数据报文,显示为即时通讯软件的命令,版本号0x392b,内容为获取朋友状态,***22075,并显示了我的QQ号144******:
根据之前分析的QQ协议格式,可以逐字节分析:
02:TCPF包识别码
39 2b:客户端版本号
00 81:命令标识(129)
56 3b:命令***(22075)
55 ec 71 6f:客户的QQ号码(144********)
后面的5a~d8可能是一些附加数据,加密无法解析,不得而知了。
03:TCPF包结尾标识符 - 第二条OICQ报文即第27个数据包,内容为下载朋友群组,***22124,分析方法类似。
- 查看UDP流的所有可显示字符,发现并没有明文显示消息内容,可知QQ的消息是使用了之前交换的**加密的。
参考文献
[1] 腾讯QQ,腾讯最新财报:QQ年轻用户月活跃同比增长13%,Available: https://zhuanlan.zhihu.com/p/59986430
[2] 腾讯科技,腾讯2020年Q1财报:QQ每日总消息数及使用时长同比双位数增长,Available:https://tech.qq.com/a/20200513/066084.htm
[3] 百度百科,QQ,Available:https://baike.baidu.com/item/QQ
[4] 腾讯QQ,QQ·PC版,Available:https://im.qq.com/pcqq/
[5] Cisco,NBAR2 Protocol Pack 22.0.0 Chapter: Protocols: Q, R,Available: https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/qos_nbar/prot_lib/config_library/pp2200/nbar-prot-pack2200/nbar-prot-pack2200_chapter_01111.html#wp2970606887