拱豬大戰 1.8破解手記--演算法分析

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

拱豬大戰 1.8破解手記--演算法分析
作者:newlaos[DFCG]


軟體名稱:拱豬大戰 1.8(棋牌遊戲)
整理日期:2003.3.14
檔案大小:1107KB
軟體授權:共享軟體
使用平臺:Win9x/Me/NT/2000/XP
釋出公司:"http://www.joygames.com/
軟體簡介:支援對家結盟模式,支援現在流行的拱雙豬,允許亮牌,支援"除羊全亮",支援幾乎所有的拱豬規則;可以隨時察看亮牌和已經得到的分數;具有積分榜和英雄榜,更加你的成就感;自由的設計軟體皮膚;軟體介面友好,易用性強.

加密方式:註冊碼
功能限制:次數限制
PJ工具:TRW20001.23註冊版、PE-SCAN3.31、W32Dasm8.93黃金版,FI2.5
PJ日期:2003-03-22
作者newlaos申明:只是學習,請不用於商業用途或是將本文方法制作的序號產生器任意傳播,造成後果,本人一概不負。

1、先用FI2.5看一下主程式“拱豬大戰.exe”,加了個ASPACK2.12的殼,先脫了它。這種殼很容易脫,用PE-scan3.31很快搞定。脫殼生成檔案UNPACK.EXE

2、用W32Dasm8.93黃金版對UNPACK.EXE進行靜態反彙編,再用串式資料參考,找到"註冊碼輸入錯誤,請重新檢查後輸入!"(很經典的句子),雙擊來到下面程式碼段。這樣就找到註冊碼的計算部分。

3、再用TRW20001.23註冊版進行動態跟蹤,下斷BPX 00425ACE(通常在註冊成功與否的前面一些下斷,這樣,才能找到關鍵部分),先輸入假碼78787878

......
......
:00425ACE 66C747101400            mov [edi+10], 0014
:00425AD4 33C9                    xor ecx, ecx
:00425AD6 894DF4                  mov dword ptr [ebp-0C], ecx
:00425AD9 8D55F4                  lea edx, dword ptr [ebp-0C]
:00425ADC FF471C                  inc [edi+1C]
:00425ADF 8B830C030000            mov eax, dword ptr [ebx+0000030C]
:00425AE5 E8D6EB0300              call 004646C0
:00425AEA 8D4DF4                  lea ecx, dword ptr [ebp-0C]
:00425AED 33D2                    xor edx, edx
:00425AEF 8B01                    mov eax, dword ptr [ecx]
:00425AF1 50                      push eax
:00425AF2 8955F0                  mov dword ptr [ebp-10], edx
:00425AF5 FF471C                  inc [edi+1C]
:00425AF8 8D55F0                  lea edx, dword ptr [ebp-10]
:00425AFB 8B8310030000            mov eax, dword ptr [ebx+00000310]
:00425B01 E8BAEB0300              call 004646C0
:00425B06 8D4DF0                  lea ecx, dword ptr [ebp-10]
:00425B09 8B01                    mov eax, dword ptr [ecx]  <===EAX=78787878
:00425B0B 50                      push eax             <===這裡壓進去的還是78787878
:00425B0C E81F39FFFF              call 00419430        <===最後推斷,這裡就是演算法CALL了,F8跟進
:00425B11 83C408                  add esp, 00000008
:00425B14 BA02000000              mov edx, 00000002
:00425B19 50                      push eax             <===這裡EAX的值就決定了,不能為0
:00425B1A 8D45F0                  lea eax, dword ptr [ebp-10]
:00425B1D FF4F1C                  dec [edi+1C]
:00425B20 E88B6B0900              call 004BC6B0
:00425B25 FF4F1C                  dec [edi+1C]
:00425B28 8D45F4                  lea eax, dword ptr [ebp-0C]
:00425B2B BA02000000              mov edx, 00000002
:00425B30 E87B6B0900              call 004BC6B0
:00425B35 59                      pop ecx              <===說明,最終判斷是由堆疊最上面的值決定!向上看
:00425B36 84C9                    test cl, cl          <===如果,ECX的低位是0,則下面就跳轉了,也就OVER了
:00425B38 0F84EF010000            je 00425D2D          <===關鍵跳轉
:00425B3E B201                    mov dl, 01
:00425B40 A1808F4900              mov eax, dword ptr [00498F80]
:00425B45 E836350700              call 00499080
:00425B4A 8BF0                    mov esi, eax
:00425B4C BA02000080              mov edx, 80000002
:00425B51 8BC6                    mov eax, esi
:00425B53 E8CC690900              call 004BC524
:00425B58 66C747102000            mov [edi+10], 0020

.......
.......
中間這段程式碼的主要功能,就是在驗證註冊碼正確後,把註冊資訊寫入登錄檔,與關鍵演算法無關,所以省略
.......
.......

* Possible StringData Ref from Data Obj ->"資訊"
                                 |
:00425CCC 6800E24F00              push 004FE200

* Possible StringData Ref from Data Obj ->"註冊成功!註冊版本在重新啟動程式後生效!"
                                 |
:00425CD1 68D9E14F00              push 004FE1D9
:00425CD6 8BC3                    mov eax, ebx
:00425CD8 E873500400              call 0046AD50
:00425CDD 50                      push eax
:00425CDE E8FD1B0D00              call 004F78E0
:00425CE3 BAEBFFFFFF              mov edx, FFFFFFEB
:00425CE8 8B83F8020000            mov eax, dword ptr [ebx+000002F8]
:00425CEE E8F16C0900              call 004BC9E4
:00425CF3 8BD0                    mov edx, eax
:00425CF5 8B83F8020000            mov eax, dword ptr [ebx+000002F8]
:00425CFB FFD2                    call edx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00425BBC(C)
|
:00425CFD 8BC6                    mov eax, esi
:00425CFF E8EC330700              call 004990F0
:00425D04 8BDE                    mov ebx, esi
:00425D06 895DCC                  mov dword ptr [ebp-34], ebx
:00425D09 85DB                    test ebx, ebx
:00425D0B 7439                    je 00425D46
:00425D0D 8B03                    mov eax, dword ptr [ebx]
:00425D0F 8945D0                  mov dword ptr [ebp-30], eax
:00425D12 66C747106800            mov [edi+10], 0068
:00425D18 BA03000000              mov edx, 00000003
:00425D1D 8B45CC                  mov eax, dword ptr [ebp-34]
:00425D20 8B08                    mov ecx, dword ptr [eax]
:00425D22 FF51FC                  call [ecx-04]
:00425D25 66C747105C00            mov [edi+10], 005C
:00425D2B EB19                    jmp 00425D46

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00425B38(C)                                <===由於上一行是無條件跳轉,所以,關鍵跳轉在00425B38
|
:00425D2D 6A40                    push 00000040

* Possible StringData Ref from Data Obj ->"資訊"
                                 |
:00425D2F 6826E24F00              push 004FE226

* Possible StringData Ref from Data Obj ->"註冊碼輸入錯誤,請重新檢查後輸入!"
                                 |
:00425D34 6805E24F00              push 004FE205
:00425D39 8BC3                    mov eax, ebx
:00425D3B E810500400              call 0046AD50
:00425D40 50                      push eax
:00425D41 E89A1B0D00              call 004F78E0

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00425D0B(C), :00425D2B(U)
|
:00425D46 8B17                    mov edx, dword ptr [edi]
:00425D48 64891500000000          mov dword ptr fs:[00000000], edx

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00425AC9(U), :00425C0D(U)
|
:00425D4F 5F                      pop edi
:00425D50 5E                      pop esi
:00425D51 5B                      pop ebx
:00425D52 8BE5                    mov esp, ebp
:00425D54 5D                      pop ebp
:00425D55 C3                      ret
......
......


------00425B0C  call 00419430  演算法CALL,F8跟進到下列程式碼段-----------------------

:00419430 55                      push ebp
:00419431 8BEC                    mov ebp, esp
:00419433 81C4BCFEFFFF            add esp, FFFFFEBC
:00419439 53                      push ebx
:0041943A 56                      push esi
:0041943B 57                      push edi
:0041943C 8D7DCC                  lea edi, dword ptr [ebp-34]
:0041943F B830AC4F00              mov eax, 004FAC30
:00419444 E88B750900              call 004B09D4
:00419449 C7471C02000000          mov [edi+1C], 00000002
:00419450 8D550C                  lea edx, dword ptr [ebp+0C]
:00419453 8D450C                  lea eax, dword ptr [ebp+0C]
:00419456 E835310A00              call 004BC590
:0041945B FF471C                  inc [edi+1C]
:0041945E 8D5508                  lea edx, dword ptr [ebp+08]
:00419461 66C747100800            mov [edi+10], 0008
:00419467 8D4508                  lea eax, dword ptr [ebp+08]
:0041946A E821310A00              call 004BC590
:0041946F FF471C                  inc [edi+1C]
:00419472 57                      push edi
:00419473 8DBDBCFEFFFF            lea edi, dword ptr [ebp+FFFFFEBC]

* Possible StringData Ref from Data Obj ->""
                                 |
:00419479 BEF4814F00              mov esi, 004F81F4
:0041947E B90C000000              mov ecx, 0000000C
:00419483 F3                      repz
:00419484 A5                      movsd
:00419485 837D0800                cmp dword ptr [ebp+08], 00000000
:00419489 5F                      pop edi
:0041948A 7408                    je 00419494
:0041948C 8B4508                  mov eax, dword ptr [ebp+08]  <===EAX=78787878
:0041948F 8B50FC                  mov edx, dword ptr [eax-04]  <===EDX=8(為輸入的註冊碼長度)
:00419492 EB02                    jmp 00419496              <===從這裡跳走

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041948A(C)
|
:00419494 33D2                    xor edx, edx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419492(U)
|
:00419496 83FA0B                  cmp edx, 0000000B        
          <===跳到這裡,可以看出,規定註冊註冊碼必須等於0xB(也就是11位),將輸入的假碼改為78787878787,重新來
:00419499 7432                    je 004194CD        <===當註冊碼長度為11位時,這裡要跳走
:0041949B 33C0                    xor eax, eax
:0041949D BA02000000              mov edx, 00000002
:004194A2 50                      push eax
:004194A3 8D4508                  lea eax, dword ptr [ebp+08]
:004194A6 FF4F1C                  dec [edi+1C]
:004194A9 E802320A00              call 004BC6B0
:004194AE FF4F1C                  dec [edi+1C]
:004194B1 8D450C                  lea eax, dword ptr [ebp+0C]
:004194B4 BA02000000              mov edx, 00000002
:004194B9 E8F2310A00              call 004BC6B0
:004194BE 58                      pop eax
:004194BF 8B17                    mov edx, dword ptr [edi]
:004194C1 64891500000000          mov dword ptr fs:[00000000], edx
:004194C8 E9B0020000              jmp 0041977D          <===如果,輸入的假碼長度不為11,則從這裡跳到OVER

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419499(C)
|
:004194CD BE01000000              mov esi, 00000001     <===從上面跳到這裡
:004194D2 8D8548FFFFFF            lea eax, dword ptr [ebp+FFFFFF48]
:004194D8 8945C8                  mov dword ptr [ebp-38], eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004195A3(C)
|     <===從這一行開始到004195A3是一個迴圈結構,主要的功能是檢測輸入的11位註冊碼,是不是數字
:004194DB 66C747101400            mov [edi+10], 0014    
:004194E1 33D2                    xor edx, edx
:004194E3 8D4DFC                  lea ecx, dword ptr [ebp-04]
:004194E6 8955FC                  mov dword ptr [ebp-04], edx
:004194E9 51                      push ecx
:004194EA FF471C                  inc [edi+1C]
:004194ED B901000000              mov ecx, 00000001
:004194F2 8BD6                    mov edx, esi
:004194F4 8D4508                  lea eax, dword ptr [ebp+08]
:004194F7 E82C330A00              call 004BC828
:004194FC 837DFC00                cmp dword ptr [ebp-04], 00000000
:00419500 7405                    je 00419507
:00419502 8B45FC                  mov eax, dword ptr [ebp-04]
:00419505 EB05                    jmp 0041950C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419500(C)
|
:00419507 B888874F00              mov eax, 004F8788

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419505(U)
|
:0041950C 8A18                    mov bl, byte ptr [eax]
:0041950E FF4F1C                  dec [edi+1C]
:00419511 8D45FC                  lea eax, dword ptr [ebp-04]
:00419514 BA02000000              mov edx, 00000002
:00419519 E892310A00              call 004BC6B0
:0041951E 0FBEC3                  movsx eax, bl  <===這裡就是將依次取出的註冊碼的ASC碼值的(16進製表示形式),放入EAX
:00419521 83F830                  cmp eax, 00000030   --
:00419524 7C05                    jl 0041952B           |
:00419526 83F839                  cmp eax, 00000039     |===>很典型的一段程式碼,功能是看輸入的註冊碼每位是不是數字
:00419529 7E32                    jle 0041955D        -- ===>如果是數字,這裡小跳

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419524(C)
|
:0041952B 33C0                    xor eax, eax          
        <===一但有一位是註冊碼不是數字,就來到這裡,隨著00419558的無條件跳轉,也就是要OVER了
:0041952D BA02000000              mov edx, 00000002
:00419532 50                      push eax
:00419533 8D4508                  lea eax, dword ptr [ebp+08]
:00419536 FF4F1C                  dec [edi+1C]
:00419539 E872310A00              call 004BC6B0
:0041953E FF4F1C                  dec [edi+1C]
:00419541 8D450C                  lea eax, dword ptr [ebp+0C]
:00419544 BA02000000              mov edx, 00000002
:00419549 E862310A00              call 004BC6B0
:0041954E 58                      pop eax
:0041954F 8B17                    mov edx, dword ptr [edi]
:00419551 64891500000000          mov dword ptr fs:[00000000], edx
:00419558 E920020000              jmp 0041977D        

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419529(C)
|
:0041955D 66C747102000            mov [edi+10], 0020  <===每次迴圈(共11次了),只要註冊都是數字,就會從上面小跳到這裡
:00419563 33C9                    xor ecx, ecx
:00419565 8D45F8                  lea eax, dword ptr [ebp-08]
:00419568 894DF8                  mov dword ptr [ebp-08], ecx
:0041956B 50                      push eax
:0041956C FF471C                  inc [edi+1C]
:0041956F 8D4508                  lea eax, dword ptr [ebp+08]
:00419572 B901000000              mov ecx, 00000001
:00419577 8BD6                    mov edx, esi
:00419579 E8AA320A00              call 004BC828
:0041957E 8D45F8                  lea eax, dword ptr [ebp-08]
:00419581 E886330A00              call 004BC90C
:00419586 8B55C8                  mov edx, dword ptr [ebp-38]
:00419589 8902                    mov dword ptr [edx], eax
:0041958B FF4F1C                  dec [edi+1C]
:0041958E 8D45F8                  lea eax, dword ptr [ebp-08]
:00419591 BA02000000              mov edx, 00000002
:00419596 E815310A00              call 004BC6B0
:0041959B 46                      inc esi
:0041959C 8345C804                add dword ptr [ebp-38], 00000004
:004195A0 83FE0B                  cmp esi, 0000000B      <===ESI實際上是個計數器
:004195A3 0F8E32FFFFFF            jle 004194DB           <===迴圈11次後,這裡就不再跳轉了!
:004195A9 BE01000000              mov esi, 00000001      
       <===呵呵,這個計數器又被初始化了。也就是又要迴圈了,幾次呢看下面0041967C行,原來是9次。
:004195AE 8D85F0FEFFFF            lea eax, dword ptr [ebp+FFFFFEF0]
:004195B4 8945C4                  mov dword ptr [ebp-3C], eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041967F(C)
|      <===從這一行開始到0041967F是一個迴圈結構,迴圈9次,正好是取機器碼的9次了。我的機器碼是642652146
:004195B7 66C747102C00            mov [edi+10], 002C
:004195BD 33D2                    xor edx, edx
:004195BF 8D4DF4                  lea ecx, dword ptr [ebp-0C]
:004195C2 8955F4                  mov dword ptr [ebp-0C], edx
:004195C5 51                      push ecx
:004195C6 FF471C                  inc [edi+1C]
:004195C9 B901000000              mov ecx, 00000001
:004195CE 8BD6                    mov edx, esi
:004195D0 8D450C                  lea eax, dword ptr [ebp+0C] <===EAX裡放的是一個地址指標,指向機器碼
:004195D3 E850320A00              call 004BC828               <===這裡當然是將機器碼處理一下了。
:004195D8 837DF400                cmp dword ptr [ebp-0C], 00000000
:004195DC 7405                    je 004195E3
:004195DE 8B45F4                  mov eax, dword ptr [ebp-0C]
:004195E1 EB05                    jmp 004195E8

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004195DC(C)
|
:004195E3 B889874F00              mov eax, 004F8789

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004195E1(U)
|
:004195E8 8A18                    mov bl, byte ptr [eax]
:004195EA FF4F1C                  dec [edi+1C]
:004195ED 8D45F4                  lea eax, dword ptr [ebp-0C]
:004195F0 BA02000000              mov edx, 00000002
:004195F5 E8B6300A00              call 004BC6B0
:004195FA 0FBEC3                  movsx eax, bl            
:004195FD 83F830                  cmp eax, 00000030        ----很典型的一小段程式碼(功能同上)
:00419600 7C05                    jl 00419607              ----
:00419602 83F839                  cmp eax, 00000039        ----
:00419605 7E32                    jle 00419639             ----這裡小跳

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419600(C)
|
:00419607 33C0                    xor eax, eax
:00419609 BA02000000              mov edx, 00000002
:0041960E 50                      push eax
:0041960F 8D4508                  lea eax, dword ptr [ebp+08]
:00419612 FF4F1C                  dec [edi+1C]
:00419615 E896300A00              call 004BC6B0
:0041961A FF4F1C                  dec [edi+1C]
:0041961D 8D450C                  lea eax, dword ptr [ebp+0C]
:00419620 BA02000000              mov edx, 00000002
:00419625 E886300A00              call 004BC6B0
:0041962A 58                      pop eax
:0041962B 8B17                    mov edx, dword ptr [edi]
:0041962D 64891500000000          mov dword ptr fs:[00000000], edx
:00419634 E944010000              jmp 0041977D

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419605(C)
|
:00419639 66C747103800            mov [edi+10], 0038          <===小跳來到這裡
:0041963F 33C9                    xor ecx, ecx
:00419641 8D45F0                  lea eax, dword ptr [ebp-10]
:00419644 894DF0                  mov dword ptr [ebp-10], ecx
:00419647 50                      push eax
:00419648 FF471C                  inc [edi+1C]
:0041964B 8D450C                  lea eax, dword ptr [ebp+0C]
:0041964E B901000000              mov ecx, 00000001
:00419653 8BD6                    mov edx, esi
:00419655 E8CE310A00              call 004BC828
:0041965A 8D45F0                  lea eax, dword ptr [ebp-10]
:0041965D E8AA320A00              call 004BC90C
:00419662 8B55C4                  mov edx, dword ptr [ebp-3C]
:00419665 8902                    mov dword ptr [edx], eax
:00419667 FF4F1C                  dec [edi+1C]
:0041966A 8D45F0                  lea eax, dword ptr [ebp-10]
:0041966D BA02000000              mov edx, 00000002
:00419672 E839300A00              call 004BC6B0
:00419677 46                      inc esi
:00419678 8345C404                add dword ptr [ebp-3C], 00000004
:0041967C 83FE09                  cmp esi, 00000009
:0041967F 0F8E32FFFFFF            jle 004195B7          <===迴圈9次後,這裡就不再跳轉了!
:00419685 33F6                    xor esi, esi          <===ESI被清0了。又要迴圈了。
:00419687 8D95BCFEFFFF            lea edx, dword ptr [ebp+FFFFFEBC]  
:0041968D 8D8548FFFFFF            lea eax, dword ptr [ebp+FFFFFF48]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004196A8(C)                                          
|                 <===這一行到004196A5,又構成一個小迴圈
:00419693 8B1A                    mov ebx, dword ptr [edx]
     <===這裡出現11次的數字是固定的(4,A,6,8,9,2,1,3,5,7,B ),估計是機器碼的變形(後來發現沒有用)
:00419695 8B08                    mov ecx, dword ptr [eax]
     <===這裡依次就是我們輸入的註冊碼的了(7,8,7,8,7,8,7,8,7,8,7)
:00419697 83C004                  add eax, 00000004
:0041969A 83C204                  add edx, 00000004    
:0041969D 46                      inc esi
:0041969E 898C9D14FFFFFF          mov dword ptr [ebp+4*ebx-000000EC], ecx
:004196A5 83FE0A                  cmp esi, 0000000A    <===由於初始值是0,所以這裡也要迴圈11次,
:004196A8 7EE9                    jle 00419693         <===迴圈11次後,不再跳轉了。
:004196AA BE01000000              mov esi, 00000001    <===又初始化了,呵呵,又要迴圈了
:004196AF 8D55A0                  lea edx, dword ptr [ebp-60]
:004196B2 8D8518FFFFFF            lea eax, dword ptr [ebp+FFFFFF18]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004196C6(C)    <===這一行到004196C6,又構成一個小迴圈
|
:004196B8 8B08                    mov ecx, dword ptr [eax]

          ****注:這裡的ECX的取值如下1、取輸入的註冊碼第7位(7)
                                     2、取輸入的註冊碼第6位(8)
                                     3、取輸入的註冊碼第8位(8)
                                     4、取輸入的註冊碼第1位(7)
                                     5、取輸入的註冊碼第9位(7)
                                     6、取輸入的註冊碼第3位(7)
                                     7、取輸入的註冊碼第10位(8)
                                     8、取輸入的註冊碼第4位(8)
                                     9、取輸入的註冊碼第5位(7)
          ****注:這裡可以推斷出輸入的註冊碼第2位和第11位,可以為任意數字!
                  由於是定位取值,所在用假碼78787878787將很定位,所以將假碼改為12345678901,重新來。
                  對應的取值變碼是768193045,記住這個對應關係後面用得到!

:004196BA 890A                    mov dword ptr [edx], ecx
    <===取得這些值依次放在EDX步進為4的位置上,ECX的初始地址8AF250正好與最後比較的地址相同,故要仔細觀察其變化
:004196BC 46                      inc esi
:004196BD 83C204                  add edx, 00000004    
:004196C0 83C004                  add eax, 00000004
:004196C3 83FE09                  cmp esi, 00000009  <===初始值是1,所以要迴圈9次。
:004196C6 7EF0                    jle 004196B8       <===迴圈9次後,不再跳轉了。
:004196C8 BB04000000              mov ebx, 00000004
:004196CD BE01000000              mov esi, 00000001  <===又初始化了,呵呵,又要迴圈了
:004196D2 3BDE                    cmp ebx, esi       <===不相等
:004196D4 7C2B                    jl 00419701        <===不會跳

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004196FF(C)      
             <===這一行到004196FF,又構成一個小迴圈,            
:004196D6 8D8574FFFFFF            lea eax, dword ptr [ebp+FFFFFF74]
:004196DC 50                      push eax
:004196DD 8D559C                  lea edx, dword ptr [ebp-64]
:004196E0 52                      push edx
:004196E1 E8FAFCFFFF              call 004193E0      
             <===第一個CALL會使我們所關心的值(以8AF250為起始地址的步進為4的位置)有變化,F8進去看得究竟吧
:004196E6 83C408                  add esp, 00000008
:004196E9 8D4D9C                  lea ecx, dword ptr [ebp-64]
:004196EC 51                      push ecx
:004196ED 8D8574FFFFFF            lea eax, dword ptr [ebp+FFFFFF74]
:004196F3 50                      push eax
:004196F4 E8E7FCFFFF              call 004193E0
             <===第二個同樣的CALL使我們所關心的值有變化
:004196F9 83C408                  add esp, 00000008
:004196FC 46                      inc esi            <===esi為計數器,每次加1
:004196FD 3BDE                    cmp ebx, esi       <===EBX=4
:004196FF 7DD5                    jge 004196D6      
             <===這裡迴圈4次,但由於有了兩個同樣的CALL,所以實際上768193045(假碼的變形)已經被處理了8次,如何處理的呢?我們再研究一下call 004193E0(功能在下面有說),
             ****  將768193045處理後為:524472195
                   將524472195處理後為:502225745
                   將502225745處理後為:055757895
                   將055757895處理後為:550523445
                   將550523445處理後為:969148595
                   將969148595處理後為:815477145
                   將815477145處理後為:083225295
                   將083225295處理後為:826757845                              

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004196D4(C)
|
:00419701 BE01000000              mov esi, 00000001  <===又初始化了,呵呵,又要迴圈了
:00419706 8D95F0FEFFFF            lea edx, dword ptr [ebp+FFFFFEF0]
:0041970C 8D45A0                  lea eax, dword ptr [ebp-60]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041974E(C)
|    <===這一行到0041974E,又構成一個小迴圈,將註冊碼處理成826757845後,與機器碼依次比較,只要一次錯了,就OVER
:0041970F 8B08                    mov ecx, dword ptr [eax]  <===EAX的初始地址8AF250
:00419711 3B0A                    cmp ecx, dword ptr [edx]  <===ECX的初始地址8AF1A0
:00419713 742F                    je 00419744       <===這裡必須跳走,不然到00419742一行無條件跳轉,就OVER了
:00419715 33C0                    xor eax, eax
:00419717 BA02000000              mov edx, 00000002
:0041971C 50                      push eax
:0041971D 8D4508                  lea eax, dword ptr [ebp+08]
:00419720 FF4F1C                  dec [edi+1C]
:00419723 E8882F0A00              call 004BC6B0
:00419728 FF4F1C                  dec [edi+1C]
:0041972B 8D450C                  lea eax, dword ptr [ebp+0C]
:0041972E BA02000000              mov edx, 00000002
:00419733 E8782F0A00              call 004BC6B0
:00419738 58                      pop eax
:00419739 8B17                    mov edx, dword ptr [edi]
:0041973B 64891500000000          mov dword ptr fs:[00000000], edx
:00419742 EB39                    jmp 0041977D

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419713(C)
|
:00419744 46                      inc esi
:00419745 83C204                  add edx, 00000004
:00419748 83C004                  add eax, 00000004
:0041974B 83FE09                  cmp esi, 00000009
:0041974E 7EBF                    jle 0041970F            <===迴圈9次後,不再跳轉了
:00419750 B001                    mov al, 01
:00419752 BA02000000              mov edx, 00000002
:00419757 50                      push eax
:00419758 8D4508                  lea eax, dword ptr [ebp+08]
:0041975B FF4F1C                  dec [edi+1C]
:0041975E E84D2F0A00              call 004BC6B0
:00419763 FF4F1C                  dec [edi+1C]
:00419766 8D450C                  lea eax, dword ptr [ebp+0C]
:00419769 BA02000000              mov edx, 00000002
:0041976E E83D2F0A00              call 004BC6B0
:00419773 58                      pop eax                <===這裡要求是EAX出來的不能為0
:00419774 8B17                    mov edx, dword ptr [edi]
:00419776 64891500000000          mov dword ptr fs:[00000000], edx

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004194C8(U), :00419558(U), :00419634(U), :00419742(U)
|
:0041977D 5F                      pop edi
:0041977E 5E                      pop esi
:0041977F 5B                      pop ebx
:00419780 8BE5                    mov esp, ebp
:00419782 5D                      pop ebp
:00419783 C3                      ret
.......
.......

--------------F8進入的數字變形call 004193E0-------------------------------------------------
* Referenced by a CALL at Addresses:          
|:004196E1   , :004196F4  
|
:004193E0 55                      push ebp
:004193E1 8BEC                    mov ebp, esp
:004193E3 53                      push ebx
:004193E4 8B450C                  mov eax, dword ptr [ebp+0C]
:004193E7 8B5508                  mov edx, dword ptr [ebp+08]
:004193EA 8B4A24                  mov ecx, dword ptr [edx+24]
:004193ED 894824                  mov dword ptr [eax+24], ecx
:004193F0 8B4A20                  mov ecx, dword ptr [edx+20]
:004193F3 3B4A24                  cmp ecx, dword ptr [edx+24]   <===第8位與第9位相比
:004193F6 7D04                    jge 004193FC                  <===相等就跳走
:004193F8 8342200A                add dword ptr [edx+20], 0000000A <===如果不相等,這裡第8位就加上A(防止第8位比第9小)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004193F6(C)
|
:004193FC 8B4A20                  mov ecx, dword ptr [edx+20]
:004193FF 2B4A24                  sub ecx, dword ptr [edx+24]
              <===如果第8位與第9位相等,則ECX=0;如果不等,則ECX=第8位+第9位
:00419402 894820                  mov dword ptr [eax+20], ecx      <===將ECX的值
:00419405 B907000000              mov ecx, 00000007     <===ECX為計數器,初始值為7
:0041940A 83C020                  add eax, 00000020
:0041940D 83C21C                  add edx, 0000001C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041942A(C)
|      <===這一行到0041942A,又構成一個小迴圈
:00419410 8B1A                    mov ebx, dword ptr [edx]
:00419412 3B18                    cmp ebx, dword ptr [eax]
:00419414 7D03                    jge 00419419
:00419416 83020A                  add dword ptr [edx], 0000000A

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00419414(C)
|
:00419419 8B1A                    mov ebx, dword ptr [edx]
:0041941B 2B18                    sub ebx, dword ptr [eax]
:0041941D 8958FC                  mov dword ptr [eax-04], ebx
:00419420 49                      dec ecx            <===計數器減去1
:00419421 83C0FC                  add eax, FFFFFFFC
:00419424 83C2FC                  add edx, FFFFFFFC
:00419427 83F901                  cmp ecx, 00000001
:0041942A 7DE4                    jge 00419410       <===共迴圈7次
:0041942C 5B                      pop ebx
:0041942D 5D                      pop ebp
:0041942E C3                      ret
       ***  此小段功能是(為了說明問題,這裡假設在新值尾部加個0,這個0在得出新值後去掉):將得到的9位數字,從尾部開始依次取值,例如取到第N位值,減去新值的第N+1的值(如果不夠減,則第N位值就加上10),得到的數就是新值的第N位值!
       ***  768193045經過這段處理後,就應該是524472195  (詳細數字處理變化情況,在上面有列表)
-----------------------------------------------------------------------------------

4、演算法總結:
  a、將註冊碼12345678901,按特定取位得到768193045
  b、將768193045經過8次的處理
               768193045
               524472195
               502225745
               055757895
               550523445
               969148595
               815477145
               083225295
               826757845  <===將最後這個值與機器碼比較
  c、反推的話就是:假設在舊值尾部加個0,新值第N位=舊第N位值+舊第N+1位值(如果有進位,就只取個位數),
               機器碼做如此處理8次,再按當初取碼位置反歸位,就得到了註冊碼。
  d、我的機器碼是:64265214        註冊碼就是:4?82648431?(?為任意數字)

5、序號產生器的製作:(我的C語言沒學完,就不在這現醜了),哪位C高手請幫忙寫一段程式碼給我,謝謝!(TC就可以了,其它的看不懂:)

6、註冊資訊存放在登錄檔:(刪除整個鍵值就成未註冊版本)
[HKEY_LOCAL_MACHINE\Software\Hearts\Register]
"user"="newlaos"
"pass"="48826484318"

相關文章