天天看點

QQ協定分析之TCPF包結構

包結構類型:

TCPF包我們把它分為5類:

登入請求包(LIP,LogIn Packet),它是由用戶端向伺服器發出登入請求的資料包。

登入應答包(LRP,Login Reply Packet),它是由伺服器響應用戶端登入請求的資料包。

登出請求包(LOP,LogOut Packet),它是由用戶端向伺服器發出登出登入請求的資料包,伺服器對這個包不作應答。

用戶端其它包(CSP,Client Sent Packet),它是由用戶端向伺服器發送的其它包。

伺服器其它包(SSP,Server Sent Packet),它是由伺服器向用戶端發送的其它包。

標頭:

所有TCPF包的前7個位元組是標頭,標頭可以識别TCPF包的内容。標頭的格式為:

第0位元組:TCPF包辨別:0x02。

第1-2位元組:發送者辨別。如果是0x01 0x00,表明是由伺服器發送。用戶端的辨別與所使用的使用的QQ版本有關,目前最新版本QQ2003(0808)的辨別為0x0A 0x1D。具體的協定的格式與這個字段所辨別的用戶端版本有關。目前我們以這個最新的0A1D版本來讨論。

第3-4位元組:指令編号。具體的指令編号含義在《QQ協定概述》(Protocol Overview.rtf)中有描述。如果這個字段是0x00 0x01,那麼這是一個登出請求包。如果這個字段是0x00 0x22,而發送者辨別是0x01 0x00,那麼這是一個登入應答包。如果這個字段是0x00 0x22,而發送者辨別是其它(例如0x0A 0x1D),那麼這是一個登入請求包。其它的指令代碼表明是其它包,我們通過發送者辨別來區分它是CSP還是SSP。

第5-6位元組:指令序列号。用戶端和伺服器都有各自的目前發送序列号。每初始發出一個指令的時候,使用目前的序列号,然後把目前序列号加一,如果超過0xFFFF,就繞回。如果是響應對方發出的指令,則使用這個指令的序列号。例如,用戶端目前的序列号為0x1110,它向服務發送一個0x0016指令,它使用0x1110這個序列号,伺服器收到以後,傳回一個序列号為0x1110的0x0016指令響應。下一次,用戶端又發送一個0x0026指令,這一次它使用加一了的序列号0x1111,伺服器也響應0x1111序列号的一個0x0026指令響應。如果這是伺服器要向用戶端發送0x0017指令,它使用它自己的目前序列号,比如說0x2220,用戶端收到以後,也響應一個序列号為0x2220的0x0017指令應答。我們可以通過序列号來判斷發出的指令是否已經得到了應答,如果沒有,可以重發。伺服器對收到的指令的序列号順序沒有要求。伺服器也不會一定按照發出的順序給予應答。

包尾:

所有的TCPF包都以0x03作為包尾。在標頭和包尾中間的包資料則不同類型的包有所不同。

LIP包:

登入請求包的包資料格式為:

第7-10位元組(4 bytes):發出登入請求的QQ号碼。這是一個Big Endian(高位在前)的unsigned long型數值。例如:0x01 0x82 0x5D 0x90就是0x01825D90,轉換為十進制是25320848,表明送出請求的QQ号是25320848。

第11-26位元組(16 bytes):随機密鑰。這個密鑰由于加密後面的資料。QQ使用TEA算法來加密資料。它使用的是128bit(16 bytes)的密鑰。在0A1D版本中,這個密鑰已經固定為16個01。

第27-106位元組(80 bytes):加密後的登入包資料。

LRP包:

從第7位元組開始到包尾前:加密的登入應答包資料。解密的密鑰随用戶端版本的不同,有不同的可能。在舊有版本中,使用登入包的随機密鑰,在後期的版本,使用使用者QQ密碼的MD5 Digest。在0A1D中,使用QQ密碼的MD5 Digest的MD5 Digest(這展現了騰訊有多麼的愚昧和無恥,為了改變而改變)。LRP包内資料很重要的是16個位元組的Session Key,它用來作為以後通訊的加密密鑰。

LOP包:

它的序列号總是0xFFFF。不過,在新的版本中,好象已經沒有了這個要求。

第7-10位元組(4 bytes):發送登出登入請求的QQ号碼。

第11位元組到包尾前:加密的登出登入包資料。使用Session Key作為密鑰。

CSP包:

第7-10位元組(4 bytes):發送請求的QQ号碼。

第11位元組到包尾前:加密的包資料。使用Session Key作為密鑰。

SSP包:

從第7位元組開始到包尾前:加密的伺服器發送包資料,使用Session Key作為密鑰。

QQ加密算法概述:

QQ使用的加密算法來源于一種稱為TEA(Tiny Encryption Algorithm)加密算法。它是在1994年由英國劍橋大學的David Wheeler和Roger Needham所發明的一種加密方法。大概來說,它是使用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個位元組)。填充後的字元串是這樣組織的。第一個位元組,為填充字元數減2 OR 上0xA8。後面是填充位元組。然後是待加密的資料,最後是7個0。填充的位元組一般是0xAD,但再0A1dD版本中,會使用随機的填充字元串。一般,我們會用解密後最後是否7個零來判斷是否正确的解密。

交織算法:第一個64bits塊,按照一般的TEA加密。下一個64bit塊與上一組的加密結果XOR生成待加密資料,加密後與上一組的待加密資料XOR生成加密結果。

轉載:http://www.csna.cn/network-analyst-1382-1-1.html?sid=2881C8

繼續閱讀