一、简介
离线激活码是一种在软件、游戏、应用程序或其他数字产品领域中常用的授权方式,旨在确保产品的合法使用并维护开发者的权益。当用户购买或获得这些产品的使用权后,开发者会提供一个唯一的、一次性的激活码给用户。与在线激活不同,离线激活码允许用户在没有网络连接的情况下完成产品的激活过程,这对于网络环境不稳定或处于无网络环境的用户尤为便利。
效果:
二、实现效果
当前帖子会展现一个激活软件的完整流程,但也只是一个仅供参考的解决方案,我也做的也那么好,虽然如此,但也不是什么小白都能破解的,还是有一定的用处的。
SoftwareVerification
首先,需要新建一个类库,用来处理激活码和验证相关的问题,取名为:SoftwareVerification
新建一个类 ActivationManager,用来生成激活码,验证激活码,和读取硬盘ID,你也可以改为读取CPU,主板序列号等,我测试了下,读取CPU,主板序列号有点慢,所以就没用了。
因为源码中包含了密匙等信息,不能直接拿了就用,需要拿代码混淆工具对当前DLL进行混淆,可以参考我的帖子:
在需要激活的软件中,使用这个混淆加密的DLL进行接口调用,并限制部分接口的访问权限,这样才可以确保软件不那么容易被破解。
cs
using System;
using System.IO;
using System.Management;
using System.Security.Cryptography;
using System.Text;
namespace SoftwareVerification
{
public class ActivationManager
{
private static string DllPath = AppDomain.CurrentDomain.BaseDirectory;
private static string SecretKey = "johusaqj!lkjuh442~34vf?%sfdsfj";
/// <summary>
/// 是否激活成功
/// </summary>
public static bool IsActivationSuccess { get; set; }
/// <summary>
/// 生成激活码
/// </summary>
/// <param name="machineCode">机器码</param>
/// <returns></returns>
public static string GenerateActivationCode(string machineCode)
{
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(SecretKey)))
{
byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(machineCode));
return Convert.ToBase64String(hashBytes);
}
}
/// <summary>
/// 读取本地激活码
/// </summary>
/// <returns></returns>
public static void ReadActivationCode()
{
try
{
string path = $"{DllPath}activation.key";
if (!File.Exists(path))
{
ShowActivationForm();
return;
}
string content = File.ReadAllText(path);
if (string.IsNullOrEmpty(content))
{
ShowActivationForm();
return;
}
string decryptAct = AesEncryptionHelper.Decrypt(content);
string activation = GenerateActivationCode(GetDiskSerialNumber());
if (activation.Contains(decryptAct))
{
IsActivationSuccess = true;
return;
}
ShowActivationForm();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 显示激活界面
/// </summary>
private static void ShowActivationForm()
{
var activationForm = new ActivationForm();
activationForm.ShowDialog();
}
/// <summary>
/// 保存激活码
/// </summary>
/// <param name="code">激活码</param>
private static void SaveActivationCode(string code)
{
if (string.IsNullOrEmpty(code)) return;
string path = $"{DllPath}activation.key";
string act = AesEncryptionHelper.Encrypt(code);
File.WriteAllText(path, act);
}
/// <summary>
/// 验证激活码
/// </summary>
/// <param name="inputActivationCode">激活码</param>
/// <returns></returns>
internal static bool ValidateActivationCode(string inputActivationCode)
{
if (string.IsNullOrEmpty(inputActivationCode))
return false;
string activation = GenerateActivationCode(GetDiskSerialNumber());
if (activation.Contains(inputActivationCode))
{
SaveActivationCode(activation);
IsActivationSuccess = true;
return true;
}
return false;
}
/// <summary>
/// 获取硬盘序列号
/// </summary>
/// <returns></returns>
internal static string GetDiskSerialNumber()
{
try
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject disk in searcher.Get())
{
var serialNum = disk["SerialNumber"];
if (serialNum != null)
return serialNum.ToString().Trim();
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
return null;
}
}
}
新建一个类 AesEncryptionHelper,用来对字符串加密和解密用的
cs
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace SoftwareVerification
{
public class AesEncryptionHelper
{
// 固定的密钥和 IV,请勿在实际生产环境中使用
private static readonly byte[] Key = Encoding.UTF8.GetBytes("12345678901234567890123456789012"); // 32 字节的密钥
private static readonly byte[] IV = Encoding.UTF8.GetBytes("1234567890123456"); // 16 字节的 IV
/// <summary>
/// 加密
/// </summary>
/// <param name="plainText"></param>
/// <returns></returns>
public static string Encrypt(string plainText)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
return Convert.ToBase64String(msEncrypt.ToArray());
}
}
}
/// <summary>
/// 解密
/// </summary>
/// <param name="cipherText"></param>
/// <returns></returns>
public static string Decrypt(string cipherText)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
return srDecrypt.ReadToEnd();
}
}
}
}
}
添加一个类 LogShow,用来显示提示信息的
cs
using System;
using System.Windows.Forms;
public class LogShow
{
public Label Label_Log = null;
private Timer Timers = null;
private int TimeOut = 3;
private void Init()
{
Timers = new Timer();
Timers.Interval = (int)TimeSpan.FromSeconds(TimeOut).TotalMilliseconds;
Timers.Tick += Timers_Tick;
}
private void Timers_Tick(object sender, EventArgs e)
{
if (Label_Log == null) return;
Label_Log.Text = string.Empty;
Timers.Enabled = false;
}
public void Show(string message)
{
if (Label_Log == null) return;
Label_Log.Invoke(new Action(() =>
{
Label_Log.Text = message;
if (Timers.Enabled)
Timers.Enabled = false;
Timers.Enabled = true;
}));
}
public void Show(string message, params object[] objs)
{
if (Label_Log == null) return;
Label_Log.Invoke(new Action(() =>
{
string content = string.Empty;
if (objs != null && objs.Length > 0)
content = string.Format(message, objs);
else
content = message;
Label_Log.Text = content;
if (Timers.Enabled)
Timers.Enabled = false;
Timers.Enabled = true;
}));
}
public LogShow() => Init();
}
接下来添加一个 Form 界面,取名:ActivationForm
代码:
cs
using System;
using System.Threading;
using System.Windows.Forms;
namespace SoftwareVerification
{
public partial class ActivationForm : Form
{
public ActivationForm()
{
InitializeComponent();
}
//提示工具
private LogShow LogShows = new LogShow();
//机器码
private string MachineCode = string.Empty;
//激活失败次数
private int ActivationErrorCount;
private void ActivationForm_Load(object sender, EventArgs e)
{
LogShows.Label_Log = Label_Log;
//显示机器码
MachineCode = ActivationManager.GetDiskSerialNumber();
TextBox_MachineCode.Text = AesEncryptionHelper.Encrypt(MachineCode);
}
private void ActivationForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (!ActivationManager.IsActivationSuccess)
Application.Exit();
}
//激活
private void Button_Activation_Click(object sender, EventArgs e)
{
string act = TextBox_Activation.Text;
if (string.IsNullOrEmpty(act))
{
LogShows.Show("请输入激活码");
return;
}
if (ActivationErrorCount >= 3)
{
LogShows.Show("激活失败次数过多");
return;
}
bool result = ActivationManager.ValidateActivationCode(act);
if (result)
{
LogShows.Show("激活成功");
Thread.Sleep(500);
this.Close();
}
ActivationErrorCount++;
LogShows.Show("激活码失败,次数:{0}", ActivationErrorCount);
}
//复制
private void Button_Copy_Click(object sender, EventArgs e)
{
string content = TextBox_MachineCode.Text;
if (!string.IsNullOrEmpty(content))
{
Clipboard.SetText(content);
LogShows.Show("复制成功");
}
}
//粘贴
private void Button_Paste_Click(object sender, EventArgs e)
{
TextBox_Activation.Text = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
}
}
}
ActivationCodeGenerate
第二个项目是激活码生成工具,根据机器码来生成激活码,这个软件主要是掌握在软件所有人这边的,你需要给谁激活码,让它发一下机器码,你就可以生成对于的激活码了。
界面如下:
这个界面和上面的 SoftwareVerification 项目中的界面类似,首先需要添加 SoftwareVerification 类库项目的引用,代码如下:
cs
using SoftwareVerification;
using System;
using System.Windows.Forms;
namespace ActivationCodeGenerate
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//提示工具
private LogShow LogShows = new LogShow();
private void Form1_Load(object sender, EventArgs e)
{
LogShows.Label_Log = Label_Log;
}
//粘贴
private void Button_Paste_Click(object sender, EventArgs e)
{
TextBox_MachineCode.Text = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
}
//生成
private void Button_Generate_Click(object sender, EventArgs e)
{
string machineCode = TextBox_MachineCode.Text;
if (string.IsNullOrEmpty(machineCode))
{
LogShows.Show("请输入机器码");
return;
}
machineCode = AesEncryptionHelper.Decrypt(machineCode);
string activation = ActivationManager.GenerateActivationCode(machineCode);
TextBox_Activation.Text = activation;
}
//复制
private void Button_Copy_Click(object sender, EventArgs e)
{
string content = TextBox_Activation.Text;
if (!string.IsNullOrEmpty(content))
{
Clipboard.SetText(content);
LogShows.Show("复制成功");
}
}
}
}
测试
新建一个 Winform 项目 Test,用来当做需要激活码的软件,随便加了点文字,要添加 SoftwareVerification 类库项目的引用
代码如下:
cs
using SoftwareVerification;
using System;
using System.Windows.Forms;
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ActivationManager.ReadActivationCode();
}
}
}
项目整体结构如下:
项目源码:
https://download.csdn.net/download/qq_38693757/89767636
运行后效果如下:
结束
如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言
end