聯眾鬥地主計牌器V2.2註冊演算法分析

看雪資料發表於2015-11-15

【破解作者】 mejy【BCG】【DFCG】【FCG】【NUKE】
【作者郵箱】 yjychao@sohu.com
【作者主頁】 mejy.126.com
【使用工具】 OD1.09d,W32ASM
【破解平臺】 Win2000
【軟體名稱】 聯眾鬥地主計牌器
【下載地址】 http://www3.skycn.com/soft/1436.html
【軟體簡介】 軟體介紹:可用於聯眾一副牌和兩副牌的鬥地主遊戲,具有自動記錄已出牌、剩餘牌和剩餘張數的功能,使用者註冊後不是地主也能看底牌(二副牌時),軟體介面美觀,使用方便
更新日期:2004-02-16 14:50:20
保護方式:反除錯,採用Aspack加殼,手動脫去,檢測DELPHI編寫


【軟體大小】 641K
【加殼方式】 Aspack
【破解宣告】 我是一隻小菜鳥,偶得一點心得,願與大家分享:)哎,都沒人追演算法了,都脫殼去了。呵呵!!!
--------------------------------------------------------------------------------
【破解內容】


我們脫殼後利用W32ASM反彙編查詢"軟體已註冊",可以找到下面的地方
0045A6D0  /. 55             PUSH EBP可在此設斷,在社斷之前建議你試著註冊一次,因為不論註冊是否成功,程式會將你輸入的註冊碼儲存在登錄檔當中。並且如果註冊失敗程式不會提示,我們猜想程式每次啟動時,必然會檢測程式是否已經註冊。我們除錯也可從這裡入手。好了下一步,你用OD載入程式,並在上面的地址社斷,F9呵呵,OD被無聲無息的關閉了。^_^不要著急,看來程式用了ANTI,我們重新來過F8單步執行,一步步抽絲撥繭,具體的單步執行後,看看在那個CALL會退出程式,然後重新來過,進入上面退出程式的CALL。來到下面的地方:
0045ABC0  /$ 55             PUSH EBP
0045ABC1  |. 8BEC           MOV EBP,ESP
。。。。。。。。。。。。。
0045AC01  |. E8 9AD7FAFF    CALL un_.004083A0
0045AC06  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
0045AC09 BA 64AC4500  MOV EDX,un_.0045AC64    ;  ASCII "EXPLORER.EXE"
這裡幹什麼,哈哈如果呼叫該程式的主程式不是"EXPLORER.EXE"就強行退出
0045AC0E  |. E8 FD9BFAFF    CALL un_.00404810
0045AC13  |. 75 1D          JE SHORT un_.0045AC32 改這裡就行了
0045AC15  |. 56       PUSH ESI                     ; /ProcessId
。。。。。。。。
0045AC4C  . C3             RETN


0045A6D0  /. 55             PUSH EBP
0045A6D1  |. 8BEC           MOV EBP,ESP
。。。。。。省略
0045A703 B8 94A74500    MOV EAX,un_.0045A794        ;  ASCII "RegCode"
。。。。。。。。
0045A729  |. 8B45 F4        MOV EAX,DWORD PTR SS:[EBP-C]
0045A72C  |. E8 BBB6FFFF    CALL un_.00455DEC很明顯這裡很關鍵我們跟蹤
0045A731  |. 84C0           TEST AL,AL 條件
0045A733  |. 74 26          JE SHORT un_.0045A75B
0045A735  |. 33D2           XOR EDX,EDX
略。。。。。
0045A77D  . C3             RETN
局級分析後來到這裡
00455568  /$ 55             PUSH EBP
00455569  |. 8BEC           MOV EBP,ESP
。。。。。略
004555C2  |> 8D45 FC        /LEA EAX,DWORD PTR SS:[EBP-4]
004555C5  |. 33C9           |XOR ECX,ECX
004555C7  |. BA 04000000    |MOV EDX,4
004555CC  |. E8 EBD9FAFF    |CALL un_.00402FBC
004555D1  |. 8D45 F8        |LEA EAX,DWORD PTR SS:[EBP-8]
004555D4  |. 50             |PUSH EAX
004555D5  |. B9 03000000    |MOV ECX,3
004555DA  |. 8BD6           |MOV EDX,ESI
004555DC  |. 8B43 30        |MOV EAX,DWORD PTR DS:[EBX+30]機器碼入棧
004555DF  |. E8 40F3FAFF    |CALL un_.00404924依次取機器碼的3位進行計算
004555E4  |. 8B45 F8        |MOV EAX,DWORD PTR SS:[EBP-8]

00455603  |. 50             |PUSH EAX                          ; /Arg1
00455604  |. 8D55 FC        |LEA EDX,DWORD PTR SS:[EBP-4]                   ; |
00455607  |. 8BCF           |MOV ECX,EDI    這裡是所取字串的長度,可能是3,當取道最後幾個字元時可能是1,2            計為"值1 "  ; |
00455609  |. 8BC3           |MOV EAX,EBX                                    ; |
0045560B  |. E8 A8FBFFFF    |CALL un_.004551B8   ; un_.004551B8 
 關鍵CALL一定要跟進 ,對上面取得的機器碼進行變形,見下面得分析
00455610  |. 8B55 F4        |MOV EDX,DWORD PTR SS:[EBP-C]轉移變形後的字串
00455613  |. 8D43 34        |LEA EAX,DWORD PTR DS:[EBX+34]
00455616  |. E8 B9F0FAFF    |CALL un_.004046D4
0045561B  |. 66:83BB 820000>|CMP WORD PTR DS:[EBX+82],0
00455623  |. 74 31          |JE SHORT un_.00455656
跳走下面一段程式碼在我分析中沒用到不知幹嗎的
00455625  |. 8B43 30        |MOV EAX,DWORD PTR DS:[EBX+30]
00455628  |. E8 9FF0FAFF    |CALL un_.004046CC
0045562D  |. 8945 F0        |MOV DWORD PTR SS:[EBP-10],EAX
00455630  |. DB45 F0        |FILD DWORD PTR SS:[EBP-10]
00455633  |. 8BC6           |MOV EAX,ESI
00455635  |. 48             |DEC EAX
00455636  |. 03F8           |ADD EDI,EAX
00455638  |. 897D EC        |MOV DWORD PTR SS:[EBP-14],EDI
0045563B  |. DB45 EC        |FILD DWORD PTR SS:[EBP-14]
0045563E  |. DEF1           |FDIVRP ST(1),ST
00455640  |. E8 3FD4FAFF    |CALL un_.00402A84
00455645  |. 6BC8 64        |IMUL ECX,EAX,64
00455648  |. 8BD3           |MOV EDX,EBX
0045564A  |. 8B83 84000000  |MOV EAX,DWORD PTR DS:[EBX+84]
00455650  |. FF93 80000000  |CALL DWORD PTR DS:[EBX+80]
00455656  |> 83C6 03        |ADD ESI,3
00455659  |. 8B43 30        |MOV EAX,DWORD PTR DS:[EBX+30]
0045565C  |. E8 6BF0FAFF    |CALL un_.004046CC
00455661  |. 3BF0           |CMP ESI,EAX
00455663  |.^0F8E 59FFFFFF  JLE un_.004555C2一個迴圈處理的過程,跳回去


上面的CALL
004551B8  /$ 55             PUSH EBP

004551CC  |. BA 05000000    MOV EDX,5
004551D1  |. E8 E6DDFAFF    CALL un_.00402FBC
004551D6  |. 8A03           MOV AL,BYTE PTR DS:[EBX]   以下這幾句作用是逆序
004551D8  |. 8A53 02        MOV DL,BYTE PTR DS:[EBX+2]
004551DB  |. 8813           MOV BYTE PTR DS:[EBX],DL
004551DD  |. 8843 02        MOV BYTE PTR DS:[EBX+2],AL
004551E0  |. 8B13           MOV EDX,DWORD PTR DS:[EBX]
這裡我感覺很奇怪,我在這裡寫序號產生器時,想了好久,如何實現
例如"BFE"經上面的處理變為"EFB" 

004551E2  |. 8BC2           MOV EAX,EDX   將逆序所得的ASCII碼付給EAX
004551E4  |. 25 0000FC00    AND EAX,0FC0000  進行與運算
004551E9  |. C1E8 12        SHR EAX,12    右移0x12位
004551EC  |. 8A4406 3C      MOV AL,BYTE PTR DS:[ESI+EAX+3C] 
根據上面的結果查表,找到相應位置的字元付給AL,這就是對機器碼進行變形
在記憶體1177F14+3C的地方有一張字元表"ABCDEFGHIJKLMNOPQRST。。。" 
第一個字元結果查的的字元為"Q";
004551F0  |. 8845 F7        MOV BYTE PTR SS:[EBP-9],AL
004551F3  |. 8BC2           MOV EAX,EDX
004551F5  |. 25 00F00300    AND EAX,3F000 計算第二個字元
004551FA  |. C1E8 0C        SHR EAX,0C
004551FD  |. 8A4406 3C      MOV AL,BYTE PTR DS:[ESI+EAX+3C]查表
00455201  |. 8845 F8        MOV BYTE PTR SS:[EBP-8],AL
00455204  |. 837D FC 01     CMP DWORD PTR SS:[EBP-4],1
這裡處理當經過幾次迴圈後,當上面"值1"等於1,跳到後面在轉化後的字串上加上"="
例如我得"BFEB0C28"經兩次迴圈後剩下"28"沒處理,這時在下面一個地方跳。
00455208  |. 7E 13          JLE SHORT un_.0045521D
0045520A  |. 8BC2           MOV EAX,EDX
0045520C  |. 25 C00F0000    AND EAX,0FC0  計算得到第三個字元
00455211  |. C1E8 06        SHR EAX,6
00455214  |. 8A4406 3C      MOV AL,BYTE PTR DS:[ESI+EAX+3C]查表
00455218  |. 8845 F9        MOV BYTE PTR SS:[EBP-7],AL
0045521B  |. EB 04          JMP SHORT un_.00455221
0045521D  |> C645 F9 3D     MOV BYTE PTR SS:[EBP-7],3D 
比較字串轉換是否結束如果結束就在轉換後的字串後面加上"="所以轉換後的結果肯定為"********="的形式
00455221  |> 837D FC 02     CMP DWORD PTR SS:[EBP-4],2
00455225  |. 7E 0E          JLE SHORT un_.00455235
00455227  |. 8BC2           MOV EAX,EDX
00455229  |. 83E0 3F        AND EAX,3F
0045522C  |. 8A4406 3C      MOV AL,BYTE PTR DS:[ESI+EAX+3C]
00455230  |. 8845 FA        MOV BYTE PTR SS:[EBP-6],AL
00455233  |. EB 04          JMP SHORT un_.00455239
00455235  |> C645 FA 3D     MOV BYTE PTR SS:[EBP-6],3D加上"="
00455239  |> 8B45 08        MOV EAX,DWORD PTR SS:[EBP+8]
0045523C  |. 8D55 F7        LEA EDX,DWORD PTR SS:[EBP-9]
0045523F  |. B9 05000000    MOV ECX,5
00455244  |. E8 33F4FAFF    CALL un_.0040467C
00455249  |. 5E             POP ESI
0045524A  |. 5B             POP EBX
0045524B  |. 8BE5           MOV ESP,EBP
0045524D  |. 5D             POP EBP
0045524E  . C2 0400        RETN 4  返回後來到下面

004559CC   $ 55             PUSH EBP

00455A5D   . 8B45 EC        MOV EAX,DWORD PTR SS:[EBP-14]
00455A60   . E8 67ECFAFF    CALL un_.004046CC這兒取得轉化後字串的長度
00455A65   . 8BF0           MOV ESI,EAX
00455A67   . 85F6           TEST ESI,ESI
00455A69   . 7E 3E          JLE SHORT un_.00455AA9
00455A6B   . BB 01000000    MOV EBX,1
00455A70   > 8B45 EC        MOV EAX,DWORD PTR SS:[EBP-14]
下面是一個計算註冊碼的迴圈
00455A73   . 807C18 FF 3D   CMP BYTE PTR DS:[EAX+EBX-1],3D
比較字串中所取的的字元是否是"="如果是則跳走。不對這裡進行處理
00455A78   . 74 2B          JE SHORT un_.00455AA5
00455A7A   . 8D45 E8        LEA EAX,DWORD PTR SS:[EBP-18]
00455A7D   . 50             PUSH EAX
00455A7E   . 8D45 E4        LEA EAX,DWORD PTR SS:[EBP-1C]
00455A81   . 8B55 EC        MOV EDX,DWORD PTR SS:[EBP-14]
00455A84   . 8A541A FF      MOV DL,BYTE PTR DS:[EDX+EBX-1]
依次取字串的每一位
00455A88   . E8 67EBFAFF    CALL un_.004045F4
00455A8D   . 8B55 E4        MOV EDX,DWORD PTR SS:[EBP-1C]
00455A90   . 8A4D F7        MOV CL,BYTE PTR SS:[EBP-9]
00455A93   . 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00455A96   . E8 61000000    CALL un_.00455AFC  這裡又是關鍵我們跟進見下面
00455A9B   . 8B55 E8        MOV EDX,DWORD PTR SS:[EBP-18]
00455A9E   . 8BC7           MOV EAX,EDI
00455AA0   . E8 2FECFAFF    CALL un_.004046D4這裡是對上面返回的字串進行連線
00455AA5   > 43             INC EBX
00455AA6   . 4E             DEC ESI
00455AA7   .^75 C7          JNZ SHORT un_.00455A70

00455ABE   . C3             RETN



上面的將變形後的機器碼經過計算求出註冊碼
00455AFC  /$ 55             PUSH EBP
00455AFD  |. 8BEC           MOV EBP,ESP
00455AFF  |. 83C4 F4        ADD ESP,-0C
00455B02  |. 53             PUSH EBX
00455B03  |. 8BD9           MOV EBX,ECX
00455B05  |. 8955 FC        MOV DWORD PTR SS:[EBP-4],EDX這裡是上面取得字元
00455B08  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00455B0B  |. E8 A4EDFAFF    CALL un_.004048B4
00455B10  |. 33C0           XOR EAX,EAX
00455B12  |. 55             PUSH EBP
00455B13  |. 68 615B4500    PUSH un_.00455B61
00455B18  |. 64:FF30        PUSH DWORD PTR FS:[EAX]
00455B1B  |. 64:8920        MOV DWORD PTR FS:[EAX],ESP
00455B1E  |. 8B45 08        MOV EAX,DWORD PTR SS:[EBP+8]
00455B21  |. 50             PUSH EAX
00455B22  |. 33C0           XOR EAX,EAX
00455B24  |. 8AC3           MOV AL,BL
00455B26  |. 8B1485 28CC450>MOV EDX,DWORD PTR DS:[EAX*4+45CC28]
這裡又有一張固定的表
"AL9=HtGzUJ4mvIJY3D7ykQgAYf+TjWCd1RhZl5oEOeBF8bF0ubKrVSaM6qp2n/xcN"
下面將知道他是幹嗎的!
00455B2D  |. 8B45 FC        MOV EAX,DWORD PTR SS:[EBP-4]
00455B30  |. E8 D3EEFAFF    CALL un_.00404A08關鍵CALL我們可以看看跟進
主要思想是在上面的字串中查詢取得上面位置字元的下標
00455B35  |. 8945 F4        MOV DWORD PTR SS:[EBP-C],EAX           ; |
這裡EAX中儲存的就是那個下標
00455B38  |. C645 F8 00     MOV BYTE PTR SS:[EBP-8],0                  ; |
00455B3C  |. 8D55 F4        LEA EDX,DWORD PTR SS:[EBP-C]             ; |
00455B3F  |. 33C9           XOR ECX,ECX                              ; |
00455B41  |. B8 785B4500    MOV EAX,un_.00455B78         ; |ASCII "%0.2d"
00455B46  |. E8 E136FBFF    CALL un_.0040922C   ; un_.0040922C
這裡對下標進行轉化,將他轉化成十進位制的字串
例如字元"H"的位置是1,那麼轉化後形成的字串為"01";
00455B4B  |. 33C0           XOR EAX,EAX
00455B4D  |. 5A             POP EDX
00455B4E  |. 59             POP ECX
00455B4F  |. 59             POP ECX
00455B50  |. 64:8910        MOV DWORD PTR FS:[EAX],EDX
00455B53  |. 68 685B4500    PUSH un_.00455B68
00455B58  |> 8D45 FC        LEA EAX,DWORD PTR SS:[EBP-4]
00455B5B  |. E8 B4E8FAFF    CALL un_.00404414
00455B60  . C3             RETN


--------------------------------------------------------------------------------
【破解總結】


總結一下注冊演算法思想:大體是先根據取得的機器號(如何取得機器號,我跟了半天沒找到誰找到了,TELL ME)然後對他進行變形,每次取機器碼的3位,進行轉化演算法較煩見0045560B處的CALL,然後對變形後的字串的每一位一次查表,如果遇到"=",拋棄掉,否則取該字串在固定串2,的位置。然後將位置下標轉化成字串。逐位連線就形成了註冊碼!這個軟體演算法的CALL比較多,很容易糊塗。很感謝你能看到這裡!希望您看懂了!
我用VC寫了一個序號產生器,誰有興趣改變一下程式,使註冊碼出現在EDIT筐中,當然高手就免了!很簡單的,就一個地方。

--------------------------------------------------------------------------------
【版權宣告】 本文純屬技術交流, 轉載請註明作者並保持文章的完整, 謝謝!

相關文章