最近在做一个软件,有一个绑定特定硬件,限制使用时间以及使用次数的需求。由于是离线的软件,所有不管怎么做,在理论上都可以被破解,比如AUTOCAD和MATLAB等软件。所以要做的就是要增加破解者的工作难度。
软件防破解,先防"君子"再防"小人"。
防“君子”的做法就是限制使用时间和使用次数,如果和特定的硬件绑定,也可以把硬件识别码作为保护手段。如果用户不对程序进行破解,那这基本上就满足要求了。
如果有“小人”进行软件破解,那也有办法。一是采用复杂的加解密机制,二是给程序加壳,三是在程序多处进行验证,四是客户端定时联网验证。方法四最稳妥,但是有时条件不允许。方法三会使破解者工作量大大增加,但会降低代码可读性,代码维护困难。方法二是离线客户端防破解最好的方案,但操作起来有点困难。方法一比较容易实现,一般同方法三结合使用。
本文只讨论防君子的方法,绑定特定的硬件。
CPU序号获取
GCC编译器
需要包含头文件
#include <cpuid.h>
QString getCpuId()
{
QString cpu_id = "";
unsigned int dwBuf[4];
unsigned long long ret;
__cpuid(1, dwBuf[0], dwBuf[1], dwBuf[2], dwBuf[3]);
ret = dwBuf[3];
ret = ret << 32;
cpu_id = QString::number(dwBuf[3], 16).toUpper();
cpu_id = cpu_id + QString::number(dwBuf[0], 16).toUpper();
return cpu_id;
}
MSVC编译器,64位
QString getCpuId()
{
QString cpu_id = "";
unsigned int dwBuf[4];
unsigned long long ret;
__cpuidex((int*)(void*)dwBuf,1,0);
ret = dwBuf[3];
ret = ret << 32;
cpu_id = QString::number(dwBuf[3], 16).toUpper();
cpu_id = cpu_id + QString::number(dwBuf[0], 16).toUpper();
return cpu_id;
}
网卡地址获取(GCC和MSVC编译器通用)
QString getMacAddress()
{
QList<QNetworkInterface> nets = QNetworkInterface::allInterfaces();// 获取所有网络接口列表
int nCnt = nets.count();
QString strMacAddr = "";
for(int i = 0; i < nCnt; i ++)
{
// 如果此网络接口被激活并且正在运行并且不是回环地址,则就是我们需要找的Mac地址
if(nets[i].flags().testFlag(QNetworkInterface::IsUp) && nets[i].flags().testFlag(QNetworkInterface::IsRunning) && !nets[i].flags().testFlag(QNetworkInterface::IsLoopBack))
{
strMacAddr = nets[i].hardwareAddress();
break;
}
}
strMacAddr.replace(":", "");
return strMacAddr;
}