以倚天II為例討論網路遊戲賬號密碼的破解

看雪資料發表於2004-12-20

【破解作者】 shoooo
【作者郵箱】 shoooo314@163.com
【使用工具】 softice 套裝2.7 iceext外掛,Iris
【破解平臺】 win2000 sp4 
【破解目標】 賬號,密碼
【軟體名稱】 倚天II (公測中)
【破解時間】 2004-12-20
【加殼方式】 無殼
【破解宣告】 我是一隻小菜鳥,偶得一點心得,願與大家分享:)
             本文旨在討論網路遊戲的破解思路,錯誤或不妥之處,各位批評指正
             文章中的程式碼貼上自IDA,我softice不會dump彙編程式碼
             由於更新頻繁或其它原因,記憶體地址可能存在出入

一,尋找登入包

    輸入錯誤的使用者名稱或密碼,讓TCP流盡早結束,這樣交流的資料包較少,容易找

    截包工具有很多,看個人喜好了~~我Iris用慣了
    啟動倚天II,出現登入介面,隨便找個伺服器,以使用者名稱shoooo 密碼1234登入,報錯。看看截的包包,在登入過程中,含有資料的共有9

個包,包中的資料都是無規則的16進位制,可以肯定是經過加密的。很容易發現前面7個包長度較短,內容近似。
    第8個包是客戶端發給伺服器,長度有56位元組如下
                C8 9E 23 AC BA 93 FD 12   05 72 11 85 BF D0 E7 BB
                D1 C0 A9 36 35 AA 5B 0B   05 72 11 85 BF D0 E7 BB
                F3 9C 41 BD C1 62 6B 7A   22 E5 37 46 B7 13 1E 00
                B2 BC FA 80 11 B6 2D 82 
    第9個包從伺服器發來給客戶端,長度為16位元組如下
                0E 6B 32 F1 40 39 80 69   05 72 11 85 BF D0 E7 BB 

    猜測第8個包是登入包,第9個登入包是登入響應包。

    用相同的賬號再登入一次
    重點觀察第8個包如下,並發現前32位元組與前次登入中的資料相同
                C8 9E 23 AC BA 93 FD 12   05 72 11 85 BF D0 E7 BB
                D1 C0 A9 36 35 AA 5B 0B   05 72 11 85 BF D0 E7 BB
                5C 7C 2A 03 B6 CF D3 39   FE 04 3D 80 C8 B0 E3 25
                5A F8 EA 9E 62 2A 13 87 
    
    重點觀察第9個包如下,與前次完全相同
                0E 6B 32 F1 40 39 80 69   05 72 11 85 BF D0 E7 BB 

    省略n次的相同或不同賬號密碼組合的登入試驗......

    這時我們得到如下結論
    a. 登入包長度固定為56位元組,若以相同的賬號,密碼登入,登入包的前32位元組相同。登入的錯誤響應包資料相同,固定16位元組
    b. 56,32,16都是8的倍數,加密演算法極有可能是8位元組的分組演算法


二,尋找傳送buffer

    可以從輸入的賬號,密碼開始跟,也可以從傳送的資料包反向跟,我個人傾向於後者,這裡採用後者的方法

    請出softice,symbol loader 載入ws2_32.dll,倚天2有防softice,用上iceext外掛順利躲過
    啟動客戶端至登入介面
    ctrl-d 撥出
    確認右下角顯示為倚天II的領空metein2(以下不再提示),如果不是可多試幾次或用addr命令

    下斷點bpx send
    下斷點bpx wsasend
    隨便選個伺服器,輸使用者名稱shoooo,密碼1234。點登入
    softice在send處斷下,按F11回到呼叫send的地方,看EAX的值,EAX是呼叫send後的返回值也就是實際傳送的位元組長度,我們想要看到的

是56位元組,即十六進位制的38。現在不是,ctrl-d讓它繼續跑,馬上又在send處斷下,F11,看EAX的值,不是就ctrl-d 再繼續
    約5到6次後,EAX的值顯示為38,立即對準呼叫send的EIP:499722下斷點,同時清除send,wsasend斷點,按若干次ctrl-d,讓登入過程結束

                 .text:00499716                 push    0               ; flags
                 .text:00499718                 push    eax             ; len
                 .text:00499719                 push    dword ptr [esi+24h] ; buf
                 .text:0049971C                 push    dword ptr [esi+244h] ; s
                 .text:00499722                 call    send            此處下斷點
                 .text:00499727                 mov     edieax
                 .text:00499729                 test    ediedi

    再次點選登入,這次在 EIP:499722處斷下
    下命令 d esi+24
                 B8 07 EE 01 08 08 00 00  .......        
    下命令 d 1ee07b8
                 C8 9E 23 AC BA 93 FD 12  05 72 11 85 BF D0 E7 BB 
                 D1 C0 A9 36 35 AA 5B 0B  05 72 11 85 BF D0 E7 BB
                 0D 15 41 28 73 52 5A 05  CF 87 39 DF 74 35 24 1C
                 87 7B 41 D6 18 21 BA B3
    這便是實際傳送的登入包的資料

三,尋找加密過程

    即尋找傳送buffer的資料從何而來,不斷的下記憶體斷點,直到找到我們需要的賬號,密碼的明文    

    只保留499722的eip斷點
    下斷點bpmd 1ee07b8
    以shoooo,1234再次登入
    第一次斷在1ee07b8的記憶體寫入,先別急著看,ctrl-d繼續
    第二次斷在了EIP:499722處。
    好了,到這裡清楚了,第一次斷下的地方便是對傳送buffer的頭8個位元組的寫入
    再次登入,斷在第一處

                   .text:0048F30D                 mov     [edx], eax      這裡edx值是1ee07b8
                   .text:0048F30F                 mov     [edx+4], ecx    斷在此處
                   .text:0048F312                 pop     ebx
                   .text:0048F313                 pop     ebp
                   .text:0048F314                 retn                    跳轉到48F3D0

    取消1ee07b8的記憶體斷點,F10單步跟蹤,48F314的retn語句後,跳轉到了48F3D0
                   
                   .text:0048F383                 push    ebp
                   .....省略若干行
                   .text:0048F3C0              /  push    [ebp+arg_0]        
                   .text:0048F3C3              |  push    [ebp+arg_8]
                   .text:0048F3C6              |  push    dword ptr [edi]
                   .text:0048F3C8              |  push    dword ptr [edi+4] 指向明文,待輸出密文的指標入棧
                   .text:0048F3CB              |  call    sub_48F2AA        核心加密,8位元組明文加密,8位元組密文輸出
                   .text:0048F3D0              |  add     [ebp+arg_0], 8    準備下次加密的8位元組明文
                   .text:0048F3D4              |  add     esp, 10h
                   .text:0048F3D7              |  add     edi, 8            準備下次輸出的8位元組密文
                   .text:0048F3DA              |  dec     [ebp+arg_C]
                   .text:0048F3DD              \  jnz     short loc_48F3C0  跳上去繼續加密下一組
                   .text:0048F3DF                 pop     edi
                   .text:0048F3E0                 mov     eaxesi
                   .text:0048F3E2                 pop     esi
                   .text:0048F3E3                 pop     ebp
                   .text:0048F3E4                 retn                     跳轉到499706

    48F3E4返回後,到了 499706

                   .text:004996EF                 push    edi             需要加密的位元組數
                   .text:004996F0                 lea     ecx, [esi+42h]
                   .text:004996F3                 push    ecx             指向金鑰
                   .text:004996F4                 mov     ecx, [esi+30h]
                   .text:004996F7                 add     ecxeax
                   .text:004996F9                 mov     eax, [esi+24h]
                   .text:004996FC                 add     eax, [esi+2Ch]
                   .text:004996FF                 push    ecx             指向登入包的明文(包含賬號,密碼)
                   .text:00499700                 push    eax             指向登入包的待輸出的密文,這裡是1ee07b8
                   .text:00499701                 call    sub_48F383      最外層的加密函式
                   .text:00499706                 add     [esi+2Ch], eax

    此時可以清除先前的所有斷點,在EIP: 499071處下斷,跟蹤整個加密過程,到這裡不難發現登入包的明文必須是8位元組的倍數,每8個位元組

呼叫call 48F2AA進行加密,輸出8位元組的密文

四,加密演算法求逆

   既然伺服器能對我們傳送的加密登入包作出登入失敗的反應,顯然它是可逆的

   重點觀察48F2AA處的核心加密函式,分析出相應的解密演算法
    
                   .text:0048F2AA                 push    ebp
                   .text:0048F2AB                 mov     ebpesp
                   .text:0048F2AD                 mov     eax, [ebp+arg_4]
                   .text:0048F2B0                 mov     ecx, [ebp+arg_0]
                   .text:0048F2B3                 mov     edx, [ebp+arg_8]
                   .text:0048F2B6                 push    ebx
                   .text:0048F2B7                 push    esi
                   .text:0048F2B8                 push    edi
                   .text:0048F2B9                 xor     esiesi
                   .text:0048F2BB                 mov     [ebp+arg_4], 20h  作32輪
                   .text:0048F2C2                 mov     ediecx
                   .text:0048F2C4                 shr     edi, 5
                   .text:0048F2C7                 mov     ebxecx
                   .text:0048F2C9                 shl     ebx, 4
                   .text:0048F2CC                 xor     ediebx
                   .text:0048F2CE                 add     ediecx
                   .text:0048F2D0                 mov     ebxesi
                   .text:0048F2D2                 and     ebx, 3
                   .text:0048F2D5                 mov     ebx, [edx+ebx*4]
                   .text:0048F2D8                 add     ebxesi
                   .text:0048F2DA                 xor     ediebx
                   .text:0048F2DC                 add     eaxedi
                   .text:0048F2DE                 mov     edieax
                   .text:0048F2E0                 shr     edi, 5
                   .text:0048F2E3                 mov     ebxeax
                   .text:0048F2E5                 shl     ebx, 4
                   .text:0048F2E8                 xor     ediebx
                   .text:0048F2EA                 sub     esi, 61C88647h    加密函式中唯一出現的奇怪常數
                   .text:0048F2F0                 mov     ebxesi
                   .text:0048F2F2                 shr     ebx, 0Bh
                   .text:0048F2F5                 and     ebx, 3
                   .text:0048F2F8                 mov     ebx, [edx+ebx*4]
                   .text:0048F2FB                 add     edieax
                   .text:0048F2FD                 add     ebxesi
                   .text:0048F2FF                 xor     ediebx
                   .text:0048F301                 add     ecxedi
                   .text:0048F303                 dec     [ebp+arg_4]
                   .text:0048F306                 jnz     short loc_48F2C2
                   .text:0048F308                 mov     edx, [ebp+arg_C]
                   .text:0048F30B                 pop     edi
                   .text:0048F30C                 pop     esi
                   .text:0048F30D                 mov     [edx], eax
                   .text:0048F30F                 mov     [edx+4], ecx
                   .text:0048F312                 pop     ebx
                   .text:0048F313                 pop     ebp
                   .text:0048F314                 retn

    一般到這裡就要開始體力勞動了,不過或許可以碰碰運氣 
    google 關鍵字 0x61C88647  很快便能找到這個公開的加密解密演算法 ^_^
    本文以討論思路為主,破解到此為止,在網咖玩遊戲的朋友小心哦~

相關文章