最近做了一个绿色免安装软件,领导临时要求加个注册机制,不能让现场工程师随意复制。事出突然,只能在现场开发(离开现场软件就不受我们控了)。花了不到两个小时实现了简单的注册机制,稍作整理。
基本原理:1.软件一运行就把计算机的CPU、主板、BIOS、MAC地址记录下来,然后加密(key=key1)生成文件;2.注册机将该文件内容MD5加密后再进行一次加密(key=key2)保存成注册文件;3.注册验证的逻辑,计算机信息加密后(key=key1)加密md5==注册文件解密(key=key2);
另外,采用ConfuserEx将可执行文件加密;这样别人要破解也就需要点力气了(没打算防破解,本意只想防复制的),有能力破解的人也不在乎破解这个软件了(开发这个软件前后只花了一周时间而已);
技术上主要三个模块:1.获取电脑相关硬件信息(可参考);2.加密解密;3.读写文件;
1.获取电脑相关硬件信息代码:
[csharp]view plaincopy
publicclassComputerInfo
{
publicstaticstringGetComputerInfo()
{
stringinfo=string.Empty;
stringcpu=GetCPUInfo();
stringbaseBoard=GetBaseBoardInfo();
stringbios=GetBIOSInfo();
stringmac=GetMACInfo();
info=string.Concat(cpu,baseBoard,bios,mac);
returninfo;
}
privatestaticstringGetCPUInfo()
{
stringinfo=string.Empty;
info=GetHardWareInfo("Win32_Processor","ProcessorId");
returninfo;
}
privatestaticstringGetBIOSInfo()
{
stringinfo=string.Empty;
info=GetHardWareInfo("Win32_BIOS","SerialNumber");
returninfo;
}
privatestaticstringGetBaseBoardInfo()
{
stringinfo=string.Empty;
info=GetHardWareInfo("Win32_BaseBoard","SerialNumber");
returninfo;
}
privatestaticstringGetMACInfo()
{
stringinfo=string.Empty;
info=GetHardWareInfo("Win32_BaseBoard","SerialNumber");
returninfo;
}
privatestaticstringGetHardWareInfo(stringtypePath,stringkey)
{
try
{
ManagementClassmanagementClass=newManagementClass(typePath);
ManagementObjectCollectionmn=managementClass.GetInstances();
PropertyDataCollectionproperties=managementClass.Properties;
foreach(PropertyDatapropertyinproperties)
{
if(property.Name==key)
{
foreach(ManagementObjectminmn)
{
returnm.Properties[property.Name].Value.ToString();
}
}
}
}
catch(Exceptionex)
{
//这里写异常的处理
}
returnstring.Empty;
}
privatestaticstringGetMacAddressByNetworkInformation()
{
stringkey="SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
stringmacAddress=string.Empty;
try
{
NetworkInterface[]nics=NetworkInterface.GetAllNetworkInterfaces();
foreach(NetworkInterfaceadapterinnics)
{
if(workInterfaceType==NetworkInterfaceType.Ethernet
&&adapter.GetPhysicalAddress().ToString().Length!=0)
{
stringfRegistryKey=key+adapter.Id+"\\Connection";
RegistryKeyrk=Registry.LocalMachine.OpenSubKey(fRegistryKey,false);
if(rk!=null)
{
stringfPnpInstanceID=rk.GetValue("PnpInstanceID","").ToString();
intfMediaSubType=Convert.ToInt32(rk.GetValue("MediaSubType",0));
if(fPnpInstanceID.Length>3&&
fPnpInstanceID.Substring(0,3)=="PCI")
{
macAddress=adapter.GetPhysicalAddress().ToString();
for(inti=1;i<6;i++)
{
macAddress=macAddress.Insert(3*i-1,":");
}
break;
}
}
}
}
}
catch(Exceptionex)
{
//这里写异常的处理
}
returnmacAddress;
}
}
2.加密解密代码;
[csharp]view plaincopy
publicenumEncryptionKeyEnum
{
KeyA,
KeyB
}
publicclassEncryptionHelper
{
stringencryptionKeyA="pfe_Nova";
stringencryptionKeyB="WorkHard";
stringmd5Begin="Hello";
stringmd5End="World";
stringencryptionKey=string.Empty;
publicEncryptionHelper()
{
this.InitKey();
}
publicEncryptionHelper(EncryptionKeyEnumkey)
{
this.InitKey(key);
}
privatevoidInitKey(EncryptionKeyEnumkey=EncryptionKeyEnum.KeyA)
{
switch(key)
{
caseEncryptionKeyEnum.KeyA:
encryptionKey=encryptionKeyA;
break;
caseEncryptionKeyEnum.KeyB:
encryptionKey=encryptionKeyB;
break;
}
}
publicstringEncryptString(stringstr)
{
returnEncrypt(str,encryptionKey);
}
publicstringDecryptString(stringstr)
{
returnDecrypt(str,encryptionKey);
}
publicstringGetMD5String(stringstr)
{
str=string.Concat(md5Begin,str,md5End);
MD5md5=newMD5CryptoServiceProvider();
byte[]fromData=Encoding.Unicode.GetBytes(str);
byte[]targetData=puteHash(fromData);
stringmd5String=string.Empty;
foreach(varbintargetData)
md5String+=b.ToString("x2");
returnmd5String;
}
privatestringEncrypt(stringstr,stringsKey)
{
DESCryptoServiceProviderdes=newDESCryptoServiceProvider();
byte[]inputByteArray=Encoding.Default.GetBytes(str);
des.Key=ASCIIEncoding.ASCII.GetBytes(sKey);
des.IV=ASCIIEncoding.ASCII.GetBytes(sKey);
MemoryStreamms=newMemoryStream();
CryptoStreamcs=newCryptoStream(ms,des.CreateEncryptor(),CryptoStreamMode.Write);
cs.Write(inputByteArray,0,inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilderret=newStringBuilder();
foreach(bytebinms.ToArray())
{
ret.AppendFormat("{0:X2}",b);
}
ret.ToString();
returnret.ToString();
}
privatestringDecrypt(stringpToDecrypt,stringsKey)
{
DESCryptoServiceProviderdes=newDESCryptoServiceProvider();
byte[]inputByteArray=newbyte[pToDecrypt.Length/2];
for(intx=0;x<pToDecrypt.Length/2;x++)
{
inti=(Convert.ToInt32(pToDecrypt.Substring(x*2,2),16));
inputByteArray[x]=(byte)i;
}
des.Key=ASCIIEncoding.ASCII.GetBytes(sKey);
des.IV=ASCIIEncoding.ASCII.GetBytes(sKey);
MemoryStreamms=newMemoryStream();
CryptoStreamcs=newCryptoStream(ms,des.CreateDecryptor(),CryptoStreamMode.Write);
cs.Write(inputByteArray,0,inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilderret=newStringBuilder();
returnSystem.Text.Encoding.Default.GetString(ms.ToArray());
}
}
注:这边在MD5时前后各加了一段字符,这样增加一点破解难度。
3.读写文件
[csharp]view plaincopy
publicclassRegistFileHelper
{
publicstaticstringComputerInfofile="ComputerInfo.key";
publicstaticstringRegistInfofile="RegistInfo.key";
publicstaticvoidWriteRegistFile(stringinfo)
{
WriteFile(info,RegistInfofile);
}
publicstaticvoidWriteComputerInfoFile(stringinfo)
{
WriteFile(info,ComputerInfofile);
}
publicstaticstringReadRegistFile()
{
returnReadFile(RegistInfofile);
}
publicstaticstringReadComputerInfoFile()
{
returnReadFile(ComputerInfofile);
}
publicstaticboolExistComputerInfofile()
{
returnFile.Exists(ComputerInfofile);
}
publicstaticboolExistRegistInfofile()
{
returnFile.Exists(RegistInfofile);
}
privatestaticvoidWriteFile(stringinfo,stringfileName)
{
try
{
using(StreamWritersw=newStreamWriter(fileName,false))
{
sw.Write(info);
sw.Close();
}
}
catch(Exceptionex)
{
}
}
privatestaticstringReadFile(stringfileName)
{
stringinfo=string.Empty;
try
{
using(StreamReadersr=newStreamReader(fileName))
{
info=sr.ReadToEnd();
sr.Close();
}
}
catch(Exceptionex)
{
}
returninfo;
}
}
4.其他界面代码:
主界面代码:
[csharp]view plaincopy
publicpartialclassFormMain:Form
{
privatestringencryptComputer=string.Empty;
privateboolisRegist=false;
privateconstinttimeCount=30;
publicFormMain()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls=false;
}
privatevoidFormMain_Load(objectsender,EventArgse)
{
stringcomputer=ComputerInfo.GetComputerInfo();
encryptComputer=newEncryptionHelper().EncryptString(computer);
if(CheckRegist()==true)
{
lbRegistInfo.Text="已注册";
}
else
{
lbRegistInfo.Text="待注册,运行十分钟后自动关闭";
RegistFileHelper.WriteComputerInfoFile(encryptComputer);
TryRunForm();
}
}
///<summary>
///试运行窗口
///</summary>
privatevoidTryRunForm()
{
ThreadthreadClose=newThread(CloseForm);
threadClose.IsBackground=true;
threadClose.Start();
}
privateboolCheckRegist()
{
EncryptionHelperhelper=newEncryptionHelper();
stringmd5key=helper.GetMD5String(encryptComputer);
returnCheckRegistData(md5key);
}
privateboolCheckRegistData(stringkey)
{
if(RegistFileHelper.ExistRegistInfofile()==false)
{
isRegist=false;
returnfalse;
}
else
{
stringinfo=RegistFileHelper.ReadRegistFile();
varhelper=newEncryptionHelper(EncryptionKeyEnum.KeyB);
stringregistData=helper.DecryptString(info);
if(key==registData)
{
isRegist=true;
returntrue;
}
else
{
isRegist=false;
returnfalse;
}
}
}
privatevoidCloseForm()
{
intcount=0;
while(count<timeCount&&isRegist==false)
{
if(isRegist==true)
{
return;
}
Thread.Sleep(1*1000);
count++;
}
if(isRegist==true)
{
return;
}
else
{
this.Close();
}
}
privatevoidbtnRegist_Click(objectsender,EventArgse)
{
if(lbRegistInfo.Text=="已注册")
{
MessageBox.Show("已经注册~");
return;
}
stringfileName=string.Empty;
OpenFileDialogopenFileDialog=newOpenFileDialog();
if(openFileDialog.ShowDialog()==DialogResult.OK)
{
fileName=openFileDialog.FileName;
}
else
{
return;
}
stringlocalFileName=string.Concat(
Environment.CurrentDirectory,
Path.DirectorySeparatorChar,
RegistFileHelper.RegistInfofile);
if(fileName!=localFileName)
File.Copy(fileName,localFileName,true);
if(CheckRegist()==true)
{
lbRegistInfo.Text="已注册";
MessageBox.Show("注册成功~");
}
}
}
注册机代码:
[csharp]view plaincopy
publicpartialclassFormMain:Form
{
publicFormMain()
{
InitializeComponent();
}
privatevoidbtnRegist_Click(objectsender,EventArgse)
{
stringfileName=string.Empty;
OpenFileDialogopenFileDialog=newOpenFileDialog();
if(openFileDialog.ShowDialog()==DialogResult.OK)
{
fileName=openFileDialog.FileName;
}
else
{
return;
}
stringlocalFileName=string.Concat(
Environment.CurrentDirectory,
Path.DirectorySeparatorChar,
puterInfofile);
if(fileName!=localFileName)
File.Copy(fileName,localFileName,true);
stringcomputer=RegistFileHelper.ReadComputerInfoFile();
EncryptionHelperhelp=newEncryptionHelper(EncryptionKeyEnum.KeyB);
stringmd5String=help.GetMD5String(computer);
stringregistInfo=help.EncryptString(md5String);
RegistFileHelper.WriteRegistFile(registInfo);
MessageBox.Show("注册码已生成");
}
}
最后采用ConfuserEx将可执行文件加密(ConfuserEx介绍),这样就不能反编译获得源码。
至此全部完成,只是个人的一些实践,对自己是一个记录,同时希望也能对别人有些帮助,如果有什么错误,还望不吝指出,共同进步,转载请保留原文地址。
---------------------
作者:weixin_37691493
来源:CSDN
原文:/weixin_37691493/article/details/79716050
版权声明:本文为博主原创文章,转载请附上博文链接!