現在做軟件試用限制,那么就討論下軟件的試用限制。總體來說,限制的方法有這么幾種:
1.時間限制。
2.次數限制。
以時間限制為例,主要是用戶從安裝之日起, 限制用戶使用天數。n天之后,就無法使用。這種限制主要是安裝的時候,將當前日期寫入注冊表(或者硬盤上某文件)。當然,寫入的是加密過的亂碼字符。運行軟件時,首先讀取注冊表(或者文件),如找不到注冊表(或者文件),則提示軟件未注冊。當正常讀取后進行解密,得到注冊日期,與當前日期進行比較,如果 當前日期 減去 注冊日期 > n(允許試用天數),那么提示軟件試用到期,直接退出軟件。否則 提示可試用天數, 繼續試用軟件。 根據以上思路,那么用戶可以很容易破解軟件。比如更改系統日期、或者刪除注冊表,重新安裝軟件等 。
針對用戶的破解,對軟件限制進行修改。如果試用軟件必須聯網,或者需要服務器端(比如聊天軟件等客戶端軟件),當前時間要從去服務器的時間,防止用戶更改客戶機系統時間。或者服務器上對客戶機進行記錄,如記錄主板id,安裝時間,等等。。。
以上為客戶機可聯網的做法,當客戶機無法上網,切不存在服務器,或者服務器就在本機時。以上做法將無法使用。
那么對於單機運行的軟件,如果需要數據庫,我們可以將注冊時間等信息寫入數據庫。或者,我們可以采用一明一暗的做法,注冊表是明,在硬盤的某角落,存放隱藏文件。軟件需讀取兩處,對兩處進行比較,一致則通過,不一致就退出程序。當然,安裝的時候對該文件不替換。 我想用戶是不願意為了使用你的軟件而格式化整個硬盤的。
其實還有做法,就是每次運行軟件,先將當前日期與注冊表對比,看是否過期。如未過期,就對注冊表進行一次更改,更改為當前日期,那么用戶即使更改系統日期,他的試用期限也在逐漸縮小。為了防止用戶重裝,還是采用一明一暗的做法。
基本上就這些方法吧.. 貼上測試代碼:
加密解密類:
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Xml.Linq;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace Add_To_Regedit
{
public class Encryption
{
public static string EncryPW(string Pass, string Key)
{
return DesEncrypt(Pass, Key);
}
public static string DisEncryPW(string strPass, string Key)
{
return DesDecrypt(strPass, Key);
}
/////////////////////////////////////////////////////////////////////
/// <summary>
/// DES加密
/// </summary>
/// <param name="encryptString"></param>
/// <returns></returns>
public static string DesEncrypt(string encryptString, string key)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 8));
byte[] keyIV = keyBytes;
byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, provider.CreateEncryptor(keyBytes, keyIV), CryptoStreamMode.Write);
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Convert.ToBase64String(mStream.ToArray());
}
/// <summary>
/// DES解密
/// </summary>
/// <param name="decryptString"></param>
/// <returns></returns>
public static string DesDecrypt(string decryptString, string key)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key.Substring(0, 8));
byte[] keyIV = keyBytes;
byte[] inputByteArray = Convert.FromBase64String(decryptString);
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, provider.CreateDecryptor(keyBytes, keyIV), CryptoStreamMode.Write);
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Encoding.UTF8.GetString(mStream.ToArray());
}
//////////////////////////////////////////////////////
}
}
讀寫注冊表類:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Security.Cryptography;
using Microsoft.Win32;
namespace Test_Form_Time
{
class TimeClass
{
public static int InitRegedit()
{
/*檢查注冊表*/
string SericalNumber = ReadSetting("", "SerialNumber", "-1"); // 讀取注冊表, 檢查是否注冊 -1為未注冊
if (SericalNumber == "-1")
{
return 1;
}
/* 比較CPUid */
string CpuId = GetSoftEndDateAllCpuId(1, SericalNumber); //從注冊表讀取CPUid
string CpuIdThis = GetCpuId(); //獲取本機CPUId
if (CpuId != CpuIdThis)
{
return 2;
}
/* 比較時間 */
string NowDate = TimeClass.GetNowDate();
string EndDate = TimeClass.GetSoftEndDateAllCpuId(0, SericalNumber);
if (Convert.ToInt32(EndDate) - Convert.ToInt32(NowDate) < 0)
{
return 3;
}
return 0;
}
/*CPUid*/
public static string GetCpuId()
{
ManagementClass mc = new ManagementClass("Win32_Processor");
ManagementObjectCollection moc = mc.GetInstances();
string strCpuID = null;
foreach (ManagementObject mo in moc)
{
strCpuID = mo.Properties["ProcessorId"].Value.ToString();
break;
}
return strCpuID;
}
/*當前時間*/
public static string GetNowDate()
{
string NowDate = DateTime.Now.ToString("yyyyMMdd"); //.Year + DateTime.Now.Month + DateTime.Now.Day).ToString();
// DateTime date = Convert.ToDateTime(NowDate, "yyyy/MM/dd");
return NowDate;
}
/* 生成序列號 */
public static string CreatSerialNumber()
{
string SerialNumber = GetCpuId() + "-" + "20110915";
return SerialNumber;
}
/*
* i=1 得到 CUP 的id
* i=0 得到上次或者 開始時間
*/
public static string GetSoftEndDateAllCpuId(int i, string SerialNumber)
{
if (i == 1)
{
string cupId = SerialNumber.Substring(0, SerialNumber.LastIndexOf("-")); // .LastIndexOf("-"));
return cupId;
}
if (i == 0)
{
string dateTime = SerialNumber.Substring(SerialNumber.LastIndexOf("-") + 1);
// dateTime = dateTime.Insert(4, "/").Insert(7, "/");
// DateTime date = Convert.ToDateTime(dateTime);
return dateTime;
}
else
{
return string.Empty;
}
}
/*寫入注冊表*/
public static void WriteSetting(string Section, string Key, string Setting) // name = key value=setting Section= path
{
string text1 = Section;
RegistryKey key1 = Registry.CurrentUser.CreateSubKey("Software\\MyTest_ChildPlat\\ChildPlat"); // .LocalMachine.CreateSubKey("Software\\mytest");
if (key1 == null)
{
return;
}
try
{
key1.SetValue(Key, Setting);
}
catch (Exception exception1)
{
return;
}
finally
{
key1.Close();
}
}
/*讀取注冊表*/
public static string ReadSetting(string Section, string Key, string Default)
{
if (Default == null)
{
Default = "-1";
}
string text2 = Section;
RegistryKey key1 = Registry.CurrentUser.OpenSubKey("Software\\MyTest_ChildPlat\\ChildPlat");
if (key1 != null)
{
object obj1 = key1.GetValue(Key, Default);
key1.Close();
if (obj1 != null)
{
if (!(obj1 is string))
{
return "-1";
}
string obj2 = obj1.ToString();
obj2 = Encryption.DisEncryPW(obj2, "ejiang11");
return obj2;
}
return "-1";
}
return Default;
}
}
}
調用方式如下:
int res = TimeClass.InitRegedit();
if (res == 0)
{
Application.Run(new Form1());
}
else if(res == 1)
{
MessageBox.Show("軟件尚未注冊,請注冊軟件!");
}
else if (res == 2)
{
MessageBox.Show("注冊機器與本機不一致,請聯系管理員!");
}
else if (res == 3)
{
MessageBox.Show("軟件試用已到期!");
}
else
{
MessageBox.Show("軟件運行出錯,請重新啟動!");
}
