一、基本思路
根据CPU机器码和主板机器码进行软件加密是一种常见的保护软件安全的方法。下面是一种简单的实现方式:
-
获取CPU机器码和主板机器码:通过编程语言提供的API或者第三方库,可以获取到当前计算机的CPU和主板的唯一标识码。
-
组合机器码:将CPU机器码和主板机器码组合成一个唯一的标识码,可以使用字符串拼接或者哈希算法等方式。
-
生成加密密钥:根据组合后的机器码生成一个加密密钥,可以使用对称加密算法(如AES)或者非对称加密算法(如RSA)生成密钥。
-
加密软件:使用生成的密钥对软件进行加密,可以选择对整个软件进行加密,或者只对关键部分进行加密。
-
验证机器码:在软件运行时,将当前计算机的CPU和主板机器码与加密时使用的机器码进行比对,如果匹配则解密软件,否则拒绝运行。
需要注意的是,这种简单的机器码加密方式并不能完全防止软件被破解,只能增加破解难度。为了提高软件的安全性,还可以结合其他防护措施,如代码混淆、反调试等技术手段。
二、获取CPU机器码和主板机器码,
在dos命令下分别输入,wmic csproduct get uuid,wmic bios get serialnumber
PS C:\Users\aa> wmic csproduct get uuid
UUID
4C4C4544-0058-3410-8051-B2C04F375432
PS C:\Users\aa> wmic bios get serialnumber
SerialNumber
2X4Q7T2
通过c++获取uuic和serialNumber
#include <iostream>
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
std::string GetWindowsUUID() {
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) {
std::cerr << "Failed to initialize COM library. Error code = 0x" << std::hex << hres << std::endl;
return "";
}
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres)) {
std::cerr << "Failed to initialize security. Error code = 0x" << std::hex << hres << std::endl;
CoUninitialize();
return "";
}
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres)) {
std::cerr << "Failed to create IWbemLocator object. Error code = 0x" << std::hex << hres << std::endl;
CoUninitialize();
return "";
}
IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&pSvc
);
if (FAILED(hres)) {
std::cerr << "Could not connect. Error code = 0x" << std::hex << hres << std::endl;
pLoc->Release();
CoUninitialize();
return "";
}
hres = CoSetProxyBlanket(
pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hres)) {
std::cerr << "Could not set proxy blanket. Error code = 0x" << std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return "";
}
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT UUID FROM Win32_ComputerSystemProduct"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if (FAILED(hres)) {
std::cerr << "Failed to execute query. Error code = 0x" << std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return "";
}
IWbemClassObject* pclsObj;
ULONG uReturn = 0;
std::string uuid = "";
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"UUID", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr) && vtProp.vt == VT_BSTR)
{
_bstr_t bstrUUID = vtProp.bstrVal;
uuid = (char*)bstrUUID;
VariantClear(&vtProp);
break;
}
VariantClear(&vtProp);
pclsObj->Release();
}
pEnumerator->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize();
return uuid;
}
std::string GetWindowsSerialNumber() {
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) {
std::cerr << "Failed to initialize COM library. Error code = 0x" << std::hex << hres << std::endl;
return "";
}
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres)) {
std::cerr << "Failed to initialize security. Error code = 0x" << std::hex << hres << std::endl;
CoUninitialize();
return "";
}
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres)) {
std::cerr << "Failed to create IWbemLocator object. Error code = 0x" << std::hex << hres << std::endl;
CoUninitialize();
return "";
}
IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&pSvc
);
if (FAILED(hres)) {
std::cerr << "Could not connect. Error code = 0x" << std::hex << hres << std::endl;
pLoc->Release();
CoUninitialize();
return "";
}
hres = CoSetProxyBlanket(
pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hres)) {
std::cerr << "Could not set proxy blanket. Error code = 0x" << std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return "";
}
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT SerialNumber FROM Win32_BIOS"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if (FAILED(hres)) {
std::cerr << "Failed to execute query. Error code = 0x" << std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return "";
}
IWbemClassObject* pclsObj;
ULONG uReturn = 0;
std::string serialNumber = "";
while (pEnumerator) {
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn) {
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr) && vtProp.vt == VT_BSTR) {
_bstr_t bstrSerial = vtProp.bstrVal;
serialNumber = (char*)bstrSerial;
VariantClear(&vtProp);
break;
}
VariantClear(&vtProp);
pclsObj->Release();
}
pEnumerator->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize();
return serialNumber;
}
int main() {
std::string uuid = GetWindowsUUID();
if (!uuid.empty()) {
std::cout << "UUID: " << uuid << std::endl;
} else {
std::cerr << "Failed to get UUID." << std::endl;
}
std::string serialNumber = GetWindowsSerialNumber();
if (!serialNumber.empty()) {
std::cout << "Serial Number: " << serialNumber << std::endl;
} else {
std::cerr << "Failed to get Serial Number." << std::endl;
}
return 0;
}