编译器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
[注意]APP应用上架合规检测服务,协助应用顺利上架!