为了保护软件成果,通常会设置在使用软件时需要进行认证、鉴权、有效期的识别:
(1)对于在线系统通常的做法是设计与部署一个认证服务,软件链接登陆服务获得认证信息(License)实现,当然也可以一旦通过验证,将License本地存储使用。
(2)离线系统一般是通过绑定软件安装的机器或者发放序列号的方式控制。如果是绑定软件安装的机器需要在license申请前采集机器指纹(含CPU、硬盘、MAC地址等一种或者几种信息的加密数据)。机器指纹的加密算法一般是采用不可逆的加密算法,如MD5等。
另外更复杂的License创建策略会将控制的功能项编码、受限使用的控制信息、使用期限等信息加密放到license中,在软件运行过程中实时检测。大多商业系统或软件会采用license发放的时候用公钥加密,软件运行时通过私钥解密等方式实现。而很多为项目或某特定行业服务的工具软件大多使用机器指纹进行私钥加密/解密实现。
下面讲述根据磁盘或网卡创建软件License的方法,其采用对称式加密,即加密和解密使用同一个密钥,加密算法是自定义的,绝大多数个人工具、项目工具的开发都可以采用,对软件工具起到一定的保护作用。
(1)获取网卡或磁盘信息
bool CLicense::Create()
{
source_flag = false;
#ifdef _WIN32
if (m_nMacType == 0) // 取网卡地址
{
DWORD m_dwNetCardCount = 0;
PIP_ADAPTER_INFO m_pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
DWORD dwRetVal = GetAdaptersInfo(m_pAdapterInfo, &ulOutBufLen);
if (dwRetVal == ERROR_BUFFER_OVERFLOW)
{
free(m_pAdapterInfo);
m_pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
dwRetVal = GetAdaptersInfo(m_pAdapterInfo, &ulOutBufLen);
}
if (dwRetVal == NO_ERROR)
{
PIP_ADAPTER_INFO pAdapter = m_pAdapterInfo;
while (pAdapter)
{
TRACE("\tAdapter Name: \t%s\n", pAdapter->AdapterName);
TRACE("\tAdapter Desc: \t%s\n", pAdapter->Description);
TRACE("\tAdapter Addr: \t%ld\n", pAdapter->Address);
TRACE("\tIP Address: \t%s\n", pAdapter->IpAddressList.IpAddress.String);
TRACE("\tIP Mask: \t%s\n", pAdapter->IpAddressList.IpMask.String);
TRACE("\tGateway: \t%s\n", pAdapter->GatewayList.IpAddress.String);
TRACE("\t***\n");
if (pAdapter->DhcpEnabled)
{
TRACE("\tDHCP Enabled: Yes\n");
TRACE("\t\tDHCP Server: \t%s\n", pAdapter->DhcpServer.IpAddress.String);
TRACE("\tLease Obtained: %ld\n", pAdapter->LeaseObtained);
}
else
TRACE("\tDHCP Enabled: No\n");
if (pAdapter->HaveWins)
{
TRACE("\tHave Wins: Yes\n");
TRACE("\t\tPrimary Wins Server: \t%s\n", pAdapter->PrimaryWinsServer.IpAddress.String);
TRACE("\t\tSecondary Wins Server: \t%s\n", pAdapter->SecondaryWinsServer.IpAddress.String);
}
else
TRACE("\tHave Wins: No\n");
pAdapter = pAdapter->Next;
m_dwNetCardCount++;
}
}
else
{
free(m_pAdapterInfo);
m_pAdapterInfo = NULL;
}
PIP_ADAPTER_INFO pAdapter = m_pAdapterInfo;
while (pAdapter)
{
sprintf(szMacAddress, "%02X-%02X-%02X-%02X-%02X-%02X",
pAdapter->Address[0], pAdapter->Address[1], pAdapter->Address[2],
pAdapter->Address[3], pAdapter->Address[4], pAdapter->Address[5]);
addr[0] = pAdapter->Address[0];
addr[1] = pAdapter->Address[1];
addr[2] = pAdapter->Address[2];
addr[3] = pAdapter->Address[3];
addr[4] = pAdapter->Address[4];
addr[5] = pAdapter->Address[5];
pAdapter = pAdapter->Next;
source_flag = true;
break;
}
}
else // 取磁盘码
{
for (int i=0; i<5; i++)
{
memset(szMacAddress,0x00,sizeof(szMacAddress));
if ((byMacAddrLen=GetHDSN(szMacAddress,i))>0)
{
source_flag = true;
break;
}
}
}
#else
/* implementation for Linux */
int fd;
if (m_nMacType == 0) // 取网卡序列号
{
fd = socket(AF_INET, SOCK_DGRAM, 0);
printf("socket fd is %d!\n",fd);
if (fd == -1) {
return source_flag;
}
char buf[1024];
struct ifconf ifc;
int ok = 0;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
ioctl(fd, SIOCGIFCONF, &ifc);
struct ifreq *IFR = ifc.ifc_req;
struct ifreq ifr;
for (int i = ifc.ifc_len/sizeof(struct ifreq); --i >= 0; IFR++)
{
strcpy(ifr.ifr_name, IFR->ifr_name);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
{
if (!(ifr.ifr_flags & IFF_LOOPBACK) && (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0))
{
ok = 1;
break;
}
}
}
close(fd);
if (ok)
{
bcopy(ifr.ifr_hwaddr.sa_data, addr, 6);
source_flag = true;
}else{
printf("ifr.ifr_hwaddr.sa_data is NULL!\n");
}
}
else // 取磁盘码 added 2017.01.20
{
struct hd_driveid hd;
int ok = 0;
memset(szMacAddress,0x00,sizeof(szMacAddress));
bool openf = true;
if ((fd = open("/dev/hdc", O_RDONLY|O_NONBLOCK)) < 0
&& (fd = open("/dev/hdb", O_RDONLY|O_NONBLOCK)) < 0
&& (fd = open("/dev/sda", O_RDONLY|O_NONBLOCK)) < 0
&& (fd = open("/dev/sdb", O_RDONLY|O_NONBLOCK)) < 0)
{
printf("open /dev/hdc fail!\n");
return source_flag;
}
if (!ioctl(fd, HDIO_GET_IDENTITY, &hd)) {
//printf("Hard Disk Model: %.40s\n", hd.model);
//printf(" Serial Number: %.20s\n", hd.serial_no);
ok = 1;
}
if (ok)
{
sprintf(szMacAddress,"%.20s",hd.serial_no);
byMacAddrLen = strlen(szMacAddress);
source_flag = true;
}else{
printf("szMacAddress is NULL!\n");
}
}
#endif
return source_flag;
}
// **********************************************************************************************************
// 取硬盘序列码
// **********************************************************************************************************
int CLicense::GetHDSN(char * szSN, int n)
{
//int done = -1;
int ret = 0;
#ifdef _WIN32
{
char szHDName[512];
sprintf_s(szHDName, "\\\\.\\PhysicalDrive%d", n);
HANDLE hPhysicalDriveIOCTL = 0;
hPhysicalDriveIOCTL = CreateFile (szHDName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
{
TRACE("\tCreateFile Ret : INVALID_HANDLE_VALUE\n");
printf("CreateFile Return(INVALID_HANDLE_VALUE) and error(%d)\n", GetLastError());
}
else
{
GETVERSIONINPARAMS GetVersionParams;
DWORD cbBytesReturned = 0;
memset ((void*) & GetVersionParams, 0, sizeof(GetVersionParams));
if ( ! DeviceIoControl (hPhysicalDriveIOCTL, SMART_GET_VERSION,
NULL,
0,
&GetVersionParams, sizeof (GETVERSIONINPARAMS),
&cbBytesReturned, NULL) )
{
;
}
else
{
ULONG CommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE;
PSENDCMDINPARAMS Command = (PSENDCMDINPARAMS) malloc (CommandSize);
//#define ID_CMD 0xEC // Returns ID sector for ATA
Command -> irDriveRegs.bCommandReg = 0xEC; //ID_CMD;
DWORD BytesReturned = 0;
if ( ! DeviceIoControl (hPhysicalDriveIOCTL,
SMART_RCV_DRIVE_DATA, Command, sizeof(SENDCMDINPARAMS),
Command, CommandSize,
&BytesReturned, NULL) )
{
;
}
else
{
DWORD diskdata [256];
USHORT *pIdSector = (USHORT *)
/*(PIDENTIFY_DATA)*/ ((PSENDCMDOUTPARAMS) Command) -> bBuffer;
//printf("diskdata:\n");
for (int ijk = 0; ijk < 256; ijk++) {
diskdata[ijk] = pIdSector[ijk];
//printf("%ld ", diskdata[ijk]);
}
//printf("\n");
if(szSN)
{
int index = 0;
int position = 0;
for (index = 10; index <= 19; index++)
{
szSN [position++] = (char) (diskdata [index] / 256);
szSN [position++] = (char) (diskdata [index] % 256);
}
szSN[position] = '\0';
for (index = position - 1; index > 0 && isspace(szSN [index]); index--)
szSN [index] = '\0';
}
//done = TRUE;
}
CloseHandle (hPhysicalDriveIOCTL);
free (Command);
Command = NULL;
}
}
}
ret = static_cast(strlen(szSN));
#else
;
#endif
return ret;
}
(2)根据网卡或磁盘信息进行加密,加密算法可以自行根据需要调整,最好是不可逆的加密算法
bool CLicense::encrypt()
{
if (!source_flag)
return false;
if (m_nMacType == 0) // 网卡地址加密
{
sprintf(szMacAddress, "%0X-%0X-%0X-%0X-%0X-%0X\n"
, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
for (unsigned char b = 0; b < 6; b++) {
addr[b] ^= 2 * (b + 1) + 0x88;
}
unsigned long dwCRC = GetLicense(&addr[0], 2) + (GetLicense(&addr[2], 4) << 16);
sprintf(m_szLicense, "%u", dwCRC);
for (unsigned int i = 0; i < strlen(m_szLicense); i++)
{
if (m_szLicense[i] <= '5')
m_szLicense[i] = m_szLicense[i] - '0' + 'A';
else
m_szLicense[i] = m_szLicense[i] - '6' + '0';
}
}
else // 硬盘序列码加密
{
char buf[128] = { '\0' };
for (int i = 0; i < byMacAddrLen && i < sizeof(m_szLicense); i++)
{
m_szLicense[i] = (u_char)GetLicense((u_char *)&szMacAddress[i], byMacAddrLen - i);
if (m_szLicense[i] <= '5')
m_szLicense[i] = m_szLicense[i] - '0' + 'A';
else
m_szLicense[i] = m_szLicense[i] - '6' + '0';
char tmp[3] = { '\0' };
sprintf(tmp, "%02X", (u_char)m_szLicense[i]);
strncat(buf, tmp, strlen(tmp));
}
strncpy(m_szLicense, buf, (strlen(buf) >= MAX_LICENSE_SIZE) ? (MAX_LICENSE_SIZE - 1) : strlen(buf));
}
//printf("mac address %s ==> %s\n", szMacAddress, m_szLicense);
return true;
};
(3)编程实现License工具,调用函数生成机器指纹(网卡信息或磁盘信息),根据机器指纹生成License
#include "License.h"
//软件License测试
int main(int argc, char *argv[])
{
printf("Run ...\n");
int license_mode=0;
int encrypt_mode = 0;
if (argc > 1)
{
sscanf(argv[1],"%d",&license_mode);
}
if (argc > 2)
{
sscanf(argv[2], "%d", &encrypt_mode);
}
printf("License mode is %s\n",(license_mode==0)?"NetCard":"Disk");
CLicense sn;
sn.SetMacAddrType(license_mode);
switch (encrypt_mode)
{
case 0: //获取硬件信息
{
//获取
if(!sn.Create())
printf("CLicense Create fail!\n");
//打印输出
std::string strSn = sn.ToStringS();
printf("strSn:%s\n", strSn.c_str());
//向文件写入硬件信息
sn.SerializeSource("sc.txt", true);
}
break;
case 11: //根据硬件信息生成License
{
//从文件读取硬件信息
sn.SerializeSource("sc.txt", false);
//生成算法
sn.encrypt();
//打印输出
std::string strSn = sn.ToString();
printf("strSn:%s\n", strSn.c_str());
//向文件写入License
sn.Serialize("sn.txt", true);
}
break;
default:
printf("encrypt_mode is NULL\n");
break;
}
return 0;
}
(4)在软件工具上进行验证,先读取License工具生成的License文件,与软件工具创建的License做校对
bool LicenseCheck()
{
bool license_check = false;
#ifdef DEBUG //不做校对
license_check = false;
#else
license_check = true;
#endif
bool bRet = !license_check;
if (!bRet)
{
CLicense sn1;
if (sn1.Serialize("sn.txt", false))
{
CLogger::createInstance()->Log(eTipMessage
, "license:%s", sn1.ToString().c_str());
CLicense sn; // used netcard serial first
if (sn.Create()&&sn.encrypt())
bRet = (sn1 == sn);
if (!bRet)
{
sn.SetMacAddrType(1); // used HD serial second
if (sn.Create()&&sn.encrypt())
bRet = (sn1 == sn);
}
}
}
return bRet;
};
int main(int argc, char* argv[])
{
if (!LicenseCheck()) {
printf("license is error, please make sure software instance is right first!");
exit(true);
}
//your code
}
总的来说,软件License创建就是根据机器指纹(磁盘、网卡、CPU等一种或多种信息),这些机器指纹信息具有惟一性和确定性,很好作为软件使用约束的依据,通过机器指纹生成License实现软件工具与机器绑定。如果是商用软件,最好采用不可逆的非对称式加密算法实现,即“公钥”和“私钥”配对使用。
附件给出本实例中软件License工具的全部代码,关于License的头文件及源码有些复杂,是因我还有兼顾其他用途,大家可以自行简化,希望能帮助到有需要的小伙伴。
CMakeLists.txt
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (SoftWareLicense)
#
if(WIN32)
message(STATUS "windows compiling...")
add_definitions(-D_PLATFORM_IS_WINDOWS_)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
else(WIN32)
message(STATUS "linux compiling...")
add_definitions( -D_PLATFORM_IS_LINUX_)
endif(WIN32)
#
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 指定源文件的目录,并将名称保存到变量
SET(source_h
${PROJECT_SOURCE_DIR}/common/License.h
${PROJECT_SOURCE_DIR}/common/ostype.h
)
SET(source_cpp
${PROJECT_SOURCE_DIR}/common/License.cpp
${PROJECT_SOURCE_DIR}/src/main.cpp
)
#头文件目录
include_directories(${PROJECT_SOURCE_DIR}/common)
# 指定生成目标
add_executable(SWL ${source_h} ${source_cpp})
src/main.cpp
#include "License.h"
int main(int argc, char *argv[])
{
printf("Run ...\n");
int license_mode=0;
int encrypt_mode = 0;
if (argc > 1)
{
sscanf(argv[1],"%d",&license_mode);
}
if (argc > 2)
{
sscanf(argv[2], "%d", &encrypt_mode);
}
printf("License mode is %s\n",(license_mode==0)?"NetCard":"Disk");
CLicense sn;
sn.SetMacAddrType(license_mode);
switch (encrypt_mode)
{
case 0: //获取硬件信息
{
//获取
if(!sn.Create())
printf("CLicense Create fail!\n");
//打印输出
std::string strSn = sn.ToStringS();
printf("strSn:%s\n", strSn.c_str());
//向文件写入硬件信息
sn.SerializeSource("sc.txt", true);
}
break;
case 11: //根据硬件信息生成License
{
//从文件读取硬件信息
sn.SerializeSource("sc.txt", false);
//生成算法
sn.encrypt();
//打印输出
std::string strSn = sn.ToString();
printf("strSn:%s\n", strSn.c_str());
//向文件写入License
sn.Serialize("sn.txt", true);
}
break;
default:
printf("encrypt_mode is NULL\n");
break;
}
return 0;
}
common/License.h
#ifndef __SNFACTORY_H__
#define __SNFACTORY_H__
// ANSC C/C++
#include
#include
#include
#include
#include
#include
#define MAX_LICENSE_SIZE 32
class CLicense
{
public:
CLicense();
CLicense(const CLicense& other);
bool operator !=(const CLicense& other);
bool operator ==(const CLicense& other);
bool Create();
bool encrypt();
bool SerializeSource(const char* strFile, bool bStoring);
std::string ToStringS() const;
bool Serialize(const char* strFile, bool bStoring);
std::string ToString() const;
// added 2010.11.15
void SetMacAddrType(int mMacType){m_nMacType = mMacType;} // 设置取物理地址类型
private:
bool string_divide(std::vector &_strlist, const std::string src, const std::string div);
protected:
bool source_flag;
char szMacAddress[128];
unsigned char addr[6];
unsigned char byMacAddrLen;
//
char m_szLicense[MAX_LICENSE_SIZE];
int GetHDSN(char * szSN, int n);
int m_nMacType;
};
#endif /*__SNFACTORY_H__*/
common/License.cpp
#include "License.h"
#include "ostype.h"
#ifdef _WIN32
// === 增加硬盘序列码 ===
#include
#include
#define SMART_GET_VERSION CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
// ==================================
#include
#pragma comment(lib, "Iphlpapi.lib")
#else
// linux
#include
#include
#include
#include
#include
#include
#include // socket
#include
#include // time
#include
#include
#include
//#include
#include //Drive specific defs
#include
#include
#include
#endif
//******************************************************************************************************
static unsigned short GetLicense(unsigned char* byData,unsigned short wLen)
{
static const unsigned short crctable[256] =
{
0x0000,0x365e,0x6cbc,0x5ae2,0xd978,0xef26,0xb5c4,0x839a,0xff89,0xc9d7,0x9335,0xa56b,0x26f1,0x10af,0x4a4d,0x7c13,
0xb26b,0x8435,0xded7,0xe889,0x6b13,0x5d4d,0x07af,0x31f1,0x4de2,0x7bbc,0x215e,0x1700,0x949a,0xa2c4,0xf826,0xce78,
0x29af,0x1ff1,0x4513,0x734d,0xf0d7,0xc689,0x9c6b,0xaa35,0xd626,0xe078,0xba9a,0x8cc4,0x0f5e,0x3900,0x63e2,0x55bc,
0x9bc4,0xad9a,0xf778,0xc126,0x42bc,0x74e2,0x2e00,0x185e,0x644d,0x5213,0x08f1,0x3eaf,0xbd35,0x8b6b,0xd189,0xe7d7,
0x535e,0x6500,0x3fe2,0x09bc,0x8a26,0xbc78,0xe69a,0xd0c4,0xacd7,0x9a89,0xc06b,0xf635,0x75af,0x43f1,0x1913,0x2f4d,
0xe135,0xd76b,0x8d89,0xbbd7,0x384d,0x0e13,0x54f1,0x62af,0x1ebc,0x28e2,0x7200,0x445e,0xc7c4,0xf19a,0xab78,0x9d26,
0x7af1,0x4caf,0x164d,0x2013,0xa389,0x95d7,0xcf35,0xf96b,0x8578,0xb326,0xe9c4,0xdf9a,0x5c00,0x6a5e,0x30bc,0x06e2,
0xc89a,0xfec4,0xa426,0x9278,0x11e2,0x27bc,0x7d5e,0x4b00,0x3713,0x014d,0x5baf,0x6df1,0xee6b,0xd835,0x82d7,0xb489,
0xa6bc,0x90e2,0xca00,0xfc5e,0x7fc4,0x499a,0x1378,0x2526,0x5935,0x6f6b,0x3589,0x03d7,0x804d,0xb613,0xecf1,0xdaaf,
0x14d7,0x2289,0x786b,0x4e35,0xcdaf,0xfbf1,0xa113,0x974d,0xeb5e,0xdd00,0x87e2,0xb1bc,0x3226,0x0478,0x5e9a,0x68C4,
0x8f13,0xb94d,0xe3af,0xd5f1,0x566b,0x6035,0x3ad7,0x0c89,0x709a,0x46c4,0x1c26,0x2a78,0xa9e2,0x9fbc,0xc55e,0xf300,
0x3d78,0x0b26,0x51c4,0x679a,0xe400,0xd25e,0x88bc,0xbee2,0xc2f1,0xf4af,0xae4d,0x9813,0x1b89,0x2dd7,0x7735,0x416b,
0xf5e2,0xc3bc,0x995e,0xaf00,0x2c9a,0x1ac4,0x4026,0x7678,0x0a6b,0x3c35,0x66d7,0x5089,0xd313,0xe54d,0xbfaf,0x89f1,
0x4789,0x71d7,0x2b35,0x1d6b,0x9ef1,0xa8af,0xf24d,0xc413,0xb800,0x8e5e,0xd4bc,0xe2e2,0x6178,0x5726,0x0dc4,0x3b9a,
0xdc4d,0xea13,0xb0f1,0x86af,0x0535,0x336b,0x6989,0x5fd7,0x23c4,0x159a,0x4f78,0x7926,0xfabc,0xcce2,0x9600,0xa05e,
0x6e26,0x5878,0x029a,0x34c4,0xb75e,0x8100,0xdbe2,0xedbc,0x91af,0xa7f1,0xfd13,0xcb4d,0x48d7,0x7e89,0x246b,0x1235
};
unsigned short X = 0;
for (unsigned short i = 0; i < wLen; i++)
X = (X / 256) ^ (crctable[(X % 256) ^ byData[i]]) ;
return (X ^ 0xffff);
}
//**********************************************************************************************************
CLicense::CLicense()
{
source_flag = false;
memset(szMacAddress, '\0', 128);
memset(addr, '\0', 6);
byMacAddrLen = 0;
memset(m_szLicense, '\0', MAX_LICENSE_SIZE);
m_nMacType = 0; // 缺省为取网卡地址
}
//**********************************************************************************************************
CLicense::CLicense(const CLicense& other)
{
}
//**********************************************************************************************************
bool CLicense::operator !=(const CLicense& other)
{
bool b = strcmp(m_szLicense, other.m_szLicense) != 0;
return b;
}
//**********************************************************************************************************
bool CLicense::operator ==(const CLicense& other)
{
//printf("%s==%s\n", m_szLicense, other.m_szLicense);
bool b = strcmp(m_szLicense, other.m_szLicense) == 0;
return b;
}
//**********************************************************************************************************
bool CLicense::Create()
{
source_flag = false;
#ifdef _WIN32
if (m_nMacType == 0) // 取网卡地址
{
DWORD m_dwNetCardCount = 0;
PIP_ADAPTER_INFO m_pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
DWORD dwRetVal = GetAdaptersInfo(m_pAdapterInfo, &ulOutBufLen);
if (dwRetVal == ERROR_BUFFER_OVERFLOW)
{
free(m_pAdapterInfo);
m_pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
dwRetVal = GetAdaptersInfo(m_pAdapterInfo, &ulOutBufLen);
}
if (dwRetVal == NO_ERROR)
{
PIP_ADAPTER_INFO pAdapter = m_pAdapterInfo;
while (pAdapter)
{
TRACE("\tAdapter Name: \t%s\n", pAdapter->AdapterName);
TRACE("\tAdapter Desc: \t%s\n", pAdapter->Description);
TRACE("\tAdapter Addr: \t%ld\n", pAdapter->Address);
TRACE("\tIP Address: \t%s\n", pAdapter->IpAddressList.IpAddress.String);
TRACE("\tIP Mask: \t%s\n", pAdapter->IpAddressList.IpMask.String);
TRACE("\tGateway: \t%s\n", pAdapter->GatewayList.IpAddress.String);
TRACE("\t***\n");
if (pAdapter->DhcpEnabled)
{
TRACE("\tDHCP Enabled: Yes\n");
TRACE("\t\tDHCP Server: \t%s\n", pAdapter->DhcpServer.IpAddress.String);
TRACE("\tLease Obtained: %ld\n", pAdapter->LeaseObtained);
}
else
TRACE("\tDHCP Enabled: No\n");
if (pAdapter->HaveWins)
{
TRACE("\tHave Wins: Yes\n");
TRACE("\t\tPrimary Wins Server: \t%s\n", pAdapter->PrimaryWinsServer.IpAddress.String);
TRACE("\t\tSecondary Wins Server: \t%s\n", pAdapter->SecondaryWinsServer.IpAddress.String);
}
else
TRACE("\tHave Wins: No\n");
pAdapter = pAdapter->Next;
m_dwNetCardCount++;
}
}
else
{
free(m_pAdapterInfo);
m_pAdapterInfo = NULL;
}
PIP_ADAPTER_INFO pAdapter = m_pAdapterInfo;
while (pAdapter)
{
sprintf(szMacAddress, "%02X-%02X-%02X-%02X-%02X-%02X",
pAdapter->Address[0], pAdapter->Address[1], pAdapter->Address[2],
pAdapter->Address[3], pAdapter->Address[4], pAdapter->Address[5]);
addr[0] = pAdapter->Address[0];
addr[1] = pAdapter->Address[1];
addr[2] = pAdapter->Address[2];
addr[3] = pAdapter->Address[3];
addr[4] = pAdapter->Address[4];
addr[5] = pAdapter->Address[5];
pAdapter = pAdapter->Next;
source_flag = true;
break;
}
}
else // 取磁盘码
{
for (int i=0; i<5; i++)
{
memset(szMacAddress,0x00,sizeof(szMacAddress));
if ((byMacAddrLen=GetHDSN(szMacAddress,i))>0)
{
source_flag = true;
break;
}
}
}
#else
/* implementation for Linux */
int fd;
if (m_nMacType == 0) // 取网卡序列号
{
fd = socket(AF_INET, SOCK_DGRAM, 0);
printf("socket fd is %d!\n",fd);
if (fd == -1) {
return source_flag;
}
char buf[1024];
struct ifconf ifc;
int ok = 0;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
ioctl(fd, SIOCGIFCONF, &ifc);
struct ifreq *IFR = ifc.ifc_req;
struct ifreq ifr;
for (int i = ifc.ifc_len/sizeof(struct ifreq); --i >= 0; IFR++)
{
strcpy(ifr.ifr_name, IFR->ifr_name);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
{
if (!(ifr.ifr_flags & IFF_LOOPBACK) && (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0))
{
ok = 1;
break;
}
}
}
close(fd);
if (ok)
{
bcopy(ifr.ifr_hwaddr.sa_data, addr, 6);
source_flag = true;
}else{
printf("ifr.ifr_hwaddr.sa_data is NULL!\n");
}
}
else // 取磁盘码
{
struct hd_driveid hd;
int ok = 0;
memset(szMacAddress,0x00,sizeof(szMacAddress));
bool openf = true;
if ((fd = open("/dev/hdc", O_RDONLY|O_NONBLOCK)) < 0
&& (fd = open("/dev/hdb", O_RDONLY|O_NONBLOCK)) < 0
&& (fd = open("/dev/sda", O_RDONLY|O_NONBLOCK)) < 0
&& (fd = open("/dev/sdb", O_RDONLY|O_NONBLOCK)) < 0)
{
printf("open /dev/hdc fail!\n");
return source_flag;
}
if (!ioctl(fd, HDIO_GET_IDENTITY, &hd)) {
//printf("Hard Disk Model: %.40s\n", hd.model);
//printf(" Serial Number: %.20s\n", hd.serial_no);
ok = 1;
}
if (ok)
{
sprintf(szMacAddress,"%.20s",hd.serial_no);
byMacAddrLen = strlen(szMacAddress);
source_flag = true;
}else{
printf("szMacAddress is NULL!\n");
}
}
#endif
return source_flag;
}
bool CLicense::encrypt()
{
if (!source_flag)
return false;
if (m_nMacType == 0) // 网卡地址加密
{
sprintf(szMacAddress, "%0X-%0X-%0X-%0X-%0X-%0X\n"
, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
for (unsigned char b = 0; b < 6; b++) {
addr[b] ^= 2 * (b + 1) + 0x88;
}
unsigned long dwCRC = GetLicense(&addr[0], 2) + (GetLicense(&addr[2], 4) << 16);
sprintf(m_szLicense, "%u", dwCRC);
for (unsigned int i = 0; i < strlen(m_szLicense); i++)
{
if (m_szLicense[i] <= '5')
m_szLicense[i] = m_szLicense[i] - '0' + 'A';
else
m_szLicense[i] = m_szLicense[i] - '6' + '0';
}
}
else // 硬盘序列码加密
{
char buf[128] = { '\0' };
for (int i = 0; i < byMacAddrLen && i < sizeof(m_szLicense); i++)
{
m_szLicense[i] = (u_char)GetLicense((u_char *)&szMacAddress[i], byMacAddrLen - i);
if (m_szLicense[i] <= '5')
m_szLicense[i] = m_szLicense[i] - '0' + 'A';
else
m_szLicense[i] = m_szLicense[i] - '6' + '0';
char tmp[3] = { '\0' };
sprintf(tmp, "%02X", (u_char)m_szLicense[i]);
strncat(buf, tmp, strlen(tmp));
}
strncpy(m_szLicense, buf, (strlen(buf) >= MAX_LICENSE_SIZE) ? (MAX_LICENSE_SIZE - 1) : strlen(buf));
}
//printf("mac address %s ==> %s\n", szMacAddress, m_szLicense);
return true;
};
bool CLicense::string_divide(std::vector &_strlist, const std::string src, const std::string div)
{
std::string _src = src;
std::string::size_type _pos = _src.find(div);
while (std::string::npos != _pos)
{
std::string _buf = "";
_buf = _src.substr(0, _pos);
_strlist.push_back(_buf);
_src = _src.erase(0, _pos + div.size());
_pos = _src.find(div.c_str());
}
if (!_src.empty()) {
_strlist.push_back(_src);
}
return true;
};
bool CLicense::SerializeSource(const char* strFile, bool bStoring)
{
if (bStoring)
{
// Save
if (strlen(szMacAddress) > 0)
{
std::ofstream fLincese(strFile);
fLincese.write(szMacAddress, strlen(szMacAddress));
return true;
}
}
else
{
// Read
std::ifstream fLincese(strFile);
fLincese.read(szMacAddress, MAX_LICENSE_SIZE);
byMacAddrLen = static_cast(strlen(szMacAddress));
bool read_flag = byMacAddrLen > 0 ? true : false;
bool map_flag = false;
if (0 == m_nMacType) {
std::vector _strlist;
if (string_divide(_strlist,std::string(szMacAddress),"-"))
{
try
{
if (6 == _strlist.size()) {
for (int index = 0; index < 6; index++)
{
int n = 0;
for (int i = 0; i < 2; i++)
{
if (_strlist.at(index)[i] >= 'A'&&_strlist.at(index)[i] <= 'F')//十六进制还要判断他是不是在A-F或者a-f之间a=10。。
n = _strlist.at(index)[i] - 'A' + 10;
else if (_strlist.at(index)[i] >= 'a'&&_strlist.at(index)[i] <= 'f')
n = _strlist.at(index)[i] - 'a' + 10;
else
n = _strlist.at(index)[i] - '0';
addr[index] = addr[index] * 16 + n;
}
}
map_flag = true;
}
else {
#ifdef WIN32
throw std::exception("MacAddress be split by \'-\' and size isn't 6");
#else
throw std::logic_error("MacAddress be split by \'-\' and size isn't 6");
#endif
}
}
catch (const std::exception& e)
{
printf("error(%s) for SerializeSource\r\n",e.what());
}
}
}
else {
map_flag = true;
}
source_flag = read_flag&&map_flag;
return read_flag;
}
return false;
};
std::string CLicense::ToStringS() const
{
std::string strName = szMacAddress;
return strName;
};
//**********************************************************************************************************
bool CLicense::Serialize(const char* strFile, bool bStoring)
{
if (bStoring)
{
// Save
if (strlen(m_szLicense) > 0)
{
std::ofstream fLincese(strFile);
fLincese.write(m_szLicense, strlen(m_szLicense));
return true;
}
}
else
{
// Read
std::ifstream fLincese(strFile);
fLincese.read(m_szLicense, MAX_LICENSE_SIZE);
return strlen(m_szLicense) > 0;
}
return false;
}
//**********************************************************************************************************
std::string CLicense::ToString() const
{
std::string strName = m_szLicense;
return strName;
}
// **********************************************************************************************************
// 取硬盘序列码
// **********************************************************************************************************
int CLicense::GetHDSN(char * szSN, int n)
{
//int done = -1;
int ret = 0;
#ifdef _WIN32
{
char szHDName[512];
sprintf_s(szHDName, "\\\\.\\PhysicalDrive%d", n);
HANDLE hPhysicalDriveIOCTL = 0;
hPhysicalDriveIOCTL = CreateFile (szHDName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
{
TRACE("\tCreateFile Ret : INVALID_HANDLE_VALUE\n");
printf("CreateFile Return(INVALID_HANDLE_VALUE) and error(%d)\n", GetLastError());
}
else
{
GETVERSIONINPARAMS GetVersionParams;
DWORD cbBytesReturned = 0;
memset ((void*) & GetVersionParams, 0, sizeof(GetVersionParams));
if ( ! DeviceIoControl (hPhysicalDriveIOCTL, SMART_GET_VERSION,
NULL,
0,
&GetVersionParams, sizeof (GETVERSIONINPARAMS),
&cbBytesReturned, NULL) )
{
;
}
else
{
ULONG CommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE;
PSENDCMDINPARAMS Command = (PSENDCMDINPARAMS) malloc (CommandSize);
//#define ID_CMD 0xEC // Returns ID sector for ATA
Command -> irDriveRegs.bCommandReg = 0xEC; //ID_CMD;
DWORD BytesReturned = 0;
if ( ! DeviceIoControl (hPhysicalDriveIOCTL,
SMART_RCV_DRIVE_DATA, Command, sizeof(SENDCMDINPARAMS),
Command, CommandSize,
&BytesReturned, NULL) )
{
;
}
else
{
DWORD diskdata [256];
USHORT *pIdSector = (USHORT *)
/*(PIDENTIFY_DATA)*/ ((PSENDCMDOUTPARAMS) Command) -> bBuffer;
//printf("diskdata:\n");
for (int ijk = 0; ijk < 256; ijk++) {
diskdata[ijk] = pIdSector[ijk];
//printf("%ld ", diskdata[ijk]);
}
//printf("\n");
if(szSN)
{
int index = 0;
int position = 0;
for (index = 10; index <= 19; index++)
{
szSN [position++] = (char) (diskdata [index] / 256);
szSN [position++] = (char) (diskdata [index] % 256);
}
szSN[position] = '\0';
for (index = position - 1; index > 0 && isspace(szSN [index]); index--)
szSN [index] = '\0';
}
//done = TRUE;
}
CloseHandle (hPhysicalDriveIOCTL);
free (Command);
Command = NULL;
}
}
}
ret = static_cast(strlen(szSN));
#else
;
#endif
return ret;
}
common/ostype.h
#ifndef __OSTYPE_HH__
#define __OSTYPE_HH__
#ifdef _WIN32
#include
#define __WINDOWS__
#else
#define __LINUX__
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include
#include
#include
#include
#include
#include
#include
#include