一个十分简单的算法保护程序
 
     日期:2007年1月29日   破解人:林海雪原
———————————————————————————————————————————
 
 
【软件名称】:   软件版本:3.33
【软件大小】: KB
【下载地址】:http://
【软件简介】:
【软件限制】:
【破解声明】:初学Crack,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!
【破解工具】:

———————————————————————————————————————————
 
【破解过程】:

 这是一个十分简单的算法保护程序,特别对新手有用,所以就发到这,希望对新手能有一点帮助!


用PEID查一下:Borland Delphi 6.0 - 7.0  虽然我们不能迷信这个结果,但先用它看看还是有必要的. 既然是Delphi的,就可以用DEDE分析了.其实这个程序保护较弱,不用DEDE也是一样的(用字符串参考,你会得到很多有用的东西!!):

004E6C45      mov edx,winchm.004E7178           ASCII "Single-user License"
004E6C68      mov edx,winchm.004E7194           ASCII "2-user License"
004E6C8B      mov edx,winchm.004E71AC           ASCII "5-user License"
004E6CAE      mov edx,winchm.004E71C4           ASCII "10-user License"
004E6CD1      mov edx,winchm.004E71DC           ASCII "20-user License"
004E6CF4      mov edx,winchm.004E71F4           ASCII "50-user License"
004E6D17      mov edx,winchm.004E720C           ASCII "Site License"
004E6DBE      mov edx,winchm.004E7178           ASCII "Single-user License"
004E6DE1      mov edx,winchm.004E7194           ASCII "2-user License"
004E6E04      mov edx,winchm.004E71AC           ASCII "5-user License"
004E6E27      mov edx,winchm.004E71C4           ASCII "10-user License"
004E6E4A      mov edx,winchm.004E71DC           ASCII "20-user License"
004E6E6D      mov edx,winchm.004E71F4           ASCII "50-user License"
004E6E90      mov edx,winchm.004E720C           ASCII "Site License"
004E6F3C      mov ecx,winchm.004E7224           ASCII "-user License"
004E6FAA      mov edx,winchm.004E720C           ASCII "Site License"
004E7097      mov ecx,winchm.004E7224           ASCII "-user License"
004E7114      mov edx,winchm.004E720C           ASCII "Site License"


在DEDE中,有这样一个窗体会引起你注意:TfrmRegister!! 

事件如下:

Register

TfrmRegister.FormCreate                          004E7648   *(为了防范作者玩火,这应注意一下,不用断的)
TfrmRegister.btnCleanInfoClick                   004E7768
TfrmRegister.BitBtn3Click                        004E78FC   ***
TfrmRegister.Action1Update                       004E796C   *
TfrmRegister.Action1Execute                      004E79F0   *
TfrmRegister.Label1Click                         004E7B98   *
TfrmRegister._PROC_004E6494                      004E6494
TfrmRegister._PROC_004E6558                      004E6558
TfrmRegister._PROC_004E6A10                      004E6A10
TfrmRegister._PROC_004E6A85                      004E6A85
TfrmRegister._PROC_004E6BB8                      004E6BB8
TfrmRegister._PROC_004E7235                      004E7235
TfrmRegister._PROC_004E72D4                      004E72D4
TfrmRegister._PROC_004E73D5                      004E73D5
TfrmRegister._PROC_004E7460                      004E7460
TfrmRegister._PROC_004E762D                      004E762D
TfrmRegister._PROC_004E772C                      004E772C
TfrmRegister._PROC_004E7964                      004E7964
TfrmRegister._PROC_004E7BA1                      004E7BA1
TfrmRegister._PROC_004E7BD0                      004E7BD0
TfrmRegister._PROC_004E7BD8                      004E7BD8

在上面的事件中只有加了"*"的能引人注目,先不管,用OD载入,在上面4处下断在说了,OD中断入口如下:

00512914 w> $  55              push ebp
00512915    .  8BEC            mov ebp,esp
00512917    .  B9 06000000     mov ecx,6
0051291C    >  6A 00           push 0
0051291E    .  6A 00           push 0
00512920    .  49              dec ecx
00512921    .^ 75 F9           jnz short winchm.0051291C
00512923    .  51              push ecx
00512924    .  53              push ebx
00512925    .  B8 AC245100     mov eax,winchm.005124AC
0051292A    .  E8 A93BEFFF     call winchm.004064D8
0051292F    .  33C0            xor eax,eax
00512931    .  55              push ebp


这是一个非标准的delphi入口,作者在dpr文件里弄了自己的代码!这说明PEID识别正确(绝大部份时候都是正确的).在上面4处下断,运行!结果未中断,而出来个框框,说"15 days left for trial period",在下面找到这个串:

004EAAC1   |.  8B86 10030000   mov eax,[dword ds:esi+310]   ; |
004EAAC7   |.  8945 F4         mov [dword ss:ebp-C],eax     ; |
004EAACA   |.  C645 F8 00      mov [byte ss:ebp-8],0        ; |
004EAACE   |.  8D55 F4         lea edx,[dword ss:ebp-C]     ; |
004EAAD1   |.  33C9            xor ecx,ecx                  ; |
004EAAD3   |.  B8 84AB4E00     mov eax,winchm.004EAB84      ; |ASCII "%d days left for trial period"
004EAAD8   |.  E8 D3F5F1FF     call winchm.0040A0B0         ; \winchm.0040A0B0
004EAADD   |.  8B55 FC         mov edx,[dword ss:ebp-4]

这个框框还有个"entr reg code"的按钮,我点了下,立马中断了:

004E796C   /.  55              push ebp
004E796D   |.  8BEC            mov ebp,esp
004E796F   |.  6A 00           push 0
004E7971   |.  6A 00           push 0

(TfrmRegister.Action1Update    004E796C   *)

看看上下文,感觉没有紧要之处,放行后,它要我输入name 和 License code,现在就各有所爱了,我就用scxtb 和 123456789 ,点register,又中断于下:

004E79F0   /.  55              push ebp
004E79F1   |.  8BEC            mov ebp,esp
004E79F3   |.  33C9            xor ecx,ecx
004E79F5   |.  51              push ecx
004E79F6   |.  51              push ecx

(TfrmRegister.Action1Execute    004E79F0   *)

同样,上下看看,这次收获可不小了:

004E7AC9   |.  A1 0C485100     mov eax,[dword ds:51480C]
004E7ACE   |.  8B00            mov eax,[dword ds:eax]
004E7AD0   |.  33D2            xor edx,edx
004E7AD2   |.  E8 F5CFF1FF     call winchm.00404ACC
004E7AD7   |.  74 0C           je short winchm.004E7AE5
004E7AD9   |.  B8 687B4E00     mov eax,winchm.004E7B68      ;  ASCII "Thank you!"          ===========>注册成功!!
004E7ADE   |.  E8 15F6F4FF     call winchm.004370F8
004E7AE3   |.  EB 0A           jmp short winchm.004E7AEF
004E7AE5   |>  B8 7C7B4E00     mov eax,winchm.004E7B7C      ;  ASCII "Illegal registration code!"=====>注册失败!!
004E7AEA   |.  E8 09F6F4FF     call winchm.004370F8
004E7AEF   |>  C786 4C020000 0>mov [dword ds:esi+24C],1

看来正确与否,就此见分晓了!主要代码如下:

004E7A4E   |.  E8 D146F9FF     call winchm.0047C124
004E7A53   |.  8B45 F4         mov eax,[dword ss:ebp-C]     ;  (ASCII "scxtb")
004E7A56   |.  8D55 F8         lea edx,[dword ss:ebp-8]
004E7A59   |.  E8 360DF2FF     call winchm.00408794
004E7A5E   |.  8B4D F8         mov ecx,[dword ss:ebp-8]
004E7A61   |.  BA 487B4E00     mov edx,winchm.004E7B48      ;  ASCII "RegName"
004E7A66   |.  8BC3            mov eax,ebx
004E7A68   |.  E8 BFAFF5FF     call winchm.00442A2C         ;  写注册表
004E7A6D   |.  8D45 EC         lea eax,[dword ss:ebp-14]
004E7A70   |.  50              push eax
004E7A71   |.  8D55 E0         lea edx,[dword ss:ebp-20]
004E7A74   |.  8B86 0C030000   mov eax,[dword ds:esi+30C]
004E7A7A   |.  E8 A546F9FF     call winchm.0047C124
004E7A7F   |.  8B45 E0         mov eax,[dword ss:ebp-20]    ;  (ASCII "123456")
004E7A82   |.  8D55 E4         lea edx,[dword ss:ebp-1C]
004E7A85   |.  E8 0A0DF2FF     call winchm.00408794
004E7A8A   |.  8B45 E4         mov eax,[dword ss:ebp-1C]
004E7A8D   |.  8D55 E8         lea edx,[dword ss:ebp-18]
004E7A90   |.  E8 AF0AF2FF     call winchm.00408544         ;  转为大写
004E7A95   |.  8B45 E8         mov eax,[dword ss:ebp-18]    ; |
004E7A98   |.  B1 01           mov cl,1                     ; |加解密的标志:1,加密
004E7A9A   |.  66:BA FE05      mov dx,5FE                   ; |初始密码;
004E7A9E   |.  E8 31F9FFFF     call winchm.004E73D4         ; \winchm.004E73D4
004E7AA3   |.  8B45 EC         mov eax,[dword ss:ebp-14]    ;  RegCode加密
004E7AA6   |.  8D55 F0         lea edx,[dword ss:ebp-10]
004E7AA9   |.  E8 86F7FFFF     call winchm.004E7234
004E7AAE   |.  8B4D F0         mov ecx,[dword ss:ebp-10]    ;  (ASCII "348678F37CE9")
004E7AB1   |.  BA 587B4E00     mov edx,winchm.004E7B58      ;  ASCII "RegCode"
004E7AB6   |.  8BC3            mov eax,ebx
004E7AB8   |.  E8 6FAFF5FF     call winchm.00442A2C         ;  写注册表
004E7ABD   |.  8BC3            mov eax,ebx


就是先把用户名和加密后的注册码写进注册表hKey = HKEY_CURRENT_USER\Software\Softany\winchm里在说,加密注册码过程如下(call winchm.004E73D4):


004E73D4   /$  55              push ebp                     ;本地调用来自 004E750D, 004E7A9E
004E73D5   |.  8BEC            mov ebp,esp                  ;很明显,004E750D处就是解密调用!
004E73D7   |.  83C4 F8         add esp,-8
..............
004E7414   |.  85C0            test eax,eax
004E7416   |.  7E 3F           jle short winchm.004E7457    ;  加密和还原
004E7418   |>  0FB7D7          /movzx edx,di                ;  05Fe:
004E741B   |.  C1EA 08         |shr edx,8
004E741E   |.  3213            |xor dl,[byte ds:ebx]        ;  与5 XOR
004E7420   |.  8816            |mov [byte ds:esi],dl
004E7422   |.  807D FB 00      |cmp [byte ss:ebp-5],0       ;  这是加解密的标志:1,加密;0,解密
004E7426   |.  74 17           |je short winchm.004E743F
004E7428   |.  81E2 FF000000   |and edx,0FF                 ;  XOR的结果只要未2位
004E742E   |.  66:03FA         |add di,dx                   ;  与初始码相加
004E7431   |.  66:69D7 540D    |imul dx,di,0D54             ;  dx==di*0d54(结果保留word大小)
004E7436   |.  66:81C2 3422    |add dx,2234                 ;  +$2234
004E743B   |.  8BFA            |mov edi,edx                 ;  结果为下次XOR的密码
004E743D   |.  EB 13           |jmp short winchm.004E7452
004E743F   |>  33D2            |xor edx,edx                 ;  这是解密!!
004E7441   |.  8A13            |mov dl,[byte ds:ebx]
004E7443   |.  66:03FA         |add di,dx
004E7446   |.  66:69D7 540D    |imul dx,di,0D54
004E744B   |.  66:81C2 3422    |add dx,2234
004E7450   |.  8BFA            |mov edi,edx
004E7452   |>  46              |inc esi
004E7453   |.  43              |inc ebx
004E7454   |.  48              |dec eax
004E7455   |.^ 75 C1           \jnz short winchm.004E7418
004E7457   |>  5F              pop edi


作者大概是先加密写进注册表,在读出来解密验证了!很明显,004E750D处就是解密调用!
我们到004E750D处看看,果不出所料:

004E74FF    .  E8 D0FDFFFF     call winchm.004E72D4
004E7504    .  8B45 EC         mov eax,[dword ss:ebp-14]    ; |
004E7507    .  33C9            xor ecx,ecx                  ; |
004E7509    .  66:BA FE05      mov dx,5FE                   ; |
004E750D    .  E8 C2FEFFFF     call winchm.004E73D4         ; \winchm.004E73D4


向下我们可以定位到如下关键处:

004E758C    .  E8 1BCEF1FF     call winchm.004043AC
004E7591    .  8B45 DC         mov eax,[dword ss:ebp-24]     ;  (ASCII "scxtb")
004E7594    .  8D4D E4         lea ecx,[dword ss:ebp-1C]
004E7597    .  5A              pop edx                       ;  (00ECA07C), ASCII "123456789"
004E7598    .  E8 1BF6FFFF     call winchm.004E6BB8          ;  关键!!======>进入!!
004E759D    .  8B55 E4         mov edx,[dword ss:ebp-1C]
004E75A0    .  A1 0C485100     mov eax,[dword ds:51480C]
004E75A5    .  E8 EAD3F1FF     call winchm.00404994
004E75AA    .  A1 0C485100     mov eax,[dword ds:51480C]
004E75AF    .  8B00            mov eax,[dword ds:eax]
004E75B1    .  33D2            xor edx,edx
004E75B3    .  E8 14D5F1FF     call winchm.00404ACC
004E75B8    .  75 16           jnz short winchm.004E75D0
004E75BA    .  A1 244A5100     mov eax,[dword ds:514A24]
004E75BF    .  BA 28764E00     mov edx,winchm.004E7628       ;  UNICODE " [Unregistered]"
004E75C4    .  E8 F7D3F1FF     call winchm.004049C0
004E75C9    .  A1 244A5100     mov eax,[dword ds:514A24]
004E75CE    .  EB 0A           jmp short winchm.004E75DA
004E75D0    >  A1 244A5100     mov eax,[dword ds:514A24]
004E75D5    .  E8 56D2F1FF     call winchm.00404830


=====>进入call winchm.004E6BB8:

004E6BB8   /$  55              push ebp
004E6BB9   |.  8BEC            mov ebp,esp
004E6BBB   |.  51              push ecx
004E6BBC   |.  B9 05000000     mov ecx,5
004E6BC1   |>  6A 00           /push 0
........
004E6BF8   |.  E8 A3D5F1FF     call winchm.004041A0
004E6BFD   |.  8B45 EC         mov eax,[dword ss:ebp-14]
004E6C00   |.  E8 DFD7F1FF     call winchm.004043E4          ;  取注册码长度
004E6C05   |.  8B15 444B5100   mov edx,[dword ds:514B44]     ;  winchm.00515E0C
004E6C0B   |.  C702 FFFFFFFF   mov [dword ds:edx],-1
004E6C11   |.  83F8 14         cmp eax,14                    ;  Switch (cases 14..22)
004E6C14   |.  0F85 23010000   jnz winchm.004E6D3D           ;  14----22
004E6C1A   |.  A1 444B5100     mov eax,[dword ds:514B44]     ;  Case 14 of switch 004E6C11
004E6C1F   |.  33D2            xor edx,edx
004E6C21   |.  8910            mov [dword ds:eax],edx
004E6C23   |.  8B45 EC         mov eax,[dword ss:ebp-14]
004E6C26   |.  E8 69F8FFFF     call winchm.004E6494          ;  关键!!======>进入!!
004E6C2B   |.  8945 F0         mov [dword ss:ebp-10],eax
004E6C2E   |.  8955 F4         mov [dword ss:ebp-C],edx



这里说一点就行了:
004E6C11   |.  83F8 14         cmp eax,14             =====>比较假注册码长度;
004E6C14   |.  0F85 23010000   jnz winchm.004E6D3D    =====>每次比较长度后的跳转就是很好的爆破点;



现在我们可以一些对注册码长度的要求了. 注册码长度如下5种(14;18;19;1D;22):

004E6C05   |.  8B15 444B5100      mov edx,dword ptr ds:[514B44]  ;  winchm.00515E0C
004E6C0B   |.  C702 FFFFFFFF      mov dword ptr ds:[edx],-1
004E6C11   |.  83F8 14            cmp eax,14                     ;  Switch (cases 14..22)
004E6C14   |.  0F85 23010000      jnz winchm.004E6D3D            ;  14----22
004E6C1A   |.  A1 444B5100        mov eax,dword ptr ds:[514B44]  ;  Case 14 of switch 004E6C11
.......
004E6D3D   |> \83F8 19            cmp eax,19
004E6D40   |.  0F85 70010000      jnz winchm.004E6EB6
004E6D46   |.  8D45 E8            lea eax,[local.6]              ;  Case 19 of switch 004E6C11
.........
004E6EB6   |> \83F8 1D            cmp eax,1D
004E6EB9   |.  0F85 12010000      jnz winchm.004E6FD1
004E6EBF   |.  8D45 E8            lea eax,[local.6]              ;  Case 1D of switch 004E6C11
.......
004E6FD1   |> \83F8 22            cmp eax,22
004E6FD4   |.  0F85 E1000000      jnz winchm.004E70BB
004E6FDA   |.  8D45 E8            lea eax,[local.6]              ;  Case 22 of switch 004E6C11
.......
004E70BB   |> \83F8 18            cmp eax,18
004E70BE   |.  75 72              jnz short winchm.004E7132
004E70C0   |.  8D45 E8            lea eax,[local.6]              ;  Case 18 of switch 004E6C11



我们来看下注册码长为20(14H)的情形:(call 004E6494为关键!)

======>进入!!跟进后可以看见下面的循环,就是计算注册码了(我已将注册码重填为:12345678901234567891):

004E64DF   |. /7E 39              jle short winchm.004E651A
004E64E1   |. |BB 01000000        mov ebx,1                    ;  计算注册码了!!
004E64E6   |> |8BC3               /mov eax,ebx                 ;  从1开始取循环数,以决定取注册码的位数
004E64E8   |. |99                 |cdq                         ;  把EAX中的字的符号扩展到EDX中去
004E64E9   |. |52                 |push edx                    ; /Arg2
004E64EA   |. |50                 |push eax                    ; |Arg1
004E64EB   |. |B8 03000000        |mov eax,3                   ; |
004E64F0   |. |E8 5BFFFFFF        |call winchm.004E6450        ; \winchm.004E6450======>进入!!
004E64F5   |. |52                 |push edx                    ;  3^n: n==循环数+1
004E64F6   |. |50                 |push eax
004E64F7   |. |8B45 EC            |mov eax,[local.5]           ;  注册码 (ASCII "12345678901234567891")
004E64FA   |. |8A4418 FF          |mov al,byte ptr ds:[eax+ebx>;  取1位注册码的ASCII
004E64FE   |. |25 FF000000        |and eax,0FF                 ;  与上面结果进行
004E6503   |. |33D2               |xor edx,edx
004E6505   |. |E8 02ECF1FF        |call winchm.0040510C        ;  int64乘法
004E650A   |. |0345 E0            |add eax,[local.8]           ;  加上次结果
004E650D   |. |1355 E4            |adc edx,[local.7]           ;  带进位加法
004E6510   |. |8945 E0            |mov [local.8],eax
004E6513   |. |8955 E4            |mov [local.7],edx
004E6516   |. |43                 |inc ebx                     ;  循环次数+1::注册码的下1位
004E6517   |. |4E                 |dec esi                     ;  控制器-1
004E6518   |.^|75 CC              \jnz short winchm.004E64E6
004E651A   |> \8B45 E0            mov eax,[local.8]
004E651D   |.  8945 F0            mov [local.4],eax
004E6520   |.  8B45 E4            mov eax,[local.7]
004E6523   |.  8945 F4            mov [local.3],eax


======>进入!!上面的call winchm.004E6450如下(实质上是计算3^n):


004E6458   |.  8BF0               mov esi,eax
004E645A   |.  8BC6               mov eax,esi                  ;  esi==eax==3
004E645C   |.  99                 cdq
004E645D   |.  8945 F8            mov [local.2],eax
004E6460   |.  8955 FC            mov [local.1],edx
004E6463   |.  8B5D 08            mov ebx,[arg.1]              ;  用上层循环次数来作这里的循环控制
004E6466   |.  85DB               test ebx,ebx
004E6468   |.  7C 1A              jl short winchm.004E6484
004E646A   |.  43                 inc ebx                      ; +1
004E646B   |>  8BC6               /mov eax,esi                 ;  esi=3
004E646D   |.  99                 |cdq
004E646E   |.  52                 |push edx
004E646F   |.  50                 |push eax
004E6470   |.  8B45 F8            |mov eax,[local.2]           ;  ==3(下次就是上轮的结果)
004E6473   |.  8B55 FC            |mov edx,[local.1]
004E6476   |.  E8 91ECF1FF        |call winchm.0040510C        ;  int64乘法
004E647B   |.  8945 F8            |mov [local.2],eax           ; 保存结果
004E647E   |.  8955 FC            |mov [local.1],edx
004E6481   |.  4B                 |dec ebx
004E6482   |.^ 75 E7              \jnz short winchm.004E646B
004E6484   |>  8B45 F8            mov eax,[local.2]            ;  结果就是3^n
004E6487   |.  8B55 FC            mov edx,[local.1]
004E648A   |.  5E                 pop esi


 ======>int64乘法 call winchm.0040510C :

这个是delphi的系统函数(procedure __llmul):

0040510C   /$  52              push edx                      ;  int64 乘法
0040510D   |.  50              push eax
0040510E   |.  8B4424 10       mov eax,[dword ss:esp+10]     ;  c2的高位
00405112   |.  F72424          mul [dword ss:esp]            ;  *c1的低位
00405115   |.  89C1            mov ecx,eax                   ;  结果==>ecx
00405117   |.  8B4424 04       mov eax,[dword ss:esp+4]      ;  c1的高位
0040511B   |.  F76424 0C       mul [dword ss:esp+C]          ;  *c2的低位
0040511F   |.  01C1            add ecx,eax                   ;  结果累加在ecx
00405121   |.  8B0424          mov eax,[dword ss:esp]        ;  c1的低位
00405124   |.  F76424 0C       mul [dword ss:esp+C]          ;  *c2的低位,就是返回值的低位--eax
00405128   |.  01CA            add edx,ecx                   ;  ecx累加在本次积的高位,就是返回值的高位--edx
0040512A   |.  59              pop ecx
0040512B   |.  59              pop ecx
0040512C   \.  C2 0800         retn 8


Borland的说法如下:

// 64 bit integer helper routines
//
// These functions always return the 64-bit result in EAX:EDX

// ------------------------------------------------------------------------------
//  64-bit signed multiply
// ------------------------------------------------------------------------------
//
//  Param 1(EAX:EDX), Param 2([ESP+8]:[ESP+4])  ; before reg pushing
//


注册算法描述如下:

  用注册码每1位的ASCII码与3的n次方进行int64乘法运算(n==注册码的对应位数+1),结果进行累加,累加和只能有7种情形注册成功!
这7种情形的运算结果分别如下所示,它分别对应了一种License类型(验证过程同硬件或用户名无关, 这样一来,就可以一码行天下了!): 


004E6C2B   |.  8945 F0         mov [dword ss:ebp-10],eax
004E6C2E   |.  8955 F4         mov [dword ss:ebp-C],edx
004E6C31   |.  817D F4 9902000>cmp [dword ss:ebp-C],299
004E6C38   |.  75 1A           jnz short winchm.004E6C54
004E6C3A   |.  817D F0 5BA60EF>cmp [dword ss:ebp-10],F90EA65B       ===>1:$299F90EA65B
004E6C41   |.  75 11           jnz short winchm.004E6C54
004E6C43   |.  8BC3            mov eax,ebx
004E6C45   |.  BA 78714E00     mov edx,winchm.004E7178              ;  ASCII "Single-user License"
004E6C4A   |.  E8 0DD5F1FF     call winchm.0040415C
004E6C4F   |.  E9 E5040000     jmp winchm.004E7139
004E6C54   |>  817D F4 7D03000>cmp [dword ss:ebp-C],37D
004E6C5B   |.  75 1A           jnz short winchm.004E6C77
004E6C5D   |.  817D F0 CAC1000>cmp [dword ss:ebp-10],800C1CA       ===>2:$37D0800C1CA
004E6C64   |.  75 11           jnz short winchm.004E6C77
004E6C66   |.  8BC3            mov eax,ebx
004E6C68   |.  BA 94714E00     mov edx,winchm.004E7194              ;  ASCII "2-user License"
004E6C6D   |.  E8 EAD4F1FF     call winchm.0040415C
004E6C72   |.  E9 C2040000     jmp winchm.004E7139
004E6C77   |>  817D F4 9D02000>cmp [dword ss:ebp-C],29D
004E6C7E   |.  75 1A           jnz short winchm.004E6C9A
004E6C80   |.  817D F0 10AF842>cmp [dword ss:ebp-10],2884AF10       ===>3:$29D2884AF10
004E6C87   |.  75 11           jnz short winchm.004E6C9A
004E6C89   |.  8BC3            mov eax,ebx
004E6C8B   |.  BA AC714E00     mov edx,winchm.004E71AC              ;  ASCII "5-user License"
004E6C90   |.  E8 C7D4F1FF     call winchm.0040415C
004E6C95   |.  E9 9F040000     jmp winchm.004E7139
004E6C9A   |>  817D F4 6802000>cmp [dword ss:ebp-C],268
004E6CA1   |.  75 1A           jnz short winchm.004E6CBD
004E6CA3   |.  817D F0 ED55AE4>cmp [dword ss:ebp-10],4FAE55ED       ===>4:$2684FAE55ED
004E6CAA   |.  75 11           jnz short winchm.004E6CBD
004E6CAC   |.  8BC3            mov eax,ebx
004E6CAE   |.  BA C4714E00     mov edx,winchm.004E71C4              ;  ASCII "10-user License"
004E6CB3   |.  E8 A4D4F1FF     call winchm.0040415C
004E6CB8   |.  E9 7C040000     jmp winchm.004E7139
004E6CBD   |>  817D F4 0F03000>cmp [dword ss:ebp-C],30F
004E6CC4   |.  75 1A           jnz short winchm.004E6CE0
004E6CC6   |.  817D F0 A9C407B>cmp [dword ss:ebp-10],B107C4A9       ===>5:$30FB107C4A9
004E6CCD   |.  75 11           jnz short winchm.004E6CE0
004E6CCF   |.  8BC3            mov eax,ebx
004E6CD1   |.  BA DC714E00     mov edx,winchm.004E71DC              ;  ASCII "20-user License"
004E6CD6   |.  E8 81D4F1FF     call winchm.0040415C
004E6CDB   |.  E9 59040000     jmp winchm.004E7139
004E6CE0   |>  817D F4 E002000>cmp [dword ss:ebp-C],2E0
004E6CE7   |.  75 1A           jnz short winchm.004E6D03
004E6CE9   |.  817D F0 FB6A6F0>cmp [dword ss:ebp-10],0E6F6AFB       ===>6:$2E00E6F6AFB
004E6CF0   |.  75 11           jnz short winchm.004E6D03
004E6CF2   |.  8BC3            mov eax,ebx
004E6CF4   |.  BA F4714E00     mov edx,winchm.004E71F4              ;  ASCII "50-user License"
004E6CF9   |.  E8 5ED4F1FF     call winchm.0040415C
004E6CFE   |.  E9 36040000     jmp winchm.004E7139
004E6D03   |>  817D F4 2A03000>cmp [dword ss:ebp-C],32A
004E6D0A   |.  75 1A           jnz short winchm.004E6D26
004E6D0C   |.  817D F0 B27EC9B>cmp [dword ss:ebp-10],BCC97EB2       ===>7:$32ABCC97EB2 
004E6D13   |.  75 11           jnz short winchm.004E6D26
004E6D15   |.  8BC3            mov eax,ebx
004E6D17   |.  BA 0C724E00     mov edx,winchm.004E720C              ;  ASCII "Site License"
004E6D1C   |.  E8 3BD4F1FF     call winchm.0040415C
004E6D21   |.  E9 13040000     jmp winchm.004E7139


  如果License类型为空, 那就是未注册了!

004E75AA    .  A1 0C485100     mov eax,[dword ds:51480C]
004E75AF    .  8B00            mov eax,[dword ds:eax]        ;  (UNICODE "Site License")
004E75B1    .  33D2            xor edx,edx
004E75B3    .  E8 14D5F1FF     call winchm.00404ACC
004E75B8    .  75 16           jnz short winchm.004E75D0
004E75BA    .  A1 244A5100     mov eax,[dword ds:514A24]
004E75BF    .  BA 28764E00     mov edx,winchm.004E7628       ;  UNICODE " [Unregistered]"
004E75C4    .  E8 F7D3F1FF     call winchm.004049C0
004E75C9    .  A1 244A5100     mov eax,[dword ds:514A24]
004E75CE    .  EB 0A           jmp short winchm.004E75DA
004E75D0    >  A1 244A5100     mov eax,[dword ds:514A24]
004E75D5    .  E8 56D2F1FF     call winchm.00404830
004E75DA    >  33C0            xor eax,eax


它的验证算法很简单,实现如下(大至的原里,细节上可能不对!):

var a,b,c:int64;
.....
  result:=0;
  for i:=0 to 19 do
    begin
     a:=int64(3)^(i+2);
     b:=注册码[i];
     c:=a*b;
     result:=result+c;
   end;
.....

注册机全部源代码(我没有更好的办法,也就只有穷举了):

var
  Form1: TForm1;
  bstr:array[0..19] of byte;
  cstr:array[0..19] of int64;
  str:array[0..20] of int64;
  sstr:string[20];

implementation

{$R *.dfm}
function Butt(a:int64;b:integer):int64;
var  i:integer;
begin
  result:=a;
  for i:=1 to b do
  begin
  result:=result*a;
  end;
end;

procedure Tck;
var  i:integer;
begin
  for i:=0 to 19 do
    begin
     str[i]:=Butt(3,i+2);
    end;
end;

procedure TForck(a:BYTE);
var  i:integer;
begin
  for i:=0 to 19 do
    begin
     bstr[i]:=a;
    end;
end;

procedure subbb;
var a,b:int64;
   i:integer;
begin
    a:=$32ABCC97EB2;  //ASCII "Site License" ======>我仅仅以这种License为例!!
    b:=0;
  for i:=0 to 19 do
    begin
     cstr[i]:=str[i]*bstr[i];
     b:=b+cstr[i];
    end;
    str[20]:=a-b;
end;

procedure filstr;
var  i:integer;
begin
  for i:=19 downto 0 do
    begin
     byte(sstr[i+1]):=bstr[i];
    end;
    byte(sstr[0]):=20;    
end;

// bstr[i]:=bstr[i-n]*3^n
procedure TForm1.ton2C;
var i:integer;
begin
 if CheckBox1.Checked then
 begin
  for  i:=19 downto 1 do
     begin
      //为了不在注册码中出现小写字母和不可输入字符,有如下限制
       if (bstr[i]<$5D) and (bstr[i]>$21) and (bstr[i-1]<$5D) and (bstr[i-1]>$1E) then
        begin
         bstr[i]:=bstr[i]-1;
         bstr[i-1]:=bstr[i-1]+3;
        end;
    end;
  end else
   begin
  for  i:=19 downto 2 do
     begin
       //为了不在注册码中出现小写字母和不可输入字符,有如下限制
        if (bstr[i]>$1F) and (bstr[i]<$60) and (bstr[i-2]>$29) and (bstr[i-2]<$69) then
          begin
           bstr[i]:=bstr[i]+1;
           bstr[i-2]:=bstr[i-2]-9;
          end;
     end;
   end ;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
   d:byte;
  Label fff,ffg;
begin
    subbb;
   if str[20] = 0 then  goto fff;
    while str[20]> 0 do
      begin
       d:=bstr[0];
       TForck(d+1);
       subbb;
      end;
    d:=bstr[0];
    TForck(d-1);
    subbb;
    for  i:=19 downto 0 do
     begin
      if str[20] = 0 then  goto ffg;
     while str[20]> 0 do
       begin
         bstr[i]:=bstr[i]+1;
         subbb;
         if str[20] = 0 then  goto ffg;
       end;
     bstr[i]:=bstr[i]-1;
     subbb;
    end;
  fff:
    ton2C;
  ffg:
    filstr;
    Edit1.Text:=sstr;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  Tck;
  TForck($30);   //用'0'初始, 其实我们可以一开始就用$49初始
end;

end.


注册机并不能算出全部注册码, 因为我仅仅考虑了很少的情况, 但对这种验证方式, 有一个注册码就够了! 

可用注册码:

]TCZZXRSUZZQZBYTJTLH 

<;=<<<<><<>>>=>>=>PJ 

ZUCZZXRSUZZQZBYTJTII

至于其它几种情形变化不是很大,也不是很难,就留下你来分析好了...

程序对时间(试用期)的检查在下面, 我对浮点运算不懂, 无法解说了, 自己看看好了:

004EA9EF   |.  B1 01         mov cl,1
004EA9F1   |.  BA 40AB4E00   mov edx,winchm.004EAB40      ;  ASCII "\Software\Microsoft\Internet Explorer"
004EA9F6   |.  8BC3          mov eax,ebx
004EA9F8   |.  E8 137AF5FF   call winchm.00442410
004EA9FD   |.  BA 70AB4E00   mov edx,winchm.004EAB70      ;  ASCII "CloseTime"
004EAA02   |.  8BC3          mov eax,ebx
004EAA04   |.  E8 5382F5FF   call winchm.00442C5C
004EAA09   |.  84C0          test al,al
004EAA0B   |.  75 2E         jnz short winchm.004EAA3B
004EAA0D   |.  E8 6E020000   call winchm.004EAC80
004EAA12   |.  E8 99E8FFFF   call winchm.004E92B0
004EAA17   |.  E8 7403F2FF   call winchm.0040AD90
004EAA1C   |.  83C4 F8       add esp,-8                   ; /
004EAA1F   |.  DD1C24        fstp [qword ss:esp]          ; |Arg1 (8 字节)
004EAA22   |.  9B            wait                         ; |
004EAA23   |.  BA 70AB4E00   mov edx,winchm.004EAB70      ; |ASCII "CloseTime"
004EAA28   |.  8BC3          mov eax,ebx                  ; |
004EAA2A   |.  E8 0981F5FF   call winchm.00442B38         ; \winchm.00442B38
004EAA2F   |.  C786 10030000>mov [dword ds:esi+310],0F
004EAA39   |.  EB 74         jmp short winchm.004EAAAF
004EAA3B   |> \E8 5003F2FF   call winchm.0040AD90
004EAA40   |.  83C4 F8       add esp,-8
004EAA43   |.  DD1C24        fstp [qword ss:esp]
004EAA46   |.  9B            wait
004EAA47   |.  BA 70AB4E00   mov edx,winchm.004EAB70      ;  ASCII "CloseTime"
004EAA4C   |.  8BC3          mov eax,ebx
004EAA4E   |.  E8 F980F5FF   call winchm.00442B4C
004EAA53   |.  83C4 F8       add esp,-8                   ; |
004EAA56   |.  DD1C24        fstp [qword ss:esp]          ; |Arg1 (8 字节)
004EAA59   |.  9B            wait                         ; |
004EAA5A   |.  E8 2DB4FFFF   call winchm.004E5E8C         ; \winchm.004E5E8C
004EAA5F   |.  84C0          test al,al
004EAA61   |.  7C 33         jl short winchm.004EAA96
004EAA63   |.  E8 2803F2FF   call winchm.0040AD90
004EAA68   |.  83C4 F8       add esp,-8
004EAA6B   |.  DD1C24        fstp [qword ss:esp]
004EAA6E   |.  9B            wait
004EAA6F   |.  BA 70AB4E00   mov edx,winchm.004EAB70      ;  ASCII "CloseTime"
004EAA74   |.  8BC3          mov eax,ebx
004EAA76   |.  E8 D180F5FF   call winchm.00442B4C
004EAA7B   |.  83C4 F8       add esp,-8                   ; |
004EAA7E   |.  DD1C24        fstp [qword ss:esp]          ; |Arg1 (8 字节)
004EAA81   |.  9B            wait                         ; |
004EAA82   |.  E8 DDB2FFFF   call winchm.004E5D64         ; \winchm.004E5D64
004EAA87   |.  BA 0F000000   mov edx,0F                   ;  最长试用期==15天(F)
004EAA8C   |.  2BD0          sub edx,eax                  ;  eax==已用天数
004EAA8E   |.  8996 10030000 mov [dword ds:esi+310],edx   ;  乘余天数
004EAA94   |.  EB 08         jmp short winchm.004EAA9E
004EAA96   |>  33C0          xor eax,eax
004EAA98   |.  8986 10030000 mov [dword ds:esi+310],eax
004EAA9E   |>  83BE 10030000>cmp [dword ds:esi+310],0     ;  试用期已用完?
004EAAA5   |.  7D 08         jge short winchm.004EAAAF
004EAAA7   |.  33C0          xor eax,eax
004EAAA9   |.  8986 10030000 mov [dword ds:esi+310],eax
004EAAAF   |>  8BC3          mov eax,ebx
004EAAB1   |.  E8 E677F5FF   call winchm.0044229C
004EAAB6   |.  8BC3          mov eax,ebx
004EAAB8   |.  E8 BB88F1FF   call winchm.00403378
004EAABD   |.  8D45 FC       lea eax,[dword ss:ebp-4]
004EAAC0   |.  50            push eax                     ; /Arg1
004EAAC1   |.  8B86 10030000 mov eax,[dword ds:esi+310]   ; |
004EAAC7   |.  8945 F4       mov [dword ss:ebp-C],eax     ; |
004EAACA   |.  C645 F8 00    mov [byte ss:ebp-8],0        ; |
004EAACE   |.  8D55 F4       lea edx,[dword ss:ebp-C]     ; |
004EAAD1   |.  33C9          xor ecx,ecx                  ; |
004EAAD3   |.  B8 84AB4E00   mov eax,winchm.004EAB84      ; |ASCII "%d days left for trial period"
004EAAD8   |.  E8 D3F5F1FF   call winchm.0040A0B0         ; \winchm.0040A0B0
004EAADD   |.  8B55 FC       mov edx,[dword ss:ebp-4]
004EAAE0   |.  8B86 0C030000 mov eax,[dword ds:esi+30C]
004EAAE6   |.  E8 6916F9FF   call winchm.0047C154
004EAAEB   |.  83BE 10030000>cmp [dword ds:esi+310],0     ;  在次检查试用期已用完?
004EAAF2   |.  75 20         jnz short winchm.004EAB14
004EAAF4   |.  BA ACAB4E00   mov edx,winchm.004EABAC      ;  ASCII "Close"
004EAAF9   |.  8B86 FC020000 mov eax,[dword ds:esi+2FC]
004EAAFF   |.  E8 5016F9FF   call winchm.0047C154


好似在[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer]下有一个"CloseTime"项, 记录了安装或第1次使用时间, 删除它就没有了限制?

注册机源码: