QQ在登入時,需要輸入密碼,密碼正確方能登陸成功。基本機制是:將輸入的QQ密碼進行加密,採用公開的MD5演算法,通過N次迴圈以及異或後求
反,最終計算出加密的結果,與使用者的ewh.db檔案中的密文比較後,發出“輸入密碼與上次成功登入的密碼不一致,$0A是否到伺服器驗證?”(該資訊在
BasicCtrlDll.dll的資源中,$0A在C的格式化中為斷行符號)。根據該機制,可以完成本地QQ密碼的暴力破解。 拿到QQ
2005賀歲版後,發現其加密原理並沒有新的改變,經過跟蹤和分析,編製出暴力破解本地QQ密碼的程式。 在QQ系統中,“QD”標誌代表QQ
Data,例如,我們可以在檔案User.db或ewh.db中找到這個以QD開頭的資料結構。 下面介紹ewh.db的詳細資料資訊
一、 ewh.db未經處理資料
00 00 00 00h: 51 44 01 01 03 00 04 03 00 BD AF A8 04 00 00 00
00 00 00 10h: 00 2E 06 00 07 03 00 B9 AB B4 10 00 00 00 07 22
00 00 00 20h: AA 96 56 19 A3 9E 82 19 B7 2B BD 2D 34 4A 04 03
00 00 00 30h: 00 A9 B5 B2 04 00 00 00 3C A8 93 06
其中,紅色為AST迴圈次數,蘭色為EWH加密字串,綠色為UIN QQ號(110340156=0x0693A83C,Intel體系記憶體中排列順序為:3CA89306)。
二、 ewh.db資料結構
HEX位移 DEC位移 資料 注釋 變數 標誌
0000 1 51 44 QD QQ Data 資料標誌 Flag
0002 3 01 01 保留的資料結構 Reserve
0004 5 03 00 總資料區段(Data Sections)的個數 Sections
0006 7 04 第一個資料區段(簡稱1S)的類型,可以從0x01到0x0F,04代表資料沒經過加密處理 Type1S
0007 8 03 00 1S標誌的長度。 LenFlag1S
0009 11 BD AF A8 1S標誌(例如AST、UIN、EWH等),是經過簡單的異或並求反計算處理的,此處是AST,可能是Algorithm Shift Times 或Axxx Switch Time,管他的呢! Flag1S
000C 15 04 00 00 00 1S資料的長度 LenData1S
0010 19 00 2E 06 00 = (404992) 1S資料,這裡是進行MD5轉換的次數。這個資料是同電腦的效能有關的,效能越高的電腦,在QQ註冊成功後產生的這個迴圈控制變數就越大。 Data1S 0014 20 07 2S資料的類型,07代表使用MD5進行加密 Type2S
0015 22 03 00 2S標誌的長度 LenFlag2S
0017 24 B9 AB B4 2S標誌,此處是EWH,代表本資料區段是EWH密碼資料,可能是Encrypt With Hash的縮寫 Flag2S
001A 27 10 00 00 00 2S資料的長度 LenData2S
001E 31 07 22 AA 96 56 19 A3 9E 82 19 B7 2B BD 2D 34 4A 2S資料,是經過MD5加密計算後產生的資料,當然還要經過異或並求反的計算處理,參考下面程式中的1000B858 行代碼。 Data2S 002E 47 04 3S資料的類型 Type3S
002F 48 03 00 3S標誌的長度 LenFlag3S
0031 50 A9 B5 B2 3S標誌,此處是UIN,代表本資料區段是QQ號碼,可能是:User Identifier Number的縮寫 Flag3S
0034 53 04 00 00 00 3S資料的長度 LenData3S
0038 57 3C A8 93 06 3S資料,3C A8 93 06 = 110340156 Data3S
三、 加密原理
下面VB虛擬碼的部分符號引自以上第二點《結構說明》中的變數標誌,請注意理解:
Pwd = MD5(Pwd, Len(Pwd)) ' Pwd為使用者輸入的密碼,第一輪MD5後,Pwd為16位位元組長度的MD5串。
XorKey As Long = 0 'XorKey為用於解密的位元組
For k = 1 To Data1S – 1 '因為前面已經做過一輪,所以此處要減一
Pwd = MD5(Pwd, 16)
Next k
XorKey = XorKey And &HFFFF
XorKey = (LenData2S And &HFF) Xor (LenData2S / 256)
XorKey = &HFF - XorKey '求反
For k = 1 To 16
Pwd(k) = Pwd(k) Xor XorKey
Next k
If Pwd <> Data2S Then
MsgBox "輸入密碼與上次成功登入的密碼不一致," & vbcrlf & "是否到伺服器驗證?"
End If
通過以上的流程,我真的佩服QQ的設計者,如此巨大的迴圈量,加上迴圈次數的隨機性,如果希望產生一個QQ
MD5詞典簡直不可能。雖然理論上,可以產生一個MD5字典,但是,這個字典將有1.15E+77*16個位元組之巨,因此,只好根據ewh.db檔案提供
的資料暴力破解了,不知是不是有更好的方法呢? 不過我的感覺是,迴圈次數加多了,應該會產生更多的MD5碰撞,不見得是個好事。
還有一種破解思路,也許更加直接,將在後面的文章中詳細探討。但是我只有在有時間做完實驗後才有資格評述,不在本文章的討論範圍內。
四、 破解演算法
重複進行數十萬次MD5加密,會消耗電腦很多時間,如果使用傳統的VB或VC,對於一個密碼的等待時間也是很可觀的(例如使用VB代碼,消耗
的時間可能是彙編的400倍),因此,我使用組合語言來編製低層加密解密演算法,通過MASM32編譯串連,最後用進階語言調用。通過提供演算法動態庫的方
式,方便其他有興趣的讀者自己增加豐富的功能。例如增加多線程等,這也將在以後的探討中實現。在此不做深入討論。
附帶的例子為VB和VC調用組合語言動態庫的例子,VB代碼簡單實現了通過密碼字典進行單線程破解的功能,讀者可以豐富其內容。增加更多的功能。目前,山東大學的王小雲教授已經破解了MD5演算法,下一步打算弄清楚MD5演算法和MD5解法,今天就到這裡吧。