心理测试小精灵4.0版算法分析


1.fi2.5查无壳,delphi编写。上flyODBG V1.10正式汉化修改版伺候
2.概要分析:
004FAB17   mov eax,dword ptr ds:[ebx+2F0]
004FAB1D   call XLCS.00446A80
004FAB22   mov edx,dword ptr ss:[ebp-8] ;注册名"sky"
004FAB25   lea ecx,dword ptr ss:[ebp-4] 
004FAB28   mov eax,ebx      
004FAB2A   call XLCS.004FAD64    ;*注册程序,将注册名转为注册码
004FAB2F   lea edx,dword ptr ss:[ebp-C]
004FAB32   mov eax,dword ptr ds:[ebx+2F4]
004FAB38   call XLCS.00446A80
004FAB3D   mov eax,dword ptr ss:[ebp-C] ; 假码"1234"
004FAB40   mov edx,dword ptr ss:[ebp-4] ;真码"32565449433"
004FAB43   call XLCS.00404BDC    ;比较
004FAB48   jnz XLCS.004FABFC    ;不为零就die

进入004FAB2A   call XLCS.004FAD64  
....

004FADB2   call XLCS.00404A98
004FADB7   mov edi,eax
004FADB9   mov esi,1E8DEE           ;esi=2002414 初使值。
004FADBE   test edi,edi
004FADC0   jnz short XLCS.004FADD7
004FADC2   mov eax,dword ptr ds:[ebx+2F0]
004FADC8   mov edx,XLCS.004FB04C
004FADCD   call XLCS.00446AB0

......
004FAE17   lea edx,dword ptr ss:[ebp-10]
004FAE1A   xor eax,eax
004FAE1C   mov al,bl
004FAE1E   call XLCS.00409300
004FAE23   lea edx,dword ptr ss:[ebp-14]
004FAE26   xor eax,eax
004FAE28   mov al,byte ptr ss:[ebp-9]
004FAE2B   call XLCS.00409300
004FAE30   lea eax,dword ptr ss:[ebp-2C]
004FAE33   push eax
004FAE34   mov eax,dword ptr ss:[ebp-10]将注册名的16进制ASCII码转为10进制
004FAE37   call XLCS.00404A98    取第一个注册名ASCII码的10进制个位
004FAE3C   mov edx,eax      ‘s'ASCII码为115,所以A=5
004FAE3E   mov ecx,1
004FAE43   mov eax,dword ptr ss:[ebp-10]
004FAE46   call XLCS.00404CF0
004FAE4B   mov eax,dword ptr ss:[ebp-2C]
004FAE4E   call XLCS.00409364
004FAE53   mov ebx,eax
004FAE55   lea eax,dword ptr ss:[ebp-30]
004FAE58   push eax
004FAE59   mov eax,dword ptr ss:[ebp-14] 取最后个注册名的ASCII码10进制个位
004FAE5C   call XLCS.00404A98    'y'ASCII码为121,所以B=1
004FAE61   mov edx,eax
004FAE63   mov ecx,1
004FAE68   mov eax,dword ptr ss:[ebp-14]
004FAE6B   call XLCS.00404CF0
004FAE70   mov eax,dword ptr ss:[ebp-30]
004FAE73   call XLCS.00409364
004FAE78   xor edx,edx
004FAE7A   mov dl,bl
004FAE7C   imul edx,edx,7BD    ;A=5*7BD=26B1,取4位
004FAE82   and eax,0FF
004FAE87   imul edx,eax      A=A*B=26B1*1=26B1 (10进制为9905)
004FAE8A   mov dword ptr ss:[ebp-20],edx
004FAE8D   mov eax,edi
004FAE8F   test al,al
004FAE91   jbe short XLCS.004FAECF
004FAE93   mov byte ptr ss:[ebp-21],al  注册名ASCII码取10进制数
004FAE96   mov bl,1      C=1E8DEE+'s'*1+'k'*2+'y'*3.....
004FAE98   /mov eax,ebx      ;1E8DEE加第一个注册名乘1加第二个*2加...
004FAE9A   |dec eax
004FAE9B   |sub al,5                           ;  Switch (cases 0..31)
004FAE9D   |jb short XLCS.004FAEA5
004FAE9F   |sub al,2D
004FAEA1   |jb short XLCS.004FAEBB
004FAEA3   |jmp short XLCS.004FAEC9
004FAEA5   |xor eax,eax                        ;  Cases 0,1,2,3,4 of switch 004FAE9B
004FAEA7   |mov al,bl
004FAEA9   |mov edx,dword ptr ss:[ebp-4]
004FAEAC   |movzx eax,byte ptr ds:[edx+eax-1]
004FAEB1   |xor edx,edx
004FAEB3   |mov dl,bl
004FAEB5   |imul edx
004FAEB7   |add esi,eax
004FAEB9   |jmp short XLCS.004FAEC9
004FAEBB   |xor eax,eax                        ;  Cases 5,6,7,8,9,A,B,C,D,E,F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20,21,22,23,24,25,26,27,28,29,2A,2B,2C,2D,2E,2F,30,31 of switch 004FAE9B
004FAEBD   |mov al,bl
004FAEBF   |mov edx,dword ptr ss:[ebp-4]
004FAEC2   |movzx eax,byte ptr ds:[edx+eax-1]
004FAEC7   |add esi,eax
004FAEC9   |inc ebx                            ;  Default case of switch 004FAE9B
004FAECA   |dec byte ptr ss:[ebp-21]
004FAECD   \jnz short XLCS.004FAE98
004FAECF   mov eax,esi
004FAED1   xor edx,edx        ;转10进制
004FAED3   push edx                            ; /Arg2 => 00000000
004FAED4   push eax                            ; |Arg1
004FAED5   lea eax,dword ptr ss:[ebp-34]       ; |
004FAED8   call XLCS.00409330                  ; \XLCS.00409330
004FAEDD   mov eax,dword ptr ss:[ebp-34]
004FAEE0   push eax
004FAEE1   mov eax,dword ptr ss:[ebp-20]
004FAEE4   xor edx,edx        ;转10进制
004FAEE6   push edx                            ; /Arg2 => 00000000
004FAEE7   push eax                            ; |Arg1
004FAEE8   lea eax,dword ptr ss:[ebp-38]       ; |
004FAEEB   call XLCS.00409330                  ; \XLCS.00409330
004FAEF0   mov edx,dword ptr ss:[ebp-38]
004FAEF3   lea eax,dword ptr ss:[ebp-18]
004FAEF6   pop ecx
004FAEF7   call XLCS.00404AE4
004FAEFC   mov eax,dword ptr ss:[ebp-18]  '9905'+'2003106'
004FAEFF   call XLCS.00404A98      ;合并两组数A=99052003106
004FAF04   test al,al
004FAF06   jbe XLCS.004FAFF9
004FAF0C   mov byte ptr ss:[ebp-21],al          0123456789
004FAF0F   mov bl,1        用A来查表:"4059617382"
004FAF11   /xor eax,eax        即得注册码:
004FAF13   |mov al,bl        22415449047
004FAF15   |mov edx,dword ptr ss:[ebp-18]  
004FAF18   |movzx eax,byte ptr ds:[edx+eax-1]  
004FAF1D   |add eax,-30                        ;  Switch (cases 30..39)
004FAF20   |cmp eax,9
004FAF23   |ja XLCS.004FAFEF
004FAF29   |jmp dword ptr ds:[eax*4+4FAF30]
004FAF30   |dd XLCS.004FAF58                   ;  Switch table used at 004FAF29
004FAF34   |dd XLCS.004FAF6A
004FAF38   |dd XLCS.004FAF79
004FAF3C   |dd XLCS.004FAF88
004FAF40   |dd XLCS.004FAF97
004FAF44   |dd XLCS.004FAFA6
004FAF48   |dd XLCS.004FAFB5
004FAF4C   |dd XLCS.004FAFC4
004FAF50   |dd XLCS.004FAFD3
004FAF54   |dd XLCS.004FAFE2
004FAF58   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 30 ('0') of switch 004FAF1D
004FAF5B   |mov edx,XLCS.004FB070
004FAF60   |call XLCS.00404AA0
004FAF65   |jmp XLCS.004FAFEF
004FAF6A   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 31 ('1') of switch 004FAF1D
004FAF6D   |mov edx,XLCS.004FB07C
004FAF72   |call XLCS.00404AA0
004FAF77   |jmp short XLCS.004FAFEF
004FAF79   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 32 ('2') of switch 004FAF1D
004FAF7C   |mov edx,XLCS.004FB088
004FAF81   |call XLCS.00404AA0
004FAF86   |jmp short XLCS.004FAFEF
004FAF88   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 33 ('3') of switch 004FAF1D
004FAF8B   |mov edx,XLCS.004FB094
004FAF90   |call XLCS.00404AA0
004FAF95   |jmp short XLCS.004FAFEF
004FAF97   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 34 ('4') of switch 004FAF1D
004FAF9A   |mov edx,XLCS.004FB0A0
004FAF9F   |call XLCS.00404AA0
004FAFA4   |jmp short XLCS.004FAFEF
004FAFA6   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 35 ('5') of switch 004FAF1D
004FAFA9   |mov edx,XLCS.004FB0AC
004FAFAE   |call XLCS.00404AA0
004FAFB3   |jmp short XLCS.004FAFEF
004FAFB5   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 36 ('6') of switch 004FAF1D
004FAFB8   |mov edx,XLCS.004FB0B8
004FAFBD   |call XLCS.00404AA0
004FAFC2   |jmp short XLCS.004FAFEF
004FAFC4   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 37 ('7') of switch 004FAF1D
004FAFC7   |mov edx,XLCS.004FB0C4
004FAFCC   |call XLCS.00404AA0
004FAFD1   |jmp short XLCS.004FAFEF
004FAFD3   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 38 ('8') of switch 004FAF1D
004FAFD6   |mov edx,XLCS.004FB0D0
004FAFDB   |call XLCS.00404AA0
004FAFE0   |jmp short XLCS.004FAFEF
004FAFE2   |lea eax,dword ptr ss:[ebp-1C]      ;  Case 39 ('9') of switch 004FAF1D
004FAFE5   |mov edx,XLCS.004FB0DC
004FAFEA   |call XLCS.00404AA0
004FAFEF   |inc ebx                            ;  Default case of switch 004FAF1D
004FAFF0   |dec byte ptr ss:[ebp-21]
004FAFF3   \jnz XLCS.004FAF11
004FAFF9   mov eax,dword ptr ss:[ebp-8]
004FAFFC   mov edx,dword ptr ss:[ebp-1C]
004FAFFF   call XLCS.00404834

3.算法分析:
 程序将注册名分为二组处理
1)第一步:
 取第一个注册名和最后一个注册名的10进制ASCII码的个位数。
 如‘sky'
   's'ASCII码为115,所以A=5;
   'y'ASCII码为121,所以B=1;
    A=A*7BD;取16进制4位
    A=A*B。得出“9905”
  
2)第二步
    将注册名的10进制ASCII码逐个乘以它所在的位置并累加。
 如:C='s'*1+'k'*2+'y'*3。
     C=C+1E8DEE
  得出“2003106”

3)将A连接C得"99052003106"
  用上面的数字挨个查表4059617382
  得出注册码:22415449047
注册成功后会在xlcs.ini中写入注册名及注册码。  

附C语言注册机:很久没用C语言了,也不知结构是否合理:)
#include <stdio.h>
main()
{ int len,i,j,u,v,temp;
  char str[15],out[15],*p,a,b,c,table[10]={4,0,5,9,6,1,7,3,8,2};
  unsigned long m,n;
  
  printf("\n\nYshsoft(R) little Program ver 1.1\n ");/*版权信息*/
  printf("       (C)Copryright Yshsoft Corp 2001-2004.\n");
  
  printf("\nEnter a name ");           /*输入及处理*/
  scanf("%s",&str);
  len=strlen(str);temp=0;n=2002414;
  p=str;a=*p;b=*(p+len-1);
  a=a%10;b=b%10;        /*第一步处理*/
  m=a*1981*b;
  for(i=0,j=1;i<=len;i++,j++){temp=*(p+i)*j;n=n+temp;}/*第二步处理*/
  
  if(m==0)          /*m=0时第一步结果为0*/
  { out[0]=0; u=1;}
  else
  {
  for(i=0;((float)m)/10>0.01;i++){out[i]=m%10;m=m/10;}/*完成数字转字符串及连接*/
  u=i;for(i=0;i<u;i++){printf("%d",out[i]);}    /*处理的有点罗嗦:)*/
  for(i=0,j=u-1;i<j;i++,j--){c=out[i];out[i]=out[j];out[j]=c;}
  }
  for(i=u;((float)n)/10>0.01;i++){out[i]=n%10;n=n/10;}
  v=i;for(i=u;i<v;i++){printf("%d",out[i]);}
  for(i=u,j=v-1;i<j;i++,j--){c=out[i];out[i]=out[j];out[j]=c;}

 printf("The register is:\n");      /*查表并输出结果*/
 for(i=0;i<v;i++)
 {printf("%d",str[i]=table[out[i]]);}

}