【文章标题】: Techra Virtual Programmable Keyboard 1.02算法分析 
【文章作者】: qifeon
【软件名称】: Techra Virtual Programmable Keyboard 
【下载地址】: http://www.techrasoft.com/index.asp
【保护方式】: 注册码
【编写语言】: 英文
【操作平台】: winxp sp2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  一、分析过程
  
  首先PEID查壳,Borland Delphi 6.0 - 7.0编写,无壳。运行程序,输入“qifeon,123456”,有错误提示"invalid unlock information"。好的,我们就利用最简单而有效的查找字符串的方法。
  
  不要小瞧它哦,不必再去麻烦DeDe先生了。OD载入,插件查找上面的错误提示。
  Ultra String Reference, 条目 3004
   Address=0056D6B0
   Disassembly=mov     eax, 0056D7D4
   Text String=invalid unlock information!
  
  双击后来到
  
  *******************************************************************************************************************************************************
  
  0056D6A9   .^\E9 2A69E9FF   jmp     00403FD8                         ;  向上找到跳转
  0056D6AE   .^ EB F0         jmp     short 0056D6A0
  0056D6B0   > \B8 D4D75600   mov     eax, 0056D7D4                    ;  invalid unlock information!
  0056D6B5   .  E8 C66AECFF   call    00434180
  0056D6BA   .  8B83 18030000 mov     eax, dword ptr [ebx+318]
  0056D6C0   .  8B10          mov     edx, dword ptr [eax]
  0056D6C2   .  FF92 C4000000 call    dword ptr [edx+C4]
  0056D6C8   >  33C0          xor     eax, eax
  0056D6CA   .  5A            pop     edx
  0056D6CB   .  59            pop     ecx
  0056D6CC   .  59            pop     ecx
  
  *****************************************************************************************************************************************************
  
  由跳转向上找到注册按钮事件段首
  
  *****************************************************************************************************************************************************
  
  0056D536   .  55            push    ebp                              ;  段首
  0056D537   .  68 F8D65600   push    0056D6F8
  0056D53C   .  64:FF30       push    dword ptr fs:[eax]
  0056D53F   .  64:8920       mov     dword ptr fs:[eax], esp
  0056D542   .  8D55 F8       lea     edx, dword ptr [ebp-8]
  0056D545   .  8B83 18030000 mov     eax, dword ptr [ebx+318]
  0056D54B   .  E8 7069EEFF   call    00453EC0                         ;  取用户名长度
  0056D550   .  837D F8 00    cmp     dword ptr [ebp-8], 0
  0056D554   .  74 14         je      short 0056D56A                   ;  用户名为空则跳
  0056D556   .  8D55 F4       lea     edx, dword ptr [ebp-C]
  0056D559   .  8B83 1C030000 mov     eax, dword ptr [ebx+31C]
  0056D55F   .  E8 5C69EEFF   call    00453EC0                         ;  取试炼码长度
  0056D564   .  837D F4 00    cmp     dword ptr [ebp-C], 0                 试炼码是否为空?
  0056D568   .  75 1D         jnz     short 0056D587                      
  0056D56A   >  B8 0CD75600   mov     eax, 0056D70C                    ;  please enter unlock information!
  0056D56F   .  E8 0C6CECFF   call    00434180
  0056D574   .  8B83 18030000 mov     eax, dword ptr [ebx+318]
  0056D57A   .  8B10          mov     edx, dword ptr [eax]
  0056D57C   .  FF92 C4000000 call    dword ptr [edx+C4]
  0056D582   .  E9 41010000   jmp     0056D6C8
  0056D587   >  8D55 F0       lea     edx, dword ptr [ebp-10]
  0056D58A   .  8B83 1C030000 mov     eax, dword ptr [ebx+31C]
  0056D590   .  E8 2B69EEFF   call    00453EC0
  0056D595   .  8B45 F0       mov     eax, dword ptr [ebp-10]          ;  试炼码放入eax
  0056D598   .  50            push    eax
  0056D599   .  8D55 E8       lea     edx, dword ptr [ebp-18]
  0056D59C   .  8B83 18030000 mov     eax, dword ptr [ebx+318]
  0056D5A2   .  E8 1969EEFF   call    00453EC0
  0056D5A7   .  8B55 E8       mov     edx, dword ptr [ebp-18]          ;  用户名放入edx
  0056D5AA   .  8D4D EC       lea     ecx, dword ptr [ebp-14]
  0056D5AD   .  A1 74B75800   mov     eax, dword ptr [58B774]
  0056D5B2   .  8B00          mov     eax, dword ptr [eax]
  0056D5B4   .  E8 D3140000   call    0056EA8C                         ;  算法call,我们马上进入
  0056D5B9   .  8B55 EC       mov     edx, dword ptr [ebp-14]          ;  真正注册码
  0056D5BC   .  58            pop     eax                              ;  试炼码
  0056D5BD   .  E8 A274E9FF   call    00404A64                         ;  真正注册码与假码相比较
  0056D5C2   .  0F85 E8000000 jnz     0056D6B0                         ;  关键跳转
  0056D5C8   .  33C0          xor     eax, eax
  0056D5CA   .  55            push    ebp
  0056D5CB   .  68 A9D65600   push    0056D6A9
  0056D5D0   .  64:FF30       push    dword ptr fs:[eax]
  0056D5D3   .  64:8920       mov     dword ptr fs:[eax], esp
  0056D5D6   .  B2 01         mov     dl, 1
  0056D5D8   .  A1 489E4300   mov     eax, dword ptr [439E48]
  0056D5DD   .  E8 6AC9ECFF   call    00439F4C
  0056D5E2   .  8945 FC       mov     dword ptr [ebp-4], eax
  0056D5E5   .  BA 02000080   mov     edx, 80000002
  0056D5EA   .  8B45 FC       mov     eax, dword ptr [ebp-4]
  0056D5ED   .  E8 FAC9ECFF   call    00439FEC
  0056D5F2   .  B1 01         mov     cl, 1
  0056D5F4   .  BA 38D75600   mov     edx, 0056D738                    ;  software\vpk
  0056D5F9   .  8B45 FC       mov     eax, dword ptr [ebp-4]
  0056D5FC   .  E8 2FCBECFF   call    0043A130
  0056D601   .  8D55 E4       lea     edx, dword ptr [ebp-1C]
  0056D604   .  8B83 18030000 mov     eax, dword ptr [ebx+318]
  0056D60A   .  E8 B168EEFF   call    00453EC0
  0056D60F   .  8B45 E4       mov     eax, dword ptr [ebp-1C]
  0056D612   .  50            push    eax
  0056D613   .  B9 50D75600   mov     ecx, 0056D750                    ;  registeredto
  0056D618   .  33D2          xor     edx, edx
  0056D61A   .  8B45 FC       mov     eax, dword ptr [ebp-4]
  0056D61D   .  E8 9ECFECFF   call    0043A5C0
  0056D622   .  8D55 E0       lea     edx, dword ptr [ebp-20]
  0056D625   .  8B83 1C030000 mov     eax, dword ptr [ebx+31C]
  0056D62B   .  E8 9068EEFF   call    00453EC0
  0056D630   .  8B45 E0       mov     eax, dword ptr [ebp-20]
  0056D633   .  50            push    eax
  0056D634   .  B9 68D75600   mov     ecx, 0056D768                    ;  unlockcode
  0056D639   .  33D2          xor     edx, edx
  0056D63B   .  8B45 FC       mov     eax, dword ptr [ebp-4]
  0056D63E   .  E8 7DCFECFF   call    0043A5C0
  0056D643   .  A1 74B75800   mov     eax, dword ptr [58B774]
  0056D648   .  8B00          mov     eax, dword ptr [eax]
  0056D64A   .  E8 FD120000   call    0056E94C
  0056D64F   .  84C0          test    al, al
  0056D651   .  74 2F         je      short 0056D682
  0056D653   .  B8 7CD75600   mov     eax, 0056D77C                    ;  software has been successfully unlocked!
  0056D658   .  E8 236BECFF   call    00434180
  0056D65D   .  A1 74B75800   mov     eax, dword ptr [58B774]
  0056D662   .  8B00          mov     eax, dword ptr [eax]
  0056D664   .  8B80 28030000 mov     eax, dword ptr [eax+328]
  0056D66A   .  33D2          xor     edx, edx
  0056D66C   .  E8 078AEFFF   call    00466078
  0056D671   .  C783 4C020000>mov     dword ptr [ebx+24C], 1
  0056D67B   .  E8 3C6AE9FF   call    004040BC
  0056D680   .  EB 46         jmp     short 0056D6C8
  0056D682   >  B8 B0D75600   mov     eax, 0056D7B0                    ;  error unlocking software!
  0056D687   .  E8 F46AECFF   call    00434180
  0056D68C   .  E8 2B6AE9FF   call    004040BC
  
  *******************************************************************************************************************************************************
  
  0056D5B4处,进入算法 call    0056EA8C 
  
  *********************************************************************************************************************************************8**********
  
  
  0056EA8C   $  55            push    ebp
  0056EA8D   .  8BEC          mov     ebp, esp
  0056EA8F   .  6A 00         push    0
  0056EA91   .  6A 00         push    0
  0056EA93   .  6A 00         push    0
  0056EA95   .  6A 00         push    0
  0056EA97   .  6A 00         push    0
  0056EA99   .  53            push    ebx
  0056EA9A   .  56            push    esi
  0056EA9B   .  57            push    edi
  0056EA9C   .  8BF9          mov     edi, ecx
  0056EA9E   .  8955 FC       mov     dword ptr [ebp-4], edx
  0056EAA1   .  8B45 FC       mov     eax, dword ptr [ebp-4]
  0056EAA4   .  E8 5F60E9FF   call    00404B08
  0056EAA9   .  33C0          xor     eax, eax
  0056EAAB   .  55            push    ebp
  0056EAAC   .  68 E2EB5600   push    0056EBE2
  0056EAB1   .  64:FF30       push    dword ptr fs:[eax]
  0056EAB4   .  64:8920       mov     dword ptr fs:[eax], esp
  0056EAB7   .  33C0          xor     eax, eax
  0056EAB9   .  55            push    ebp
  0056EABA   .  68 B5EB5600   push    0056EBB5
  0056EABF   .  64:FF30       push    dword ptr fs:[eax]
  0056EAC2   .  64:8920       mov     dword ptr fs:[eax], esp
  0056EAC5   .  8D45 F4       lea     eax, dword ptr [ebp-C]
  0056EAC8   .  8B4D FC       mov     ecx, dword ptr [ebp-4]           ;  用户名
  0056EACB   .  BA F8EB5600   mov     edx, 0056EBF8                    ;  ASCII "TEST123"
  0056EAD0   .  E8 8F5EE9FF   call    00404964                         ;  连接固定字符串"TEST123"与用户名,设为link
  0056EAD5   .  8B45 F4       mov     eax, dword ptr [ebp-C]
  0056EAD8   .  8BD7          mov     edx, edi
  0056EADA   .  E8 598AECFF   call    00437538                         ;  把连接后字符串link翻转,设为reverse
  0056EADF   .  33C0          xor     eax, eax
  0056EAE1   .  8945 F8       mov     dword ptr [ebp-8], eax
  0056EAE4   .  8B07          mov     eax, dword ptr [edi]
  0056EAE6   .  E8 2D5EE9FF   call    00404918
  0056EAEB   .  8BF0          mov     esi, eax                         ;  字符串reverse长度设为len放入esi
  0056EAED   .  85F6          test    esi, esi
  0056EAEF   .  7E 15         jle     short 0056EB06
  0056EAF1   .  BB 01000000   mov     ebx, 1                           ;  ebx=1
  0056EAF6   >  8B07          mov     eax, dword ptr [edi]             ;  字符串reverse放入eax
  0056EAF8   .  0FB64418 FF   movzx   eax, byte ptr [eax+ebx-1]        ;  字符串reverse逐位取扩展放入eax
  0056EAFD   .  F7EB          imul    ebx                              ;  eax=eax*ebx
  0056EAFF   .  0145 F8       add     dword ptr [ebp-8], eax           ;  [ebp-8]=[ebp-8]+eax,循环最后计算值保存于ebp-8,设为sum
  0056EB02   .  43            inc     ebx                              ;  ebx增1
  0056EB03   .  4E            dec     esi                              ;  esi减1
  0056EB04   .^ 75 F0         jnz     short 0056EAF6                   ;  esi不为0则继续循环
  0056EB06   >  8B07          mov     eax, dword ptr [edi]
  0056EB08   .  E8 0B5EE9FF   call    00404918
  0056EB0D   .  8BF0          mov     esi, eax
  0056EB0F   .  85F6          test    esi, esi
  0056EB11   .  7E 3C         jle     short 0056EB4F
  0056EB13   .  BB 01000000   mov     ebx, 1
  0056EB18   >  8B07          mov     eax, dword ptr [edi]             ;  字符串reverse放入eax
  0056EB1A   .  0FB64418 FF   movzx   eax, byte ptr [eax+ebx-1]        ;  字符串reverse逐位取扩展放入eax
  0056EB1F   .  F7EB          imul    ebx                              ;  eax=eax*ebx
  0056EB21   .  83C0 02       add     eax, 2                           ;  eax=eax+2
  0056EB24   .  3345 F8       xor     eax, dword ptr [ebp-8]           ;  eax=eax xor sum
  0056EB27   .  B9 0A000000   mov     ecx, 0A                          ;  ecx=0Ah
  0056EB2C   .  99            cdq                                      ;  edx清零
  0056EB2D   .  F7F9          idiv    ecx                              ;  eax/ecx 商保存在 eax余数保存于edx
  0056EB2F   .  8BC2          mov     eax, edx
  0056EB31   .  8D55 F0       lea     edx, dword ptr [ebp-10]
  0056EB34   .  E8 17A4E9FF   call    00408F50                         ;  把上面逐位计算的余数16进制数字转换为对应字符
  0056EB39   .  8B45 F0       mov     eax, dword ptr [ebp-10]
  0056EB3C   .  8A00          mov     al, byte ptr [eax]               ;  转换后字符放入al
  0056EB3E   .  50            push    eax
  0056EB3F   .  8BC7          mov     eax, edi
  0056EB41   .  E8 2A60E9FF   call    00404B70
  0056EB46   .  5A            pop     edx                              ;  dl内的值等于上面al数值
  0056EB47   .  885418 FF     mov     byte ptr [eax+ebx-1], dl         ;  dl值替换字符串reverse内字符
  0056EB4B   .  43            inc     ebx
  0056EB4C   .  4E            dec     esi                              ;  esi不为0则继续循环
  0056EB4D   .^ 75 C9         jnz     short 0056EB18
  0056EB4F   >  8B07          mov     eax, dword ptr [edi]             ;  reverse全部替换后得到字符串设为replace
  0056EB51   .  E8 C25DE9FF   call    00404918
  0056EB56   .  8BF0          mov     esi, eax                         ;  字符串replace长度
  0056EB58   .  85F6          test    esi, esi
  0056EB5A   .  7E 3D         jle     short 0056EB99
  0056EB5C   .  BB 01000000   mov     ebx, 1
  0056EB61   >  8B07          mov     eax, dword ptr [edi]             ;  字符串replace放入eax
  0056EB63   .  0FB64418 FF   movzx   eax, byte ptr [eax+ebx-1]        ;  字符串replace逐位取扩展放入eax
  0056EB68   .  F7EB          imul    ebx                              ;  eax值乘以ebx
  0056EB6A   .  8BD0          mov     edx, eax                         ;  相乘得值由eax放入edx
  0056EB6C   .  C1E0 03       shl     eax, 3                           ;  eax值左移3位
  0056EB6F   .  2BC2          sub     eax, edx                         ;  eax=eax-edx
  0056EB71   .  B9 0A000000   mov     ecx, 0A                          ;  ecx=10
  0056EB76   .  99            cdq                                      ;  edx清零
  0056EB77   .  F7F9          idiv    ecx                              ;  eax/ecx 商保存在 eax余数保存于edx
  0056EB79   .  8BC2          mov     eax, edx                         ;  余数传送给eax
  0056EB7B   .  8D55 EC       lea     edx, dword ptr [ebp-14]
  0056EB7E   .  E8 CDA3E9FF   call    00408F50                         ;  把上面逐位计算的余数16进制数字转换为对应字符
  0056EB83   .  8B45 EC       mov     eax, dword ptr [ebp-14]
  0056EB86   .  8A00          mov     al, byte ptr [eax]               ;  转换后字符放入al
  0056EB88   .  50            push    eax
  0056EB89   .  8BC7          mov     eax, edi
  0056EB8B   .  E8 E05FE9FF   call    00404B70
  0056EB90   .  5A            pop     edx                              ;  dl内的值等于上面al数值
  0056EB91   .  885418 FF     mov     byte ptr [eax+ebx-1], dl         ;  dl值替换字符串reverse内字符
  0056EB95   .  43            inc     ebx
  0056EB96   .  4E            dec     esi
  0056EB97   .^ 75 C8         jnz     short 0056EB61
  0056EB99   >  57            push    edi
  0056EB9A   .  8B07          mov     eax, dword ptr [edi]             ;  replace全部替换后的字符串设为regcode
  0056EB9C   .  B9 06000000   mov     ecx, 6                           ;  ecx=6
  0056EBA1   .  BA 01000000   mov     edx, 1
  0056EBA6   .  E8 CD5FE9FF   call    00404B78                         ;  取字符串regcode前6位作为注册码
  0056EBAB   .  33C0          xor     eax, eax
  0056EBAD   .  5A            pop     edx
  0056EBAE   .  59            pop     ecx
  0056EBAF   .  59            pop     ecx
  0056EBB0   .  64:8910       mov     dword ptr fs:[eax], edx
  0056EBB3   .  EB 0A         jmp     short 0056EBBF
  0056EBB5   .^ E9 6A51E9FF   jmp     00403D24
  0056EBBA   .  E8 CD54E9FF   call    0040408C
  0056EBBF   >  33C0          xor     eax, eax
  0056EBC1   .  5A            pop     edx
  0056EBC2   .  59            pop     ecx
  0056EBC3   .  59            pop     ecx
  0056EBC4   .  64:8910       mov     dword ptr fs:[eax], edx
  0056EBC7   .  68 E9EB5600   push    0056EBE9
  0056EBCC   >  8D45 EC       lea     eax, dword ptr [ebp-14]
  0056EBCF   .  BA 03000000   mov     edx, 3
  0056EBD4   .  E8 A35AE9FF   call    0040467C
  0056EBD9   .  8D45 FC       lea     eax, dword ptr [ebp-4]
  0056EBDC   .  E8 775AE9FF   call    00404658
  0056EBE1   .  C3            retn
  
  *********************************************************************************************************************************************
  
  
  二、注册算法总结
  
  算法有些琐碎,经过多次转换。本人尝试描述清楚。
  
          
  1、固定字符串"TEST123"与用户名name连接得到字符串link;
  
  2、翻转字符串link得到字符串reverse;
  
  3、字符reverse[i]乘以字符串对应位置(i+1)依次相加之和为sum;
  
  4、字符reverse[i]乘以字符串对应位置(i+1),然后加上2,再与sum异或,异或后的值除以10,
  
    余数转化为16进制对应的字符替换掉reverse[i],得到字符串replace;(如0x1转为字符"1")
  
  5、字符replace[i]乘以字符串对应位置(i+1),所得数值左移3位,减去replace[i]*(i+1),再除以10,
  
   余数转化为16进制对应的字符替换掉replace[i],得到字符串regcode;
  
  6、取字符串regcode前6位组成的字符串即为注册码。
  
  
  *************************************************************************************************************************************************
  
  三、C语言注册机源码
  
  
  #include "stdio.h"
  #include "string.h"
  void main()
  {    
    int i,j,k,len,o,p;
     static int sum=0;
    char regcode[30];
    char replace[30];
    char reverse[30];
    char name[30];
    char link[30]="TEST123";
    printf("请输入用户名:");
    scanf("%s",name);
    strcat (link,name);
          strrev(link);
          strcpy(reverse,link);
    len=strlen(reverse);
    for (i=0;i<len;i++)
    sum=sum+reverse[i]*(i+1);
    for (i=0;i<len;i++)
    {k=reverse[i]*(i+1)+2 ;
      j=k ^ sum;
    replace[i]=j % 10+0x30;
     }
    
    for (i=0;i<len;i++)
    {  
      o=replace[i]*(i+1);
      p=o<< 3;
      regcode[i]=(p-o) % 10+0x30;
    }
    regcode[6]='\0';
    
    printf("注册码是:%s",regcode);
    
  }
  
  
  
  
  
     
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年08月09日 16:04:38