• 标 题:万象幻境网管专家普及版密码算法 (3千字)
  • 作 者:zmworm
  • 时 间:2002-6-9 13:08:50
  • 链 接:http://bbs.pediy.com

本文可以随意转载,但请保留本文的完整性

题目:万象幻境网管专家普及版密码算法

作者:zmworm
算法描述语言:VC
适应读者:编程人员
万象幻境网管专家普及版密码算法
万象幻境网管专家普及版密码破解器v0.1发布到现在已经近一年了,许多人问我万象幻境的密码算法是什么,但我一直没有公布.随着万象幻境R12的发行(其算法已经改变),面对许多国产软件的密码保护力度还不够强的现状.我决定将万象幻境的密码算法公开.
这次公布的解密算法.加密算法时此算法的逆,所以没有写.
希望本文能对大家编写软件有所帮助,对国产软件有所帮助.
希望和大家共同探讨有关算法的问题我的邮箱zmworm@sohu.com
注1:本文只是讨论算法,而不是针对某个软件进行解密.所以对seed1,seed2,seed3进行了处理
注2:本文不讨论R12的密码算法,事实上R12的算法不比此算法强,而且令人气愤的是,R12算法的密钥竟是GODPIG!!!
原理说明:
万象加密时,得到的密文不同(密文在注册表“HKEY_LOCAL_MACHINE\Software\万象幻境\专家系列网管软件\”)。
玄机何在?其实很简单,在每次加密时“万象”都要随机的选取一个16位初始向量IV和两个16位参数m1、
m2,并将它们加密后放在密文之前供解密时使用,然后再利用这三个参数对明文进行加密。
解密时,需先对这三个值解密,再对密文解密。
无论IV、m1、m2还是明文M都有了同一算法(IV、m1、m2加密过程中的初使向量和两个参数都是固定的)。
这种算法属于较为复杂的CBC模式.
解密函数解密
void uncode(char * szString,CString& sVal)
//szString 为密文;sVal为返回的明文;函数uncode的作用是解密
{
UINT seed1=0x1111,seed2=0x2222,seed3=0x3333;//关键!知道这几个值不同加解密的结果也不同
UINT IV=0,m1=0,m2=0;
//还原出参数IV
int i;
char key1[3]="";
UINT edx=seed1;//密钥1
for(i=0;i<=2;i++)
{
char inte[3]="";
inte[0]=szString[3*i];
inte[1]=szString[3*i+1];
inte[2]=szString[3*i+2];//取三位
key1[i]=CharToInt(inte);//将此三位数串转成数
int mk=(edx&0x0000ff00)>>8;//取密钥1的3 4位准备做异或
UINT temp=key1[i];
temp&=0x000000ff;
edx=(temp+edx)*seed2+seed3;//改变密钥1的值
key1[i]^=mk;//还原参数1的第i位
};
IV=(key1[0]-'0')*100+(key1[1]-'0')*10+(key1[2]-'0');
//还原出参数m1
char key2[5]="";
edx=0xseed1;
for(i=0;i<=4;i++)
{
char inte[3]="";
inte[0]=szString[3*(i+3)];
inte[1]=szString[3*(i+3)+1];
inte[2]=szString[3*(i+3)+2];
key2[i]=CharToInt(inte);
int mk=(edx&0x0000ff00)>>8;
UINT temp=key2[i];
temp&=0x000000ff;
edx=(temp+edx)*seed2+seed3;
key2[i]^=mk;
};
m1=(key2[0]-'0')*10000+(key2[1]-'0')*1000+(key2[2]-'0')*100+(key2[3]-'0')*10+(key2[4]-'0');
//还原出参数k2
char key3[5]="";
edx=seed1;
for(i=0;i<=4;i++)
{
char inte[3]="";
inte[0]=szString[3*(i+8)];
inte[1]=szString[3*(i+8)+1];
inte[2]=szString[3*(i+8)+2];
key3[i]=CharToInt(inte);
int mk=(edx&0x0000ff00)>>8;
UINT temp=key3[i];
temp&=0x000000ff;
edx=(temp+edx)*seed2+seed3;
key3[i]^=mk;
};
m2=(key3[0]-'0')*10000+(key3[1]-'0')*1000+(key3[2]-'0')*100+(key3[3]-'0')*10+(key3[4]-'0');
//利用参数k1,k2,k3将密文还原成明文密码
i=0;
char Password[255]="";
edx=IV;
while(szString[(i+13)*3]!='\0')
{
char inte[3]="";
inte[0]=szString[3*(i+13)];
inte[1]=szString[3*(i+13)+1];
inte[2]=szString[3*(i+13)+2];
Password[i]=CharToInt(inte);
int mk=(edx&0x0000ff00)>>8;
UINT temp=Password[i];
temp&=0x000000ff;
edx=(temp+edx)*m1+m2;
Password[i]^=mk;
i++;
};
//返回密码
sVal=Password;
}
char CharToInt(char * ch)
{
int i;
i=(ch[0]-'0')*100+(ch[1]-'0')*10+ch[2]-'0';
i=i%256;
return i;
}