【破解作者】 qfejj
【作者邮箱】 qfejj@163.com
【使用工具】 OllyDbgv1.10;PEIDv0.93;MASM32
【破解平台】 Win9x/NT/2000/XP
【软件名称】 PolyView version 4.251
【下载地址】 http://www.polybytes.com
【软件大小】 1.75MB
【加壳方式】 无
【破解声明】 本人破解无任何商业目的,纯粹兴趣使然
--------------------------------------------------------------------------------
【破解内容】



    一个看图软件,除了看图还可以,处理代码乱七八糟,还有一些根本不会执行的代码混在算法函数中,原来老外也是喜欢耍耍手段弄弄人的,我们还是先来看一下软件对用户名和注册码的大致处理过程,以便后面看代码或者自己调试的时候思路清晰一点:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


                                     /用算法1处理->对结果进一步运算->结果作为中间值的低16位 \
                                    /                                                        \
用户名->用户名后加上"PolyView"字串->                                                          > 得到中间值
                                    \                                                        /
                                     \用算法2得到结果2------------------->作为中间值的高16位/

                                    
                                       / 若注册码处理完毕--------------->结果作为中间值
                                      /
注册码->基数+注册码ASCII值-30->结果-->
                                      \        
                                       \若没有处理完-->结果*5作为累计值-->逻辑左移1->作为基数进行下一轮计算     
         

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    最后当然是两个中间值的比较了,相等则完成注册。
    具体的算法请看软件反汇编代码,也可以看我注册机的源码。
    注册码处理:
;-------------------------------------------------------------------------
004E0DEE   cmp byte ptr ss:[ebp-17D],0        ;  初始0
004E0DF5   jnz short PolyView.004E0E38
004E0DF7   inc dword ptr ss:[ebp-19C]
004E0DFD   mov eax,dword ptr ss:[ebp-1A0]     ;  就是那个累计的值了
004E0E03   lea eax,dword ptr ds:[eax+ebx-30]  ;  ebx为注册码一个值
004E0E07   mov dword ptr ss:[ebp-1A0],eax     ;  结果到0100f1d8
004E0E0D   cmp dword ptr ss:[ebp-1B4],0
004E0E14   je short PolyView.004E0E27
004E0E16   dec dword ptr ss:[ebp-18C]
004E0E1C   jnz short PolyView.004E0E27
004E0E1E   mov byte ptr ss:[ebp-17D],1
004E0E25   jmp short PolyView.004E0E4C
004E0E27   inc dword ptr ss:[ebp-184]         ;  1,2
004E0E2D   mov edx,esi
004E0E2F   call PolyView.004E0224             ;  取下一个注册码
004E0E34   mov ebx,eax                        ;  38
004E0E36   jmp short PolyView.004E0E4C
004E0E38   dec dword ptr ss:[ebp-184]
004E0E3E   cmp ebx,-1
004E0E41   je short PolyView.004E0E4C
004E0E43   push esi
004E0E44   push ebx
004E0E45   call PolyView.004E32BC
004E0E4A   pop ecx
004E0E4B   pop ecx
004E0E4C   cmp byte ptr ss:[ebp-17D],0        ;  看是否已经取完
004E0E53   je PolyView.004E0D88               ;  回去再来
004E0E59   mov dword ptr ss:[ebp-194],ebx     ;  完了以后的累计值就是后面用来比较的中间数
004E0E5F   cmp byte ptr ss:[ebp-197],0
004E0E66   je short PolyView.004E0E6E
004E0E68   neg dword ptr ss:[ebp-1A0]
004E0E6E   cmp edi,46
004E0E71   jnz short PolyView.004E0E7A
004E0E73   and dword ptr ss:[ebp-19C],0
004E0E7A   cmp dword ptr ss:[ebp-19C],0
004E0E81   je PolyView.004E0F6F
004E0E87   cmp byte ptr ss:[ebp-18E],0
004E0E8E   jnz short PolyView.004E0ECE
004E0E90   inc dword ptr ss:[ebp-1B8]
004E0E96   mov ebx,dword ptr ss:[ebp-1B0]
004E0E9C   mov eax,dword ptr ss:[ebp-1A0]
004E0EA2   cmp dword ptr ss:[ebp-1C8],0
004E0EA9   je short PolyView.004E0EBE
004E0EAB   mov eax,dword ptr ss:[ebp-1AC]
004E0EB1   mov dword ptr ds:[ebx],eax
004E0EB3   mov eax,dword ptr ss:[ebp-1A8]
004E0EB9   mov dword ptr ds:[ebx+4],eax
004E0EBC   jmp short PolyView.004E0ECE
004E0EBE   cmp byte ptr ss:[ebp-18D],0
004E0EC5   je short PolyView.004E0ECB
004E0EC7   mov dword ptr ds:[ebx],eax         ;  这句写入前面求得的中间值,作为标志
004E0EC9   jmp short PolyView.004E0ECE
004E0ECB   mov word ptr ds:[ebx],ax
004E0ECE   inc byte ptr ss:[ebp-195]
004E0ED4   inc dword ptr ss:[ebp+C]
004E0ED7   jmp short PolyView.004E0F50
;-------------------------------------------------------------------------------------
    用户名处理:
;-------------------------------------------------------------------------------------
004566D0   mov eax,dword ptr fs:[0]
004566D6   push -1
004566D8   push PolyView.0051A33B
004566DD   push eax
004566DE   mov eax,dword ptr ss:[esp+10]
004566E2   mov dword ptr fs:[0],esp
004566E9   sub esp,10C
004566EF   push ebx
004566F0   mov edx,eax
004566F2   mov al,byte ptr ds:[eax]           ;  取出单个用户名
004566F4   push esi                           ;  后面要取出来和eax比较
004566F5   xor ebx,ebx
004566F7   xor esi,esi
004566F9   cmp al,bl
004566FB   je short PolyView.00456721
004566FD   lea ecx,dword ptr ds:[ecx]
00456700   /cmp al,5B                         ;  [
00456702   |je PolyView.00456817
00456708   |cmp al,5D                         ;  ]
0045670A   |je PolyView.00456817
00456710   |cmp al,20                         ;  空格
00456712   |je short PolyView.00456719
00456714   |mov byte ptr ss:[esp+esi+14],al   ;  复制到别的地方去(0100F944)
00456718   |inc esi
00456719   |mov al,byte ptr ds:[edx+1]        ;  去下一个用户名
0045671C   |inc edx
0045671D   |cmp al,bl                         ;  看是否取完了
0045671F   \jnz short PolyView.00456700       ;  回去再来
00456721   mov al,byte ptr ds:[ecx]
00456723   cmp al,bl
00456725   je short PolyView.00456734
00456727   /mov byte ptr ss:[esp+esi+14],al
0045672B   |mov al,byte ptr ds:[ecx+1]
0045672E   |inc esi
0045672F   |inc ecx
00456730   |cmp al,bl
00456732   \jnz short PolyView.00456727
00456734   push ebp
00456735   push 80
0045673A   lea ecx,dword ptr ss:[esp+14]
0045673E   call PolyView.004017C0
00456743   mov ebp,dword ptr ss:[esp+10]
00456747   mov ecx,dword ptr ss:[ebp-C]
0045674A   xor eax,eax
0045674C   cmp ecx,ebx
0045674E   mov dword ptr ss:[esp+120],ebx
00456755   jle short PolyView.00456774
00456757   /cmp eax,ebx                       ;  下面的循环在用户名后加上PolyView字串
00456759   |jl PolyView.00456830
0045675F   |cmp eax,ecx
00456761   |jg PolyView.00456830
00456767   |mov dl,byte ptr ds:[eax+ebp]
0045676A   |mov byte ptr ss:[esp+esi+18],dl
0045676E   |inc esi
0045676F   |inc eax
00456770   |cmp eax,ecx
00456772   \jl short PolyView.00456757
00456774   push edi
00456775   lea eax,dword ptr ss:[esp+10]
00456779   push eax
0045677A   lea ecx,dword ptr ss:[esp+20]      ;  用户名+PolyView
0045677E   push esi                           ;  处理后的用户名长度
0045677F   push ecx                           ;  处理后的用户名
00456780   mov dword ptr ss:[esp+1C],ebx
00456784   call PolyView.00454590             ;  第一次处理用户名,留意ecx返回值
00456789   lea edx,dword ptr ss:[esp+28]      ;  用户名+PolyView
0045678D   push esi                           ;  处理后的用户名长度
0045678E   push edx                           ;  处理后的用户名
0045678F   call PolyView.00454610             ;  第二次处理用户名,要留意eax返回值
00456794   movzx ecx,word ptr ss:[esp+24]     ;  就是第一次处理用户名后返回的ecx值
00456799   movzx esi,ax                       ;  用户名第二次处理结果到esi
0045679C   shl ecx,10
0045679F   or ecx,esi                         ;  到这里结束
004567A1   mov bx,ax
004567A4   add esp,14
004567A7   xor edi,edi
004567A9   mov dword ptr ss:[esp+18],ecx      ;  保存
004567AD   shr bx,8
004567B1   /lea edx,dword ptr ss:[esp+10]     ;  地址指向第一次处理用户名的ecx返回值,在这里累计
004567B5   |push edx                          ;  
004567B6   |lea eax,dword ptr ss:[esp+1C]
004567BA   |push 4
004567BC   |push eax
004567BD   |call PolyView.00454590
004567C2   |add esp,0C
004567C5   |movzx ecx,bl
004567C8   |inc edi
004567C9   |cmp edi,ecx
004567CB   \jl short PolyView.004567B1
004567CD   movzx edx,word ptr ss:[esp+10]     ;  累计后的结果送edx,后面会作为中间值低16位值的
004567D2   shl esi,10                         ;  第一次处理后的用户名结果放到esi高16位
004567D5   lea eax,dword ptr ss:[ebp-10]
004567D8   or esi,edx                         ;  +208B
004567DA   mov dword ptr ss:[esp+124],-1
004567E5   lea ecx,dword ptr ds:[eax+C]
...
;----------------------------------------------------------------------------------------------------------

对于反推注册码部分,我画张表来说明:

|--------|----------------|---------------|
| 累计值 |      基数      |     结果      |  
|--------|----------------|---------------|
|  x     | y=(shl 5*x,1)  | z=y+注册码-30 |
|--------|----------------|---------------|
if  处理完毕 
    中间值=结果
else  
    x=结果
;-------------------------------------------------------------------------------------------------------------
    好了,要根据中间值反推注册码,我们来看一下关系式,对于每一轮的基数(第一轮除外,是0)和注册码ASCII值都是未知的,做不了逆算。我想到基数在逻辑左移前是由前一轮累计值乘5得到,那么正确的基数在逻辑右移1位后一定是可以被5整除的。由此我们可以先构造一个基数,然后除以5,如果能整除,那么这个构造的基数就是正确的,得到的商就是上一轮的累计值,然后继续构造基数,当这个累计值为0的时候,我们就得到了所有的注册码了。用关系式表示如下:
  ----------------------------
   1:
    假设:从最后最后一个注册码开始,先设其ASCII值为Number
   2:
    构造:上一轮基数=y=z+30-注册码=中间值+30-Number
   3:
    上一轮累计值=x=(shr y,1)/5
        if 余数为零 
           注册码=Number
        else 
           jmp 1(重新假设一个注册码,继续构造基数)
        endif
        中间值=上一轮基数
        cmp 商,0
        jnz 2
        计算完成 
   -----------------------------   
   当然,这样子计算有很大的漏洞,比如通过不同的中间值,可能得到相同的注册码,我暂时没有找到更合适的求解方法。在过几天要毕业答辩了,我先把注册机源码贴出来,大家看看,顺便帮忙修正上面的算法。
   最后,给个算出的注册码:
   Licensee:qfejj
   License Number:3528073355

下面是我修改后的注册机源码,计算结果是正确了,不过也是绕了一个弯:
---------------------------------------------------------

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>> Keygne For PloyView Version 4.251 >>>>
;>>>>          code:    qfejj           >>>>
;>>>>         Email : qfejj@163.com     >>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
.586
.model flat, stdcall  
option casemap :none  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDD_DLG1                equ 1000
IDC_NAME                equ 1001
IDC_CODE                equ 1002
IDC_OK                  equ 1005
IDC_ABOUT               equ 1006
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc proto :HWND,:UINT,:WPARAM,:LPARAM
GetKey  proto 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
MsgboxText    db '-=You are free to do as you wish!=-',0dh
              db '         -=Email:qfejj@163.com=-',0
MsgboxCaption db 'about',0
AppendString  db 'PolyView',0
Array         db 01,02,04,08,10h,20h,40h,80h
Table         db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00     
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 00,00,00,00,01,00,00,00,01,00,00,00,00,00,00,00
              db 01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
.data?
hInstance     HINSTANCE ?
hDlg          HINSTANCE ?
result1       dd ?
result2       dd ?
result3       dd ?
cmpResult     dd ?
cmpbuffer     dd 12 dup(?)
NameBuffer    db 40 dup (?)
SerialBuffer  db 40 dup (?)
SerialTemp    db 40 dup (?)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

.code

start:
        invoke GetModuleHandle,NULL
        mov hInstance,eax
  invoke DialogBoxParam,hInstance,IDD_DLG1,NULL,addr DlgProc,NULL
  invoke ExitProcess,0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
        mov eax,uMsg
  .if     eax==WM_CLOSE
       invoke EndDialog,hWin,0
  .elseif eax==WM_INITDIALOG
       push hWin
       pop  hDlg
  .elseif eax==WM_COMMAND
          mov eax,wParam
             .if eax==IDC_OK
                  invoke RtlZeroMemory,offset SerialBuffer,40
               invoke GetKey
             .elseif eax==IDC_ABOUT
               invoke MessageBox,hWin,addr MsgboxText,addr MsgboxCaption,MB_OK
             .endif                 
  .else
    mov eax,FALSE
    ret
  .endif
  mov eax,TRUE
  ret

DlgProc endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
GetKey proc
        
        pushad
        invoke GetDlgItemText,hDlg,IDC_NAME,offset NameBuffer,sizeof NameBuffer
        invoke lstrcat,offset NameBuffer,offset AppendString
;-------------------
;第一种算法处理用户名
;-------------------
        mov eax,0100F900h
        xor edi,edi
@1:        
        mov cl,byte ptr[NameBuffer+edi]
        xor cl,al
        mov al,7Fh
        cmp al,cl
        sbb edx,edx
        mov al,cl
        shl al,1
        xor cl,al
        movzx eax,al
        neg edx
        cmp dword ptr[Table+eax*4],0
        setne al
        dec al
        and eax,3  
        test edx,edx
        je @2
        xor al,2
@2:
        xor edx,edx
        mov dh,al
        shr al,1
        mov dl,cl
        shl edx,6
        mov ecx,edx
        or al,cl
        xor al,bl
        inc edi
        cmp byte ptr[NameBuffer+edi],0
        mov bl,ch
        jnz @1
        xor ecx,ecx
        mov ch,bl
        mov cl,al
        movzx ecx,cx
        mov dword ptr[result1],ecx      ;保存处理结果
        
;--------------------
;第二种算法处理用户名
;--------------------
        mov ebx,0FFFFh
        xor ebp,ebp
        xor esi,esi
@3:     
        mov eax,0100F900h   
        xor edx,edx
@4:
        mov cl,byte ptr[NameBuffer+ebp]
        mov al,byte ptr[Array+edx]
        and al,cl
        mov cl,dl
        shr al,cl
        xor ecx,ecx
        mov cl,bl
        movzx si,al
        xor eax,eax
        mov al,bl
        shr al,1
        xor al,bl
        and ecx,1
        xor esi,ecx
        movzx ecx,si
        and eax,7
        xor ebx,eax
        mov eax,ecx
        shl eax,4
        mov edi,ebx  ;软件有保存的地方,我没有
        shr bl,1
        sar eax,1
        and edi,0FFF7h
        shl ecx,0Bh
        sar ecx,1
        shl esi,0Fh
        and ebx,8
        xor eax,ebx
        or eax,edi
        mov edi,eax
        shr edi,1
        xor edi,eax
        mov bl,byte ptr[Array+edx+1]
        and edi,3F0h
        xor eax,edi
        mov edi,eax
        and eax,0FBFFh
        shr edi,1
        and edi,400h
        xor ecx,edi
        or ecx,eax
        mov eax,ecx
        and ecx,7FFh
        shr eax,1
        and eax,7800h
        or eax,ecx
        and bl,byte ptr[NameBuffer+ebp]
        or eax,esi
        mov cl,dl
        inc cl
        shr bl,cl
        xor ecx,ecx
        mov cl,al
        movzx di,bl
        xor ebx,ebx
        and ecx,1
        xor edi,ecx
        xor ecx,ecx
        mov cl,al
        shr cl,1
        xor cl,al
        movzx esi,di
        and ecx,7
        xor eax,ecx
        mov bl,al
        shr bl,1
        mov ecx,esi
        shl ecx,4
        sar ecx,1
        and eax,0FFF7h
        and ebx,8
        xor ecx,ebx
        or ecx,eax
        mov eax,ecx
        shr eax,1
        xor eax,ecx
        and eax,3F0h
        xor ecx,eax
        shl esi,0Bh
        mov eax,ecx
        and ecx,0FBFFh
        mov bl,byte ptr[Array+edx+2]
        shr eax,1
        and eax,400h
        sar esi,1
        xor esi,eax
        or esi,ecx
        and bl,byte ptr[NameBuffer+ebp]
        mov eax,esi
        shr eax,1
        and eax,7800h
        and esi,7FFh
        or eax,esi
        shl edi,0Fh
        or eax,edi
        mov cl,dl
        add cl,2
        shr bl,cl
        xor ecx,ecx
        mov cl,al
        movzx di,bl
        xor ebx,ebx
        and ecx,1
        xor edi,ecx
        xor ecx,ecx
        mov cl,al
        shr cl,1
        xor cl,al
        movzx esi,di
        shl edi,0Fh
        and ecx,7
        xor eax,ecx
        mov bl,al
        shr bl,1
        and eax,0FFF7h
        mov ecx,esi
        shl ecx,4
        sar ecx,1
        shl esi,0Bh
        sar esi,1
        and ebx,8
        xor ecx,ebx
        or ecx,eax
        mov eax,ecx
        mov bl,byte ptr[Array+edx+3]
        shr eax,1
        xor eax,ecx
        and eax,3F0h
        xor ecx,eax
        mov eax,ecx
        and ecx,0FBFFh
        shr eax,1
        and eax,400h
        xor esi,eax
        or esi,ecx
        and bl,byte ptr[NameBuffer+ebp]
        mov eax,esi
        shr eax,1
        mov cl,dl
        add cl,3
        shr bl,cl
        xor ecx,ecx
        and eax,7800h
        and esi,7FFh
        or eax,esi
        or eax,edi
        mov cl,al
        movzx di,bl
        and ecx,1
        xor edi,ecx
        xor ecx,ecx
        mov cl,al
        shr cl,1
        xor cl,al
        movzx esi,di
        and ecx,7
        xor eax,ecx
        mov ecx,esi
        xor ebx,ebx
        mov bl,al
        shl ecx,4
        shr bl,1
        sar ecx,1
        and eax,0FFF7h
        shl esi,0Bh
        sar esi,1
        shl edi,0Fh
        add edx,4
        and ebx,8
        xor ecx,ebx
        or ecx,eax
        mov eax,ecx
        shr eax,1
        xor eax,ecx
        and eax,3F0h
        xor ecx,eax
        mov eax,ecx
        and ecx,0FBFFh
        shr eax,1
        and eax,400h
        xor esi,eax
        or esi,ecx
        mov ecx,esi
        shr ecx,1
        and ecx,7800h
        and esi,7FFh
        or ecx,esi
        or ecx,edi
        cmp edx,8
        mov ebx,ecx
        jl @4
        inc ebp
        cmp byte ptr[NameBuffer+ebp],0
        jnz @3
        not ebx
        movzx eax,bh
        mov ah,bl
        mov dword ptr[cmpResult],eax     ;保存结果
  
;-----------------------------------
;对两算法结果进一步运算,得到中比较间值
;-----------------------------------
        movzx ecx,word ptr[result1]
        movzx esi,ax
        shl ecx,10h
        or ecx,esi
        mov bx,ax
        xor edi,edi
        mov dword ptr[result2],ecx         ;保存结果B68BD24A
        shr bx,8
        movzx ebx,bx
        mov dword ptr[result3],ebx
@7:        
        push 4
        pop ebp
        mov eax,0100F900h
        mov al,byte ptr[result1]
        mov bl,byte ptr[result1+1]
        xor esi,esi
@5:        
        mov cl,byte ptr[result2+esi]
        xor cl,al
        mov al,7Fh
        cmp al,cl
        sbb edx,edx
        mov al,cl
        shl al,1
        xor cl,al
        movzx eax,al
        neg edx
        cmp dword ptr[Table+eax*4],0
        setne al
        dec al
        and eax,3
        test edx,edx
        je @6
        xor al,2
@6:
        xor edx,edx
        mov dh,al
        shr al,1
        mov dl,cl
        shl edx,6
        mov ecx,edx
        or al,cl
        xor al,bl
        inc esi
        cmp esi,ebp
        mov bl,ch
        jl @5
        xor ecx,ecx
        mov ch,bl
        mov cl,al
        mov word ptr[result1],cx
        mov ebx,dword ptr[result3]
        movzx ecx,bl
        inc edi
        cmp edi,ecx
        jl @7
        mov edx,dword ptr[result1]         ;累计结果,作为中间值的低16位
        mov eax,dword ptr[cmpResult]
        shl eax,16
        or eax,edx                         ;执行后得到中间值
        mov dword ptr[cmpResult],eax       ;中间值存放到变量cmpbuffer中
;-------------------
;根据中间值反推注册码
;-------------------
        xor ebp,ebp
        mov eax,dword ptr[cmpResult]
        mov dword ptr[cmpbuffer],eax
@8:        
        xor edi,edi
        add edi,30h
@9:       
        mov eax,dword ptr[cmpbuffer+ebp*4-4] 
        add eax,30h
        sub eax,edi
        shr eax,1
        cdq
        mov ecx,5
        div ecx
        inc edi
        cmp edx,0
        jnz @9
        mov dword ptr[cmpbuffer+ebp*4],eax   ;我把每次计算得到的累计值保存起来,留做验算时用
        mov edx,edi
        mov byte ptr[SerialTemp+ebp],dl
        inc ebp
        cmp eax,0
        jnz @8
;--------------------------------
;取出计算出的注册码,验算正确后输出
;--------------------------------
        xor edi,edi
        xor ecx,ecx
@10:       
        mov al,byte ptr[SerialTemp+ebp-1]      ;取出计算出来的注册码 
        movzx eax,al
        lea ecx,dword ptr[ecx+ecx*4]   
        shl ecx,1
        lea ecx,dword ptr[ecx+eax-30h]
        cmp ecx,dword ptr[cmpbuffer+ebp*4-8]  ;和前面保存的累计值比较,看有无出入,没有出入则保存结果
        je @11
        mov ebx,ecx                           ;如果有出入,下面进行调整
        sub ebx,dword ptr[cmpbuffer+ebp*4-8]
        sub eax,ebx
        sub ecx,ebx
@11:        
        mov byte ptr[SerialBuffer+edi],al
        inc edi
        dec ebp
        cmp ebp,0
        jg @10         
        invoke SetDlgItemText,hDlg,IDC_CODE,addr SerialBuffer
        popad
        ret

GetKey endp


end start                

;------------------------------------------------------
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>   keygen.rc     >>>>>>     
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define IDD_DLG1 1000
#define IDC_GRP1 1007
#define IDC_NAME 1001
#define IDC_CODE 1002
#define IDC_STC1 1003
#define IDC_STC2 1004
#define IDC_OK 1005
#define IDC_ABOUT 1006
IDD_DLG1 DIALOGEX 6,5,238,52
CAPTION "Keygen For Polyview Version4.251"
FONT 8,"MS Sans Serif"
STYLE 0x10CA0880
EXSTYLE 0x00000001
BEGIN
  CONTROL "",IDC_NAME,"Edit",0x50010000,64,9,104,15,0x00000200
  CONTROL "",IDC_CODE,"Edit",0x50010800,64,29,104,15,0x00000200
  CONTROL "Licensee:",IDC_STC1,"Static",0x50000201,8,11,34,9,0x00000000
  CONTROL "License Number:",IDC_STC2,"Static",0x50000000,8,31,53,9,0x00000000
  CONTROL "GENERATE",IDC_OK,"Button",0x50010000,180,9,48,15,0x00000000
  CONTROL "ABOUT",IDC_ABOUT,"Button",0x50010000,180,29,48,15,0x00000000
  CONTROL "",IDC_GRP1,"Button",0x50000007,4,0,170,48,0x00000000
END                                    
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!