奇門遁甲演義V6.3破解手記--註冊碼演算法分析

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

奇門遁甲演義V6.3破解手記--註冊碼演算法分析
作者:newlaos[DFCG]

軟體名稱:奇門遁甲演義V6.3(周易)
檔案大小:2360KB(軟體做好後,沒有做任何處理,建議作者有類似UPX將軟體壓縮一下)
軟體授權:共享軟體
使用平臺:Win9x/Me/NT/2000/XP
釋出公司:"http://www.380000.com/
軟體簡介:自動排出從1900年到2050年內的任意時間的時家、日家、月家、年家奇門遁甲局況;附有相應的古注語和現註解,用彩色標出其中常見的兇格和吉格;方便的時間查詢功能,自動查詢滿足輸入條件的時間;可以匯出局圖的純文字版本,方便複製和傳播;時間調整功能;更詳細的幫助文件。


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

1、先用FI2.5看一下主程式“奇門遁甲演義VI.exe”,沒有加殼。是用VB編寫的。

2、用W32Dasm8.93黃金版對主檔案進行靜態反彙編,再用串式資料參考,找到"註冊成功!"(很經典的句子),雙擊來到下面程式碼段。這樣就找到註冊碼的計算部分。

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

.......
.......
:0040B73E FF15C4D14100            Call dword ptr [0041D1C4]
:0040B744 A1D0D64100              mov eax, dword ptr [0041D6D0]
:0040B749 8D4C2448                lea ecx, dword ptr [esp+48]
:0040B74D 50                      push eax

* Possible Reference to String Resource ID=00002: "212112121222#8"
                                |
:0040B74E 6A02                    push 00000002

* Possible StringData Ref from Data Obj ->"register.ini"
                                |
:0040B750 68782D4200              push 00422D78            <===檔案裡放了只有我們輸入的假碼(78787878)
:0040B755 E816830000              call 00413A70      
:0040B75A 8D7C2408                lea edi, dword ptr [esp+08]
:0040B75E 83C9FF                  or ecx, FFFFFFFF
:0040B761 33C0                    xor eax, eax
:0040B763 F2                      repnz
:0040B764 AE                      scasb
:0040B765 F7D1                    not ecx
:0040B767 49                      dec ecx
:0040B768 51                      push ecx
:0040B769 8D4C240C                lea ecx, dword ptr [esp+0C]
:0040B76D 51                      push ecx
:0040B76E 8D4C2450                lea ecx, dword ptr [esp+50]
:0040B772 E835830000              call 00413AAC
:0040B777 8D4C2448                lea ecx, dword ptr [esp+48]
:0040B77B E8827E0000              call 00413602
:0040B780 8B0D643F4200            mov ecx, dword ptr [00423F64]
:0040B786 E8F5020000              call 0040BA80  <===這個CALL會改變88FCA4處的值(這是一個標誌位),所以F8跟進
:0040B78B 8B15643F4200            mov edx, dword ptr [00423F64]
:0040B791 5F                      pop edi
:0040B792 8A8228A40000            mov al, byte ptr [edx+0000A428]
                       <===EDX=88587C(在88FCA4處的值很關鍵, 不能為0)
:0040B798 84C0                    test al, al           <===要不為0,才能正確跳轉
:0040B79A 7515                    jne 0040B7B1          <===關鍵跳轉,跳才正確

* Possible Reference to String Resource ID=00016: "221212212121#3"
                                |
:0040B79C 6A10                    push 00000010

* Possible StringData Ref from Data Obj ->"錯誤"
                                |
:0040B79E 6874004200              push 00420074

* Possible StringData Ref from Data Obj ->"註冊失敗!"
                                |
:0040B7A3 686C2D4200              push 00422D6C
:0040B7A8 56                      push esi

* Reference To: USER32.MessageBoxA, Ord:01BEh
                                |
:0040B7A9 FF1580D14100            Call dword ptr [0041D180]
:0040B7AF EB78                    jmp 0040B829

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B79A(C)
|

* Possible Reference to String Resource ID=00064: "212112121222#13"
                                |
:0040B7B1 6A40                    push 00000040

* Possible StringData Ref from Data Obj ->"提示"
                                |
:0040B7B3 68FC2C4200              push 00422CFC

* Possible StringData Ref from Data Obj ->"註冊成功!"
                                |
:0040B7B8 68602D4200              push 00422D60
:0040B7BD 56                      push esi

* Reference To: USER32.MessageBoxA, Ord:01BEh
                                |
:0040B7BE FF1580D14100            Call dword ptr [0041D180]
:0040B7C4 A1643F4200              mov eax, dword ptr [00423F64]
:0040B7C9 6A00                    push 00000000
:0040B7CB 56                      push esi
:0040B7CC C78004A40000FA000000    mov dword ptr [ebx+0000A404], 000000FA

* Reference To: USER32.EndDialog, Ord:00B9h
                                |
:0040B7D6 FF15DCD14100            Call dword ptr [0041D1DC]
:0040B7DC EB4B                    jmp 0040B829
.......
.......


-----0040B786 call 0040BA80  我們按F8跟進來到下面程式碼段-------
這一段的功能:是把我的註冊碼以“-”為標誌分成5串,而後與機器生成的5串依次比較,只一次錯就跳出
:0040BA80 6AFF                    push FFFFFFFF
:0040BA82 6858BB4100              push 0041BB58
:0040BA87 64A100000000            mov eax, dword ptr fs:[00000000]
:0040BA8D 50                      push eax
:0040BA8E 64892500000000          mov dword ptr fs:[00000000], esp
:0040BA95 81EC80000000            sub esp, 00000080
:0040BA9B 55                      push ebp
:0040BA9C 8BE9                    mov ebp, ecx
:0040BA9E 57                      push edi

* Possible Reference to String Resource ID=00001: "121121212221#19"
                                |
:0040BA9F 6A01                    push 00000001
:0040BAA1 8D4C244C                lea ecx, dword ptr [esp+4C]
:0040BAA5 E8587A0000              call 00413502

* Possible Reference to String Resource ID=00007: "121212212121#13"
                                |
:0040BAAA B907000000              mov ecx, 00000007
:0040BAAF 33C0                    xor eax, eax
:0040BAB1 8D7C2428                lea edi, dword ptr [esp+28]
:0040BAB5 6A00                    push 00000000
:0040BAB7 F3                      repz
:0040BAB8 AB                      stosd

* Possible StringData Ref from Data Obj ->"register.ini"
                                |
:0040BAB9 68782D4200              push 00422D78
:0040BABE C784249800000000000000  mov dword ptr [esp+00000098], 00000000
:0040BAC9 66AB                    stosw
:0040BACB E879FC0000              call 0041B749
:0040BAD0 83C408                  add esp, 00000008
:0040BAD3 83F8FF                  cmp eax, FFFFFFFF      
:0040BAD6 0F84CC000000            je 0040BBA8            <===這是不能跳,跳過去就OVER了。
:0040BADC A1D0D64100              mov eax, dword ptr [0041D6D0]
:0040BAE1 8D4C2448                lea ecx, dword ptr [esp+48]
:0040BAE5 50                      push eax

* Possible Reference to String Resource ID=00001: "121121212221#19"
                                |
:0040BAE6 6A01                    push 00000001

* Possible StringData Ref from Data Obj ->"register.ini"
                                |
:0040BAE8 68782D4200              push 00422D78
:0040BAED E8D47A0000              call 004135C6
:0040BAF2 8B54244C                mov edx, dword ptr [esp+4C]

* Possible Reference to String Resource ID=00010: "121121212221#10"
                                |
:0040BAF6 6A0A                    push 0000000A
:0040BAF8 8D4C242C                lea ecx, dword ptr [esp+2C]

* Possible Reference to String Resource ID=00030: "1221123121221#30"
                                |
:0040BAFC 6A1E                    push 0000001E
:0040BAFE 42                      inc edx
:0040BAFF 51                      push ecx
:0040BB00 8D4C2454                lea ecx, dword ptr [esp+54]
:0040BB04 89542458                mov dword ptr [esp+58], edx
:0040BB08 E8E27F0000              call 00413AEF
:0040BB0D 8D4C2448                lea ecx, dword ptr [esp+48]
:0040BB11 E8EC7A0000              call 00413602
:0040BB16 8BCD                    mov ecx, ebp
:0040BB18 E8A3FDFFFF              call 0040B8C0
:0040BB1D 8D542414                lea edx, dword ptr [esp+14]
:0040BB21 89442408                mov dword ptr [esp+08], eax
:0040BB25 52                      push edx
:0040BB26 8D44242C                lea eax, dword ptr [esp+2C]

* Possible Reference to String Resource ID=00045: "112112122212#13"
                                |
:0040BB2A 6A2D                    push 0000002D
:0040BB2C 50                      push eax
:0040BB2D 8BCD                    mov ecx, ebp
:0040BB2F E8FC4F0000              call 00410B30        <===這個CALL主要功能是看輸入的註冊碼裡有沒有五個“-”字元,到這裡我們將假碼改為78-78-78-78-78-78,重新來(為了說明方便,我們定義為註冊碼的1、2、3、4、5串)
:0040BB34 83F805                  cmp eax, 00000005    <===EAX必須等於5,否則就跳走出錯了。
:0040BB37 756F                    jne 0040BBA8  
 <===因為跳到錯的地方有兩個,上面那不會跳,所以這裡是一個很關鍵的跳轉
:0040BB39 53                      push ebx
:0040BB3A 56                      push esi
:0040BB3B 33FF                    xor edi, edi         <===EDI是個計數器,共5次,對應註冊碼有5串
:0040BB3D 8D5C241C                lea ebx, dword ptr [esp+1C]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040BB8D(C)
|
:0040BB41 8B542410                mov edx, dword ptr [esp+10]
:0040BB45 8D4C2414                lea ecx, dword ptr [esp+14]
:0040BB49 51                      push ecx
:0040BB4A 57                      push edi
:0040BB4B 52                      push edx
:0040BB4C 8BCD                    mov ecx, ebp
:0040BB4E E89DFDFFFF              call 0040B8F0   <===呵呵,這個就是算出正確的串值的CALL了。F8跟進
:0040BB53 8B33                    mov esi, dword ptr [ebx]
:0040BB55 8D442414                lea eax, dword ptr [esp+14]  
     <===我的機器出現EAX=為正確的串值(這裡用於比較的),共5次,在這裡設斷,得到一個值就將它改為註冊碼的對應的串,再點註冊,又失敗,但得到下一串的值,如此迴圈,註冊失敗5次後,你就得到全部的註冊碼了,我的是PLT6D-1DNLD-1KFDD-0XXXX-PLSCG

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040BB77(C)
|
:0040BB59 8A10                    mov dl, byte ptr [eax]
:0040BB5B 8ACA                    mov cl, dl
:0040BB5D 3A16                    cmp dl, byte ptr [esi]  
:0040BB5F 751C                    jne 0040BB7D            
:0040BB61 84C9                    test cl, cl
:0040BB63 7414                    je 0040BB79
:0040BB65 8A5001                  mov dl, byte ptr [eax+01]
:0040BB68 8ACA                    mov cl, dl
:0040BB6A 3A5601                  cmp dl, byte ptr [esi+01]
:0040BB6D 750E                    jne 0040BB7D
:0040BB6F 83C002                  add eax, 00000002
:0040BB72 83C602                  add esi, 00000002
:0040BB75 84C9                    test cl, cl
:0040BB77 75E0                    jne 0040BB59  
      <===這裡構成一個小迴圈功能是把我們輸入的假碼以“-”字元分開的字元與在0040BB55給出的EAX值作比較,只要一處錯就跳到40BB7D,就OVER了。

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040BB63(C)
|
:0040BB79 33C0                    xor eax, eax
:0040BB7B EB05                    jmp 0040BB82

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040BB5F(C), :0040BB6D(C)
|
:0040BB7D 1BC0                    sbb eax, eax         <===(帶位減法)EAX清0
:0040BB7F 83D8FF                  sbb eax, FFFFFFFF    <===EAX=1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040BB7B(U)
|
:0040BB82 85C0                    test eax, eax  
      <===EAX=1說明上面迴圈比較出錯了,EAX=0就說明比較對了。
:0040BB84 750B                    jne 0040BB91   <===如果EAX=1,這裡再跳走,EAX=0不跳
:0040BB86 47                      inc edi        
:0040BB87 83C304                  add ebx, 00000004
:0040BB8A 83FF05                  cmp edi, 00000005
:0040BB8D 7CB2                    jl 0040BB41  
     <===這裡是個大迴圈,共5次,分別比較機器算出的5個串和我們輸入的5個串做比較。
:0040BB8F EB07                    jmp 0040BB98    <===5次迴圈都正確,就到這裡再跳向勝利。

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040BB84(C)
|
:0040BB91 C68528A4000000          mov byte ptr [ebp+0000A428], 00

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040BB8F(U)
|
:0040BB98 5E                      pop esi
:0040BB99 83FF05                  cmp edi, 00000005
     <===這裡也是一個很關鍵的對比,上面0040BB91已經把標誌位清0
:0040BB9C 5B                      pop ebx
:0040BB9D 7510                    jne 0040BBAF  <===如果這裡跳走,就OVER
:0040BB9F C68528A4000001          mov byte ptr [ebp+0000A428], 01
     <===[ebp+0000A428]是個標誌位,能到這裡,說明成功
:0040BBA6 EB07                    jmp 0040BBAF

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040BAD6(C), :0040BB37(C)
|
:0040BBA8 C68528A4000000          mov byte ptr [ebp+0000A428], 00
     <===[ebp+0000A428]是個標誌位,要是到這裡,說明失敗      
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040BB9D(C), :0040BBA6(U)
|
:0040BBAF 8D4C2454                lea ecx, dword ptr [esp+54]
:0040BBB3 C7842490000000FFFFFFFF  mov dword ptr [esp+00000090], FFFFFFFF
:0040BBBE E8F0790000              call 004135B3
:0040BBC3 8D4C2454                lea ecx, dword ptr [esp+54]
:0040BBC7 E8DE780000              call 004134AA
:0040BBCC 8B8C2488000000          mov ecx, dword ptr [esp+00000088]
:0040BBD3 5F                      pop edi
:0040BBD4 5D                      pop ebp
:0040BBD5 64890D00000000          mov dword ptr fs:[00000000], ecx
:0040BBDC 81C48C000000            add esp, 0000008C
:0040BBE2 C3                      ret


-----0040BB4E call 0040B8F0   這個就是算出正確的串值的CALL了---------------
我的註冊碼機器454376902,註冊碼就是PLT6D-1DNLD-1KFDD-0XXXX-PLSCG
* Referenced by a CALL at Address:
|:0040BB4E  
|
:0040B8F0 83EC18                  sub esp, 00000018
:0040B8F3 33C0                    xor eax, eax   <===每次進來EAX都要清0
:0040B8F5 53                      push ebx
:0040B8F6 8B5C2428                mov ebx, dword ptr [esp+28]
:0040B8FA 8BCB                    mov ecx, ebx
:0040B8FC 56                      push esi
:0040B8FD 57                      push edi
:0040B8FE 8901                    mov dword ptr [ecx], eax
:0040B900 66894104                mov word ptr [ecx+04], ax
:0040B904 E8B68F0000              call 004148BF
:0040B909 99                      cdq

* Possible Reference to String Resource ID=00100: "221121121221#5"
                                |
:0040B90A B964000000              mov ecx, 00000064
:0040B90F F7F9                    idiv ecx  <===整數除法(EAX/ECX),商回EAX,餘數回ECX
:0040B911 33C0                    xor eax, eax
:0040B913 85D2                    test edx, edx
:0040B915 7E14                    jle 0040B92B
:0040B917 8B4C2428                mov ecx, dword ptr [esp+28]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B929(C)
|
:0040B91B 85C0                    test eax, eax
:0040B91D 7405                    je 0040B924
:0040B91F 0FAFC8                  imul ecx, eax
:0040B922 EB02                    jmp 0040B926

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B91D(C)
|
:0040B924 8BCA                    mov ecx, edx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B922(U)
|
:0040B926 40                      inc eax
:0040B927 3BC2                    cmp eax, edx
:0040B929 7CF0                    jl 0040B91B  <===這裡是一個迴圈結構

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B915(C)
|
:0040B92B 8B44242C                mov eax, dword ptr [esp+2C] <===從EAX=0開始,每次迴圈到裡,就加1,最後
:0040B92F 83F804                  cmp eax, 00000004       <===最後EAX=4,退出,共迴圈5次,正好是註冊碼的5個串值
:0040B932 7761                    ja 0040B995
:0040B934 FF248560BA4000          jmp dword ptr [4*eax+0040BA60]
   <===注意由於每次EAX都加1,所以導致這個無條件跳轉到的位置不同,每次不同跳轉產生不同的值共同構成這個註冊碼。
         
:0040B93B 8B442428                mov eax, dword ptr [esp+28]
   <===第一次跳到這裡,EAX=1B153DC6 ,它的十進位制是454376732,正好是我的機器碼!
:0040B93F 3503008519              xor eax, 19850003 <===1B153DC6與19850003做異或運算
:0040B944 0D34120000              or eax, 00001234  <===EAX再與1234做或運算,值放入EAX(為說明問題,我們定義為EAX1)
:0040B949 EB4E                    jmp 0040B999      <===跳走
:0040B94B 8B442428                mov eax, dword ptr [esp+28]
   <===第二次跳到這裡,EAX=1B153DC6,它的十進位制是454376732,正好是我的機器碼!

* Possible Reference to String Resource ID=00001: "121121212221#19"
                                |
:0040B94F B901000000              mov ecx, 00000001     <===ECX初始化為1,計數器

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B95D(C)
|
:0040B954 8BD1                    mov edx, ecx
:0040B956 0FAFC2                  imul eax, edx   <===但實際動態跟蹤時發現是EAX=EAX*1*2*3*4*5*6*7*8*9*A*B*C*D*E*F*10*11*12*13
:0040B959 41                      inc ecx              <===ECX=ECX+1
:0040B95A 83F913                  cmp ecx, 00000013    
:0040B95D 7EF5                    jle 0040B954         <===共迴圈16(注13是十六進位制)次。
:0040B95F 0D34120000              or eax, 00001234     <===EAX再與1234做或運算,值放入EAX(為說明問題,我們定義為EAX2)
:0040B964 EB33                    jmp 0040B999         <===跳走
:0040B966 8B442428                mov eax, dword ptr [esp+28]
  <===第三次跳到這裡,EAX=1B153DC6,它的十進位制是454376732,正好是我的機器碼!
:0040B96A 69C03C642B01            imul eax, 012B643C   <===EAX=EAX*12B643C
:0040B970 0D34120000              or eax, 00001234     <===EAX再與1234做或運算,值放入EAX(為說明問題,我們定義為EAX3)
:0040B975 EB22                    jmp 0040B999         <===跳走
:0040B977 8B442428                mov eax, dword ptr [esp+28]
  <===第四次跳到這裡,EAX=1B153DC6,它的十進位制是454376732,正好是我的機器碼!
* Possible Reference to String Resource ID=00010: "121121212221#10"
                                |
:0040B97B B90A000000              mov ecx, 0000000A    <===將ECX初始化為10,

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B986(C)
|
:0040B980 8BD0                    mov edx, eax
:0040B982 0FAFC2                  imul eax, edx      
   <===最後(EAX的值用C語言表示)
    eax=1B153DC6;
    for(i=0;i<>10;i++)
    {eax=eax^2;
     }
:0040B985 49                      dec ecx              <===ECX=ECX-1
:0040B986 75F8                    jne 0040B980         <===共一個小的迴圈結構,共迴圈10次,後退出!
:0040B988 EB0F                    jmp 0040B999         <===跳走,這裡的EAX(為說明問題,我們定義為EAX4)
:0040B98A 8B442428                mov eax, dword ptr [esp+28]
:0040B98E 3506068519              xor eax, 19850606
:0040B993 EB04                    jmp 0040B999

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B932(C)
|
:0040B995 8B442428                mov eax, dword ptr [esp+28]
  <===第五次跳到這裡,EAX=1B153DC6,它的十進位制是454376732,正好是我的機器碼!。這裡EAX不再做任何處理,直接拿來用了。(為說明問題,我們定義為EAX5)
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040B949(U), :0040B964(U), :0040B975(U), :0040B988(U), :0040B993(U)
|
:0040B999 8D4C240C                lea ecx, dword ptr [esp+0C]

* Possible Reference to String Resource ID=00036: "2114112212221#24"
                                |
:0040B99D 6A24                    push 00000024
:0040B99F 51                      push ecx                    <====ECX=8850D8
:0040B9A0 50                      push eax    
 <====這裡的EAX1,EAX2,EAX3,EAX4,EAX5分別為2903FF5,B2F61234,CB5DD27,0000000,2903BC0
:0040B9A1 E879FD0000              call 0041B71F    <===這裡面,EAX1,EAX2,EAX3,EAX4,EAX5再進行處理,就生成最終對應的串值,並放在出來的EAX中,F8跟進
:0040B9A6 8D7C2418                lea edi, dword ptr [esp+18]
:0040B9AA 83C9FF                  or ecx, FFFFFFFF
:0040B9AD 33C0                    xor eax, eax
:0040B9AF 83C40C                  add esp, 0000000C
:0040B9B2 F2                      repnz
:0040B9B3 AE                      scasb
:0040B9B4 F7D1                    not ecx
:0040B9B6 49                      dec ecx
:0040B9B7 8BF1                    mov esi, ecx
:0040B9B9 33C9                    xor ecx, ecx
:0040B9BB 85F6                    test esi, esi
:0040B9BD 7E17                    jle 0040B9D6

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B9D4(C)
|
:0040B9BF 8A440C0C                mov al, byte ptr [esp+ecx+0C]
:0040B9C3 3C61                    cmp al, 61
:0040B9C5 7C0A                    jl 0040B9D1
:0040B9C7 3C7A                    cmp al, 7A
:0040B9C9 7F06                    jg 0040B9D1
:0040B9CB 2C20                    sub al, 20
:0040B9CD 88440C0C                mov byte ptr [esp+ecx+0C], al

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040B9C5(C), :0040B9C9(C)
|
:0040B9D1 41                      inc ecx
:0040B9D2 3BCE                    cmp ecx, esi
:0040B9D4 7CE9                    jl 0040B9BF

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040B9BD(C)
|
:0040B9D6 83FE05                  cmp esi, 00000005
:0040B9D9 7C1C                    jl 0040B9F7
:0040B9DB 8D54240C                lea edx, dword ptr [esp+0C]
:0040B9DF 52                      push edx

* Possible StringData Ref from Data Obj ->"%.5s"
                                |
:0040B9E0 68F82D4200              push 00422DF8
:0040B9E5 53                      push ebx
:0040B9E6 E8EE890000              call 004143D9
:0040B9EB 83C40C                  add esp, 0000000C
:0040B9EE 5F                      pop edi
:0040B9EF 5E                      pop esi
:0040B9F0 5B                      pop ebx
:0040B9F1 83C418                  add esp, 00000018
:0040B9F4 C20C00                  ret 000C

---------:0040B9A1 call 0041B71F  按F8跟進來到下面程式碼段--------------------  
這段程式碼的作用:將EAX1,EAX2,EAX3,EAX4,EAX5再進行處理,就生成最終對應的串值,並放在出來的EAX中

* Referenced by a CALL at Addresses:
|:0040B80D   , :0040B9A1  
|
:0041B71F 55                      push ebp
:0041B720 8BEC                    mov ebp, esp
:0041B722 33C0                    xor eax, eax
:0041B724 837D100A                cmp dword ptr [ebp+10], 0000000A  <===[EBP+10]每次都是24
:0041B728 7508                    jne 0041B732                      <===所以這裡每次跳走
:0041B72A 394508                  cmp dword ptr [ebp+08], eax
:0041B72D 7D03                    jge 0041B732

* Possible Reference to String Resource ID=00001: "121121212221#19"
                                |
:0041B72F 6A01                    push 00000001
:0041B731 58                      pop eax

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0041B728(C), :0041B72D(C)
|
:0041B732 50                      push eax
:0041B733 FF7510                  push [ebp+10]   <===跳到這裡,將24(十六進位制)壓入棧
:0041B736 FF750C                  push [ebp+0C]                <===將8850D8壓入棧,這個是最終串值返回時的地址
:0041B739 FF7508                  push [ebp+08]                <===依次將EAX1,EAX2,EAX3,EAX4,EAX5壓入棧
:0041B73C E882FFFFFF              call 0041B6C3                <===這個CALL出來,EAX裡就是正確的串值了,F8再跟進
:0041B741 8B450C                  mov eax, dword ptr [ebp+0C]  <===最終將正確的串值放入EAX中
:0041B744 83C410                  add esp, 00000010
:0041B747 5D                      pop ebp
:0041B748 C3                      ret


---------:0041B73C call 0041B6C3  按F8跟進來到下面程式碼段--------------------  
這段程式碼的作用:將EAX1,EAX2,EAX3,EAX4,EAX5再進行處理,就生成最終對應的串值,並放在出來的EAX中

* Referenced by a CALL at Addresses:
|:0041B6B6   , :0041B73C  
|
:0041B6C3 55                      push ebp
:0041B6C4 8BEC                    mov ebp, esp
:0041B6C6 837D1400                cmp dword ptr [ebp+14], 00000000  <===這裡5次都相等
:0041B6CA 8B4D0C                  mov ecx, dword ptr [ebp+0C]
:0041B6CD 53                      push ebx
:0041B6CE 56                      push esi
:0041B6CF 57                      push edi
:0041B6D0 740B                    je 0041B6DD                       <===這裡5次都跳走
:0041B6D2 8B7508                  mov esi, dword ptr [ebp+08]
:0041B6D5 C6012D                  mov byte ptr [ecx], 2D
:0041B6D8 41                      inc ecx
:0041B6D9 F7DE                    neg esi
:0041B6DB EB03                    jmp 0041B6E0

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041B6D0(C)
|
:0041B6DD 8B7508                  mov esi, dword ptr [ebp+08]      <===跳到這裡,ESI=EAX(1,2,3,4,5)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041B6DB(U)
|
:0041B6E0 8BF9                    mov edi, ecx                     <===EDI=8850D8

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041B706(C)
|
:0041B6E2 8BC6                    mov eax, esi                     <===EAX=EAX(1,2,3,4,5)
:0041B6E4 33D2                    xor edx, edx                     <===將EDX清0
:0041B6E6 F77510                  div [ebp+10]   <===將EAX(1,2,3,4,5)除以24,商回EAX,餘數回EDX
:0041B6E9 8BC6                    mov eax, esi   <===EAX=EAX(1,2,3,4,5)
:0041B6EB 8BDA                    mov ebx, edx   <===EBX=餘數
:0041B6ED 33D2                    xor edx, edx   <===將EDX清0
:0041B6EF F77510                  div [ebp+10]   <===將EAX(1,2,3,4,5)除以24(十六進位制),商回EAX,餘數回EDX(不明白為什麼又除一遍)
:0041B6F2 83FB09                  cmp ebx, 00000009 <===這個判斷很重要!
:0041B6F5 8BF0                    mov esi, eax
:0041B6F7 7605                    jbe 0041B6FE      <===如果餘數是數字,就跳轉。如果餘數是字元,就不跳轉
:0041B6F9 80C357                  add bl, 57
:0041B6FC EB03                    jmp 0041B701

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041B6F7(C)
|
:0041B6FE 80C330                  add bl, 30

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041B6FC(U)
|
:0041B701 8819                    mov byte ptr [ecx], bl <===其實這個判斷的處理作用就是將餘數處理為其對應的ASCII值(字元是小寫)
:0041B703 41                      inc ecx
:0041B704 85F6                    test esi, esi
:0041B706 77DA                    ja 0041B6E2  <===從這裡向上,構成一個迴圈結構,共迴圈5次,第n次在bl處得到餘數轉為字元後,就構成串值的第n位
***** 這一小段的迴圈作用(以EAX1為例):
       公式           商      餘數     對應的字元
     2903FF5/24     123AAA     D        d
      123AAA/24      81A1      6        6
       81A1/24       339       1D       t  (d字元後面的16位的字元)以ASC碼錶為順序
        339/24       19        15       l  (數字5後面的16位的字元)
         19/24       0         19       p  (數字9後面的16位的字元)
***** 最後在記憶體的8850D8位置上得到串值d6tlp

:0041B708 802100                  and byte ptr [ecx], 00
:0041B70B 49                      dec ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041B718(C)
|
:0041B70C 8A17                    mov dl, byte ptr [edi]
:0041B70E 8A01                    mov al, byte ptr [ecx]
:0041B710 8811                    mov byte ptr [ecx], dl
:0041B712 8807                    mov byte ptr [edi], al
:0041B714 49                      dec ecx
:0041B715 47                      inc edi
:0041B716 3BF9                    cmp edi, ecx
:0041B718 72F2                    jb 0041B70C  
      <===從這裡向上,構成一個迴圈結構,作用是將上面得到串值反向再取值,所以最後8850D8位置上得到串值plt6d(其它程式段會把它轉為大寫)
:0041B71A 5F                      pop edi
:0041B71B 5E                      pop esi
:0041B71C 5B                      pop ebx
:0041B71D 5D                      pop ebp
:0041B71E C3                      ret
此段總結:依照上面的步驟將EAX1,EAX2,EAX3,EAX4,EAX5最後處理為plt6d,1dnld,1kfdd,0xxxx,plscg ----註冊碼浮出水面

-------------------------------------------------------------------------------------------------


4、演算法總結:-----型別:f(機器碼)=註冊碼------
 a、將機器碼454376732(每臺機器碼都不一樣),轉換為十六進位制1B153DC6

 b、將1B153DC6分別做5種的處理,得到相應串值的第一次變形
       第一種處理:1B153DC6與19850003做異或運算,再與1234做或運算,得到2903FF5
       第二種處理:1B153DC6EAX=EAX*1*2*3*4*5*6*7*8*9*A*B*C*D*E*F*10*11*12*13,再與1234做或運算,得到B2F61234
       第三種處理:1B153DC6*12B643C,再與1234做或運算,得到CB5DD27C
       第四種處理:eax=1B153DC6; for(i=0;i<>10;i++) {eax=eax^2;}一般情況EAX都會因為值太大,而爆為00000000
       第五種處理:1B153DC6不做處理

 c、分別將上一步得到的5串數字,做同樣的處理,也就是(以EAX1為例):
       公式           商      餘數     對應的字元
     2903FF5/24     123AAA     D        d
      123AAA/24      81A1      6        6
       81A1/24       339       1D       t  (d字元後面的16位的字元)以ASC碼錶為順序
        339/24       19        15       l  (數字5後面的16位的字元)
         19/24       0         19       p  (數字9後面的16位的字元)
     最後改為字串d6tlp,其它的四個串也依次類推。

 d、將上一步得到的5個字元分別反向取值,分別得到plt6d,1dnld,1kfdd,0xxxx,plscg,最後的註冊碼就是將它轉為大寫後,中間分別加上“-”,PLT6D-1DNLD-1KFDD-0XXXX-PLSCG

5、註冊資訊存放在奇門遁甲演義V6.3所在目錄的register.ini檔案中。以明檔案形式保留。

相關文章