编译器Magic C++ 3.0注册算法分析


[Cracker]    : prince
[时间]       : 2006.01.12
[声明]       : 只做技术交流,不做商业用途,如果你手头宽裕并喜欢这个软件的话请支持正版软件。
[E-mail]     : Cracker_prince@163.com
[软件信息]   : 无壳,MicroSoft Visual C++ 6.0编写
[软件说明]   : Window端功能强大的IDE客户段,本地编辑,然后通过网络连接目标Linux/Unix平台服务器,进行远程编译。可以大大方便Linux/Unix程序的编写、编译和调试...

  验证代码很容易找到:

--------------------------------------------------------------------------------------
0037E8B5    8BFE               mov edi,esi                            ; 取用户名
0037E8B7    33DB               xor ebx,ebx
0037E8B9    F2:AE              repne scas byte ptr es:[edi]
0037E8BB    F7D1               not ecx
0037E8BD    49                 dec ecx
0037E8BE    83F9 1E            cmp ecx,1E                             ; 以上计算用户名长度
0037E8C1    0F87 0D010000      ja ComLib.0037E9D4                     ; 用户名大于30则失败
0037E8C7    8B9424 DC000000    mov edx,dword ptr ss:[esp+DC]          ; 取假码
0037E8CE    83C9 FF            or ecx,FFFFFFFF
0037E8D1    8BFA               mov edi,edx
0037E8D3    F2:AE              repne scas byte ptr es:[edi]
0037E8D5    F7D1               not ecx
0037E8D7    49                 dec ecx
0037E8D8    83F9 28            cmp ecx,28                             ; 以上计算假码长度
0037E8DB    0F85 F3000000      jnz ComLib.0037E9D4                    ; 注册码长度必须为0x28
0037E8E1    B9 19000000        mov ecx,19
0037E8E6    8D7C24 0C          lea edi,dword ptr ss:[esp+C]
0037E8EA    F3:AB              rep stos dword ptr es:[edi]
0037E8EC    B9 19000000        mov ecx,19
0037E8F1    8D7C24 70          lea edi,dword ptr ss:[esp+70]

......

......

0037E931    C1E9 02            shr ecx,2
0037E934    F3:A5              rep movs dword ptr es:[edi],dword ptr >
0037E936    8BCA               mov ecx,edx
0037E938    83E1 03            and ecx,3
0037E93B    F3:A4              rep movs byte ptr es:[edi],byte ptr ds>
0037E93D    8D7C24 70          lea edi,dword ptr ss:[esp+70]
0037E941    83C9 FF            or ecx,FFFFFFFF
0037E944    F2:AE              repne scas byte ptr es:[edi]
0037E946    F7D1               not ecx
0037E948    49                 dec ecx
0037E949    0F84 85000000      je ComLib.0037E9D4                     ; 检测用户名是否为空
0037E94F    85C9               test ecx,ecx
0037E951    7E 0C              jle short ComLib.0037E95F
0037E953    0FBE5404 70        movsx edx,byte ptr ss:[esp+eax+70]     ; 循环取用户名单个字符
0037E958    03DA               add ebx,edx                            ; 该字符ASCII码累加
0037E95A    40                 inc eax                                ; 计数器增加
0037E95B    3BC1               cmp eax,ecx                            ; 是否取完所有用户名?
0037E95D  ^ 7C F4              jl short ComLib.0037E953
0037E95F    8BC3               mov eax,ebx                            ; 以上结果保存至EAX
0037E961    B9 6B000000        mov ecx,6B                             ; ECX=关键常数0x6B
0037E966    99                 cdq
0037E967    F7F9               idiv ecx                               ; 用户名和除以0x6B
0037E969    8D7C24 0C          lea edi,dword ptr ss:[esp+C]
0037E96D    83C9 FF            or ecx,FFFFFFFF
0037E970    33C0               xor eax,eax                            ; 清除商
0037E972    F2:AE              repne scas byte ptr es:[edi]
0037E974    F7D1               not ecx
0037E976    49                 dec ecx
0037E977    83F9 28            cmp ecx,28                             ; 再次验证假码长度
0037E97A    8BF2               mov esi,edx                            ; 保留余数至ESI
0037E97C    75 56              jnz short ComLib.0037E9D4
0037E97E    8A4424 0D          mov al,byte ptr ss:[esp+D]             ; 取假码第2个字符
0037E982    0FBE5424 0E        movsx edx,byte ptr ss:[esp+E]          ; 取假码第3个字符
0037E987    0FBE4C24 0F        movsx ecx,byte ptr ss:[esp+F]          ; 取假码第4个字符
0037E98C    83E0 7F            and eax,7F
0037E98F    33C2               xor eax,edx                            ; 假码第3个字符同第2个字符异或
0037E991    0FBE5424 0C        movsx edx,byte ptr ss:[esp+C]          ; 取假码第1个字符
0037E996    0FAFC1             imul eax,ecx                           ; 假码第4个字符乘以上面异或结果
0037E999    03C2               add eax,edx                            ; 再加上假码第1个字符
0037E99B    99                 cdq
0037E99C    F7FE               idiv esi                               ; 再除以第1步计算出的余数
0037E99E    85D2               test edx,edx                           ; 判断余数
0037E9A0    75 32              jnz short ComLib.0037E9D4              ; 不能整除则失败
0037E9A2    0FBE4424 12        movsx eax,byte ptr ss:[esp+12]         ; 取假码第7个字符
0037E9A7    0FBE4C24 11        movsx ecx,byte ptr ss:[esp+11]         ; 取假码第6个字符
0037E9AC    0FBE5424 13        movsx edx,byte ptr ss:[esp+13]         ; 取假码第8个字符
0037E9B1    23C1               and eax,ecx                            ; 第6个字符同第7个字符按位与,保留结果
0037E9B3    5F                 pop edi
0037E9B4    0FBE4C24 0C        movsx ecx,byte ptr ss:[esp+C]          ; 取假码第5个字符
0037E9B9    0FAFC2             imul eax,edx                           ; 第8个字符乘以第6、7个字符相与的结果
0037E9BC    03C1               add eax,ecx                            ; 再加第5个字符
0037E9BE    99                 cdq
0037E9BF    F7FE               idiv esi                               ; 再除以第1步的商
0037E9C1    33C0               xor eax,eax
0037E9C3    5E                 pop esi
0037E9C4    5B                 pop ebx
0037E9C5    83FA 08            cmp edx,8                              ; 余数必须为8
0037E9C8    0F94C0             sete al                                ; 验证全部完成,设置成功标志
0037E9CB    81C4 C8000000      add esp,0C8
0037E9D1    C2 0800            retn 8
0037E9D4    5F                 pop edi
0037E9D5    5E                 pop esi
0037E9D6    33C0               xor eax,eax
0037E9D8    5B                 pop ebx
0037E9D9    81C4 C8000000      add esp,0C8
0037E9DF    C2 0800            retn 8

--------------------------------------------------------------------------------------
  
  可见过程分两步验证:第1步验证前4个字符,第2步验证后4个字符,再后面的32个字符不参与注册验证。过程简单清晰,C语言注册机代码如下:

--------------------------------------------------------------------------------------
/*++
  Project name    : Keygen for Magic C++ 3.0

  File name       : Keygen07.cpp

  Coded by        : prince

  Date            : 01/12/2006

  E-mail          : Cracker_prince@163.com

  QQ              : 812937

  Description     : Just a game, don't use it in commerce.
--*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>


/*
 *  Declaration
 */
void FillKeyRandom(char *chKey);

int main(int argc, char* argv[])
{
  //
  // Local variable(s)
  //
  char    chKey[41]  = {0};
  char    szUser[30]  = {0};
  int      nUserName  = 0;
  int      i, nNameRemainder;
  int      nTemp1, nTemp2;

  //
  // Get user name
  //
  printf("Please input user name(3 - 30 characters):\n");
  scanf("%s", szUser);

  //
  // Fill the key with random characters
  //
  FillKeyRandom(chKey);

  //
  // Calculate the 1st key and the 5th key
  //
  for (i = 0; i < 30 && szUser[i] != '\0'; i++)
  {
    nUserName += szUser[i];
  }

  nNameRemainder = nUserName % 0x6b;

  nTemp1  = chKey[2] ^ chKey[1];
  nTemp2  = chKey[3] * nTemp1;

  chKey[0] = (nNameRemainder * 100 - nTemp2) % nNameRemainder;

  if ((int)chKey[0] < 33)
  {
    do 
    {
      chKey[0] += nNameRemainder;
    } while(chKey[0] < 33);
  }
  else if ((int)chKey[0] > 122)
  {
    do 
    {
      chKey[0] -= nNameRemainder;
    } while(chKey[0] > 122);
  }


  nTemp1 = chKey[5] & chKey[6];
  nTemp1 *= chKey[7];

  chKey[4] = (nNameRemainder * 100 + 8 - nTemp1) % nNameRemainder;

  if (chKey[4] < 33)
  {
    do 
    {
      chKey[4] += nNameRemainder;
    } while(chKey[4] < 33);
  }
  else if (chKey[4] > 122)
  {
    do 
    {
      chKey[4] -= nNameRemainder;
    } while(chKey[4] > 122);
  }

  printf("Woooo~ :) Enjoy your private key: \n%s\n", chKey);

  return 0;
}


void FillKeyRandom(char *chKey)
{
  //
  // Sets a random starting point
  //
  srand((unsigned)time(NULL));

  for (int i = 0; i < 40; i++)
  {
    chKey[i] = rand() % 89 + 33  ;
  }

  return;
}

----------------------------------------------------------------------------
  注册信息保存在:KKEY_CURRENT_USER\Software\Magic C Enterrise Edition\User 下面的Reg Code键里面,删除可重新注册。
  菜鸟写菜文,大侠见笑了~ 

                                                                     prince 2006.01.04