協議分析TMP

來源:互聯網
上載者:User

標籤:notify   升級   roc   適合   imp   filename   抓包   即時   細節   

最近閑來有事, 分析了一個非常低端(非常低端的意思是說你不應該對她是否能取代你現有的QQ用戶端作任何可能的奢望,她只是一個實驗性的東西)的手機QQ的協議, 是手機QQ3.0, 
     所用到的TCP/HTTP通訊協定版本是1.4, 也不知道是哪一年release的了, 至少有七八年的曆久了吧, 反正就是: 功能非常弱!

    主要的分析原因是想學學網路方面的編程經驗(這是我第2次弄socket編程 :-) ), 以及學學怎麼抓包分析.

主要用到的工具軟體

        手機QQ3.0: http://www.ruan8.com/soft_5872.html

        kEmulator(Java模擬器):http://gamevina.us/kemulator-vh/

        Wireshark(協議分析):http://www.wireshark.org/download.html

        Java Decompiler(Java查看(和諧)工具):http://jd.benow.ca/

 

分析流程簡要介紹1.擷取伺服器資訊

     網上分析這個版本手機QQ的使用者不在少數, 我也瞭解到這個版本比較容易分析, 協議簡單, 所以...

     首先, 開啟這個網址:http://conf.3g.qq.com/newConf/kjava/aubin2.jsp

(注意使用unicode編碼查看, 否則可能亂碼) 然後你就會看到類似下面的東西:

SERERCONFIG_NUM=5& SERVERCONFIG_TYPE=KQQTCP,KQQTCP,KQQHTTP,KQQHTTP,KQQHTTP& SERVERCONFIG_URL=socket://58.60.12.177:14000,socket: //211.136.236.88:14000,http://tqq.tencent.com:8000,http: //mconn.tencent.com:14000,http: //kconn.tencent.com:21001&UPDATAECONFIG_NUM=1& UPDATECONFIG_VERSION=2.4.2&UPDATECONFIG_MUST=N& UPDATECONFIG_URL=http://mq.3g.qq.com/g/s?aid=mqq& UPDATECONFIG_HELPTXT=請升級到2.4.3版QQ2005(Java 版)&SMSSERVICE_NUM=2&SMSSERVICE_NAME=24小時線上,關注好友& SMSSERVICE_ADDRESS=10661700,1066170056& SMSSERVICE_TEXT=HQ,SQKJ%2c||QQNO||&SMSSERVICE_HELPTXT=不用手機上網,通過簡訊就能登陸QQ,累積線上時間真是方便,讓你QQ等級不停增長!%0a當前操作需要通過簡訊操作完成,選擇取定將發送一條簡訊,請根據收到的簡訊通知完成操作!, 關注此QQ好友,好友一上QQ馬上就會有簡訊通知你手機!隨時隨地和TA在QQ上“偶遇”,資費10元/月。%0a當前操作需要通過簡訊操作完成,選擇確定將發送一條簡訊,請根據收到的簡訊通知完成操作。

其中:

        SERERCONFIG_NUM表示目前可以使用的伺服器的個數 
        SERVERCONFIG_TYPE表示伺服器類型:KQQTCP表示TCP伺服器,KQQHTTP表示HTTP伺服器 
        SERVERCONFIG_URL:伺服器位址 
        ......(不重要)

注意:各值以逗號分隔; 索引值對間使用&符號串連.

至於手機QQ要使用哪個伺服器, 現在還不知道, 反正是其中一個, 過濾試一下就知道了.

2.過濾通訊協定

先開啟Wireshark進行網路封包過濾: 選擇一張活動網卡, 然後start.

應該馬上就可以看到,  wireshark已經顯示了很多資料包... 資料太多, 不便查看, 於是過濾顯示一下,

以QQ的第一個tcp伺服器為例: 在Wireshark的Filter Expression裡面輸入過濾運算式, 並點擊Apply應用:

 

用kEmulator運行手機QQ並登入:

接下來, 如果QQ使用了第一個伺服器的話, 那麼Wireshark將會顯示以下資訊:

沒錯, 你沒有看錯, 協議可以說全部是明文的, 完全就像是HTTP那樣的...

比如VER=1.4代表版本號碼為1.4, CMD=Login表示命令為登入, UIN=***表示QQ...............

3.協議分析

    好了, QQ和伺服器的所有通訊都是基於這種HTTP的索引值對方式, 下面列出一些常見的索引值對:

VER=1.4 表示當前使用的協議版本, 不過伺服器返回的版本可能有所不一致
CON=1 這個不知道是什麼意思, 通過查看QQ的代碼可見其貌似是固定值1
CMD=*** 當前的命令, 有Login, Logout, Query_Stat2等等.
SEQ=*** 當前命令的序號, 以此來標識不同的命令序號, 每下一次發送時, 在上一次的基礎上加1
UIN=*** 當前登入的QQ號, 不變

 

命令的規定: 
                   每個命令以\r\n結束, 這就意味著命令欄位中不能再出現其它的\r\n, 還有,要把\n換成%0D,\r換成%0D 
                   每條命令都使用UTF-8編碼, 同時命令中出現的逗號,&等要轉換url編碼, 不然要誤解釋命令.

1.    登入命令: VER=1.4&CON=1&CMD=Login&SEQ={seq}&UIN={qq}&PS={ps}&M5=1&LG=0&LC={lc}&GD={gd}&CKE=\r\n 
       伺服器響應:VER=1.1&CMD=Login&SEQ={seq}&UIN=2933278370&RES=0&RS=0&HI=60&LI=300&SG=***&SSG=207390864\r\n 
                   SEQ序號應該和你發送時一樣, 不然就是錯的. 
                   RES=0代表格服務器成功響應 
                   RS=0代表登入成功,其它均為失敗; 若失敗:則有相應的RA欄位標識錯誤資訊, 比如Password Error!

                  如果有SID或者COMP欄位, 記得儲存起來, 因為後面的某些搞不懂的命令還要用它們. 其它的比如什麼HI和LI就不知道是什麼東西了. 
                  如果出現了VC欄位, 則說明需要驗證碼資訊, 我測試了很久, 一直沒遇到, 暫時不說這個...

2.取得所有QQ好友及其基本資料 
            命令:VER=1.4&CON=1&CMD=SimpleInfo2&SEQ={seq}&UIN={qq}&SID={sid}&XP={xp}&UN=0&TO=0\r\n 
            回複:VER=1.1&CMD=SIMPLEINFO2&SEQ={seq}&&UIN={qq}&RES=0&NP=65535&SN=0&UN=&FC=&NK=\r\n 
                       XP是前面根據login命令計算出來的, 具體可以看我後面的代碼. 
                      RES=0同樣代表格服務器正確響應. 
                      NP=65535表示當前返回了所有的好友資訊, 如不是, 需要多次查詢, 你應該沒有那麼多好友吧? 
                      SN表示當前返回的好友基礎資訊的個數, (注:我全沒有寫出來) 
                      UN表示好友QQ號, 以逗號分隔(我沒列出) 
                      FC表示頭像ID 
                      NK表示暱稱, 以逗號分隔

3.取得好友狀態 
             命令:VER=1.4&CON=1&CMD=Query_Stat2&SEQ={seq}&UIN={qq}&SID=&XP={xp}&CM=2&UN=0\r\n 
            回複:VER=1.1&CMD=QUERY_STAT2&SEQ={seq}&UIN={qq}&RES=0&FN=1&SN=2&ST=10,30&UN=..\r\n 
                        FN是不是finish的意思? 不知道. 
                        SN返回資訊的個數 
                        ST狀態:10-線上,20-離線,30-離開,40-隱藏 
                        UN:QQ號, 與狀態一一對應

4.發送訊息給好友 
            命令:VER=1.4&CON=1&CMD=CLTMSG&SEQ={seq}&UIN={qq}&SID={sid]&XP={xp}&UN={qq2}&MG={mg}\r\n 
            回複:VER=1.1&CMD=CLTMSG&SEQ={seq}&UIN={qq}&RES=0 
                            UN代表好友的QQ 
                            MG表示訊息, 必須是部分url編碼的 
5. ............. 
還有幾條命令, 比如加好友, 移除朋友, 我就不寫了 , 加上有些也沒做測試.

4.類比登入

1. 可以先用GET方式擷取到伺服器IP資訊

GET  /newConf/kjava/aubin2.jsp HTTP/1.1 
Accept: text/html, application/xhtml+xml,*/* 
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/6.0) 
Accept-Encoding: utf8 
Host: conf.3g.qq.com 
Connection: Keep-Alive 
[blankline]

2. 然後建立socket並串連到伺服器

3.向伺服器發送命令

4.處理伺服器返回

5...............

5.效果展示

 

3.完結

            文章裡面只是簡要介紹了一些協議方面的東西, 細節處理, 以及完全的命令列表(我也不全知道)也沒有完全列出來,若 
需要參考, 還請查看下面的原始碼.

            參考文章: 
                                 手機QQ協議分析 (一)登陸 
                                 HTTP/1.1 Request - w3school 

            未完結的原始碼: http://pan.baidu.com/s/1c0iYYDa

作者:女孩不哭 
時間:2014年4月6日 
聯絡:QQ-191035066 
地址:http://www.cnblogs.com/memset

 分類: Socket/通訊端標籤: 通訊端, socket, 手機QQ, 協議 

參考:

協議簡單調研筆記

破解研究總結

Sync協議

  道聽途說,加上上面參考中都是提到使用Sync協議。去年項目中做過參考Microsoft Exchange ActiveSync 協議來最佳化訊息協議的方案,雖經過長時間討論定稿,但由於一些原因最終沒有實現;也從中深知Sync並不是表面上那麼簡單、那麼好用。

  Sync 有啥問題呢?

  1. SyncKey 產生維護成本

    SyncKey 在ActiveSync中為字串,用戶端不需要解析,但服務端實現要用數字自增,需要強一致性,且不能回退。

  2. 訊息的訂閱模式 採用類似Zookeeper的One time triggler 還是每條訊息都推送一條通知能

    One time trigger能夠避免並發通知時,擷取訊息時重複問題,但增加了互動成本,和用戶端實現複雜性。

  3. 自己發的訊息,SyncKey怎麼擷取

    尤其要支援多端同步發訊息,保證訊息同步;也只好訊息發完在給自己同步一遍(自己裝置發的可以不帶訊息體)

  4. 訊息推送延時加重

    Sync 訊息體擷取方式:Notify - Ack - get - Mssage, 也就是至少第四個應用程式套件才能返回訊息,在移動網路下成本很高。文中提到訊息通過單獨https請求,那麼延時更為嚴重了(嗯,實測新版本並非如此)。

 

手機用戶端不再Sync協議

抓包分析版本:Android 6.0, 抓包分析可參考:android 移動網路即時抓包

在wifi、gprs網路狀況下都相同,用戶端會依次嘗試使用80、8080、443 連接埠串連伺服器;訊息發送、接收都使用長串連進行.

 

協議格式:

4byte Packet Len(包含4位元組本身)

2byte Head Len(包含2位元組本身) + 2byte Version(1) + 4byte Operation + 4byte SeqId + ….

(Packet Len - Head Len)  Body

 

協議互動方式:

- 用戶端請求(一應一答,通過seqid匹配):

      seqid = 1 開始,依次遞增,伺服器回複相同的seqid 作為應答

- 伺服器推播通知(單向):

     seqid = 0,Operation = 7a,  用戶端不需要應答

 

主要業務:

-心跳包:

     發起用戶端請求,Operation = 0c,長度為16位元組,算是最小的包

-發訊息:

     發起用戶端請求,Operation = ed

  單點線上時發完訊息後,應答攜帶SyncKey,不再同步,多點線上時,通過通知同步SyncKey,將隨後文章分析。

-收訊息:

     1. 伺服器推送訊息, Operation = 7a,  Body 中攜帶訊息內容

    抓包分析時,通過改變訊息體大小,可能到接收方第一個包length 也會隨之變化,可確認訊息是push的。

     2. 發起用戶端單向請求,即訊息的應答Ack

-加密:

     未分析,一般來說像whatsapp那樣,使用 hash(密碼/OTP + 長串連第一個請求擷取RandomCode) 做RC4 的密鑰

 總結:

現在版本的訊息推送,並非Sync方式,而是推送+ack方式;

從他們協議設計來看,應該最開始用的是Notify + Sync Req + Sync Rsp 方式,因為協議上是不支援伺服器發起請求的;

現在改成 Sync 訊息+ 單向 Ack Req 的push方式,雖然協議上怪異, 相比Sync 訊息接收會更加及時。從以前看到的文章都是說用的Sync協議,應該是是後期版本做了修改,push方式更為高效、而且通過順序的SyncKey也能夠修複丟失的訊息。

下面一個通知包樣本:

4 byte: 265 PacketLen

2 byte: 16   Head Length

2 byte: 1     Protocol Version

4 byte: 7a   Operation

4 byte: 0   SeqId 這是一個通知性訊息

4 byte: unknow header

 

……. Body

 

Web用戶端

  web用戶端使用比較標準的Sync協議,Sync協議也比較適合web長輪詢模型。

  移動用戶端模式下,協議是二進位的而且有加密,很難分析;側重手機端,web端主體協議應該保持與移動端一致,可通過web端推測整體協議實現,json也比較好分析。

  接收一條訊息後SyncKey變化: 

  synckey:1_624161340|2_624162225|3_624162051|11_624161867|201_1420112604|1000_1420104656
  synckey:1_624161340|2_624162226|3_624162051|11_624161867|201_1420112631|1000_1420104656

  可以看出:

  - Synckey 有多個,應該是應對不同業務,其中2為為所有個人訊息、討論群組訊息,其他可能是連絡人、朋友圈、訂閱號等,201 為目前時間戳。

  - SyncKey 的值為數字自增,不是從0開始,應該有個固定的初始值。  

  - 發訊息時,發完需要自己給再自己同步回一下SyncKey。

- 下面是一條訊息增量同步處理結構,一堆要同步欄位+是否修改FlagMask,同步協議變得很簡潔。

{"BaseResponse": {"Ret": 0,"ErrMsg": ""},"AddMsgCount": 1,"AddMsgList": [{"MsgId": 1625734358,"FromUserName": "@sssss","ToUserName": "@ssssssss2","MsgType": 1,"Content": "捶地笑……","Status": 3,"ImgStatus": 1,"CreateTime": 1420109883,"VoiceLength": 0,"PlayLength": 0,"FileName": "","FileSize": "","MediaId": "","Url": "","AppMsgType": 0,"StatusNotifyCode": 0,"StatusNotifyUserName": "","RecommendInfo": {"UserName": "","NickName": "","QQNum": 0,"Province": "","City": "","Content": "","Signature": "","Alias": "","Scene": 0,"VerifyFlag": 0,"AttrStatus": 0,"Sex": 0,"Ticket": "","OpCode": 0},"ForwardFlag": 0,"AppInfo": {"AppID": "","Type": 0},"HasProductId": 0,"Ticket": ""}],"ModContactCount": 0,"ModContactList": [],"DelContactCount": 0,"DelContactList": [],"ModChatRoomMemberCount": 0,"ModChatRoomMemberList": [],"Profile": {"BitFlag": 0,"UserName": {"Buff": ""},"NickName": {"Buff": ""},"BindUin": 0,"BindEmail": {"Buff": ""},"BindMobile": {"Buff": ""},"Status": 0,"Sex": 0,"PersonalCard": 0,"Alias": "","HeadImgUpdateFlag": 0,"HeadImgUrl": "","Signature": ""},"ContinueFlag": 0,"SyncKey": {"Count": 6,"List": [{"Key": 1,"Val": 624161340},{"Key": 2,"Val": 624162166},{"Key": 3,"Val": 624162051},{"Key": 11,"Val": 624161867},{"Key": 201,"Val": 1420109883},{"Key": 1000,"Val": 1420104656}]},"SKey": ""}

最初,QQ通訊協定並沒有加密,而是直接採取明文的方式進行傳輸,到了後來才使用了加密傳輸,密碼編譯演算法一直沒有變過,使用的是blowfish演算法,但是密鑰的交換協議變得比較頻繁。其實TX也是被逼的,現在的互連網使用者比前幾年更加註重隱私安全,這麼大使用者量的通訊軟體,如果使用者與對方之間的聊天資訊可以輕易的被第三方破譯擷取,那麼使用者量肯定會離開她,而去選擇那些能夠更加保護好個人隱私的人通訊軟體。因此,隨著時間的推移和技術的發展,以前設計的協議可能會被研發者發現一些弱點,“圖謀不軌”者加以利用,會對TX造成一些潛在的風險,他不得不對協議進行修改(QQ2011正式版中的金鑰交換中對密碼的MD5計算就加入了salt的概念,這個salt就是對應的QQ號碼,後面會有詳細的描敘)。

QQ協議首選的傳輸層是UDP,如果UDP不可登陸,那麼會再嘗試使用TCP進行傳輸。UDP使用的連接埠是8000,TCP使用的連接埠是443,應用協議基本一樣,只是在通過TCP進行傳輸時,前兩個位元組為協議內容的長度(包括2個位元組)。

QQ協議中每個通訊內容都帶有一個協議頭部,如:

其中標識1一個位元組,版本號碼、命令字和序號都是2個位元組,QQ號碼有4個位元組,接下來是資料部分(已加密),最後是一個尾部標識1個位元組。

在進行協議還原的時候,最關心的就是協議頭部的命令字,需要根據不同的命令字,來進行相應的處理,最終擷取密鑰解密聊天內容。

 

QQ登陸協議金鑰交換過程,首先我們使用Wireshark抓報文分析,觀察主要用到的命令字(見上一篇Header部分的介紹)。

 

 

QQ2011登陸過程分析
命令字 含義
1、Touch Information(0×0091) 根伺服器SAY HELLO,如果對該報文做一些小動作,可以讓QQ認為,TX的伺服器或網路不能訪問…
2、Login Request(0x00ba) 未知,可以不進行處理。
3、Login Verify(0x00dd) 向伺服器發送登陸請求,需要使用密碼進行運算作為密鑰才能機密該報文,解密的報文中包含對第4步的解密密鑰。
4、Login get Information(0x00e5) 未知,但是伺服器返回的報文你必須得知道,因為這個報文中包含解密工作階段金鑰報文(第6步)的密鑰。
5、Login verify E3(0x00e3) 未知,可以不進行處理。
6、Login send Information(0×0030) 用戶端向伺服器發送sessionKey,使用第4步擷取的密鑰進行解密。

 

 

 

 

 

 

 

 

 

 

 

1、Touch Information(0×0091)

這個報文無需關心,是用戶端向伺服器在SAY HELLO…

2、Login Request(0x00ba)

未知,在此處並不重要。

3、Login Verify(0x00dd)

非常重要!!擷取工作階段金鑰首先得解密該報文。但是要解密該報文,必須得知道該登陸QQ使用者的密碼,而使用者密碼只有使用者和TX知道,第三方是不知道的(也有可能存在“不可思議”的第三方…)。資料轉送過程中使用的密碼編譯演算法是blowfish,這個演算法目前從公開的資料上來說,還沒有發現漏洞。因此,要即時擷取使用者的聊天資訊,除非已經知道密碼了,或者已經暴力破解了密碼(這裡簡單介紹一下怎麼進行暴力破解,這裡的暴力破解,當然不是類比一個QQ用戶端不停的向TX伺服器發送登陸請求,這樣太慢了,而且TX那邊也會有記錄。首先,得分析出這個報文的密鑰產生演算法[不是簡單的直接使用密碼作為密鑰],密碼編譯演算法(這個已知,是blowfish),第二,需要將對方的登陸報文截取儲存到檔案,然後寫一個程式,不停拼接字串、數字、標點符號進行組合,根據第一步分析它密鑰的產生方法產生出密鑰,然後作為blowfish演算法的密鑰,去解密報文,如果解密成功,恭喜你,你暴力破解到了一個QQ密碼。但是這種機率比較小,即使有一些,這些號碼的價值不大,扯遠了…)。

LoginVerify報文的解密密鑰產生方法,在QQ2011版本之前,是MD5(MD5(PWD)),對QQ的密碼做了兩次MD5運算。但是QQ2011版本(包括2011版本)之後,這個演算法做了一點修改,就是:MD5(MD5(PWD+QQ_NUM)),這個修改其實是非常有必要的,為什麼呢?因為隨著硬體技術的發展,以及前些年MD5彩虹表的推出,簡單密碼的MD5值非常容易就能從彩虹表中找出對應MD5值,從而得到原始字串密碼,即使TX做了兩次的MD5運算。在彩虹表的推出或以前(因為我也不知道是在這以前還是以後,呵呵),在執行MD5運算時,就有了加SALT的說法,很形象!加鹽,在這裡,QQ_NUM就是鹽,這樣就加大了使用彩虹表破解的難度。

使用密碼根據以上的演算法得出解密密鑰,解密Login Verify報文後,會得到一個新的密鑰,這個密鑰暫且就叫做verify_key。

Login Verify Reply(0x00dd)

伺服器對用戶端Login Verify報文的響應,這個報文需要verify_key作為密鑰進行解密,得出一個新的密鑰-verify_reply_key。

4、Login get information(0x00e5)

用戶端接收到伺服器的Login Verify Reply報文後,會使用verify_reply_key加密資料發送到伺服器,而這裡面又包含了一個key – get_info_key。

5、Login verify E3(0x00e3)

未知,此處可以不進行處理。

6、Login send Information(0×0030)

使用get_info_key解密該報文,得到會話KEY – session key。

回想一下:密碼是關鍵,有了密碼才能解密Login Verify(0x00dd)報文,解密了Login Verify(0x00dd),才能解密後續的的報文。其步驟是:passwd -> verify_key -> verify_reply_key -> get_info_key -> session_key。

前面兩篇簡單的介紹了QQ登陸協議金鑰交換過程以及所使用的密碼編譯演算法,知道了這兩點,就可以對它的協議進行還原了。

QQDecrypt,通過winpcap抓包,即時對QQ聊天協議進行還原。

 

除了聊天協議之外,我們還可以對QQ相關的協議進行還原,包括但不限於:

1、QQ檔案傳輸

2、QQ音頻傳輸

3、QQ視頻傳輸

4、QQ密碼驗證程式

5、QQ密碼擷取,是的,你沒有看錯,有一種主動的方法(使用者登入時)就可以獲得QQ的密碼。在網路出口擷取,而不是在用戶端進行HOOK的方式擷取。

協議分析TMP

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.