邪恶八进制信息安全团队技术讨论组's Archiver

pub!1c 2006-1-14 14:26

[转载]编译器Magic C++ 3.0注册算法分析

文章作者:prince


[Cracker]   : prince
[时间]     : 2006.01.12
[声明]     : 只做技术交流,不做商业用途,如果你手头宽裕并喜欢这个软件的话请支持正版软件。
[E-mail]    : [email]Cracker_prince@163.com[/email]
[软件信息]  : 无壳,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       : [email]Cracker_prince@163.com[/email]

  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] != &#39;\0&#39;; i++)
  {
   nUserName += szUser[i];
  }

  nNameRemainder = nUserName % 0x6b;

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

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

  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;// + 0x32;

  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键里面,删除可重新注册。
  菜鸟写菜文,大侠见笑了~

页: [1]
© 1999-2008 EvilOctal Security Team