加密授權——獲取計算機CPUID序列號(32位 64位 均可以)

最近項目要用到加密授權,考慮了一下打算採用CPUID加密,上網找了資料整合如下,代碼適合windows環境下32位和64位的 均可。

首先說下 cmd 下查看 CPUID 命令:

wmic cpu get ProcessorId

在32位模式下,我們可以使用內嵌彙編來調用cpuid指令。但在64位模式下,VC編譯器不支持內嵌彙編。
  於是微軟提供了Intrinsics函數——編譯器會將Intrinsics函數編譯爲對應的機器指令,而且同時支持32位和64位。
  例如CPUID指令的對應Intrinsics函數是——

void __cpuid(
   int CPUInfo[4],
   int InfoType
);

void __cpuidex(
   int CPUInfo[4],
   int InfoType,
   int ECXValue
);

__cpuidex函數的InfoType參數是CPUID指令的eax參數,即功能ID。ECXValue參數是CPUID指令的ecx參數,即子功能ID。CPUInfo參數用於接收輸出的eax, ebx, ecx, edx這四個寄存器。
  早期的CPUID功能只需要一個功能ID參數(eax),這時可以使用__cpuid函數。
  後來CPUID的功能越來越強大,一個功能ID參數(eax)參數不夠用,於是加了一個子功能ID(ecx)參數,這時應該採用__cpuidex。

在__cpuid、__cpuidex等Intrinsics函數時,會遇到以下問題——
1.低版本的VC編譯器沒有intrin.h頭文件。【注】:只有VC2005(或更高)才擁有intrin.h,支持__cpuid。
2.低版本的VC編譯器不支持__cpuidex。【注】:只有VC2008的部分版本及VS2010(或更高)的intrin.h中才有__cpuidex

上代碼: vs x86 x64 下均可運行

#include "pch.h"
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <intrin.h>	// 所有Intrinsics函數

using namespace std;
char szBuf[64];

// 取得CPU廠商(Vendor)
//
// result: 成功時返回字符串的長度(一般爲12)。失敗時返回0。
// pvendor: 接收廠商信息的字符串緩衝區。至少爲13字節。
int cpu_getvendor(char* pvendor)
{
	INT32 dwBuf[4];
	if (NULL == pvendor)	return 0;
	// Function 0: Vendor-ID and Largest Standard Function
	__cpuid(dwBuf, 0);
	// save. 保存到pvendor
	*(INT32*)&pvendor[0] = dwBuf[1];	// ebx: 前四個字符
	*(INT32*)&pvendor[4] = dwBuf[3];	// edx: 中間四個字符
	*(INT32*)&pvendor[8] = dwBuf[2];	// ecx: 最後四個字符
	pvendor[12] = '\0';
	return 12;
}

// 取得CPU商標(Brand)
//
// result: 成功時返回字符串的長度(一般爲48)。失敗時返回0。
// pbrand: 接收商標信息的字符串緩衝區。至少爲49字節。
int cpu_getbrand(char* pbrand)
{
	INT32 dwBuf[4];
	if (NULL == pbrand)	return 0;
	// Function 0x80000000: Largest Extended Function Number
	__cpuid(dwBuf, 0x80000000);
	if (dwBuf[0] < 0x80000004)	return 0;
	// Function 80000002h,80000003h,80000004h: Processor Brand String
	__cpuid((INT32*)&pbrand[0], 0x80000002);	// 前16個字符
	__cpuid((INT32*)&pbrand[16], 0x80000003);	// 中間16個字符
	__cpuid((INT32*)&pbrand[32], 0x80000004);	// 最後16個字符
	pbrand[48] = '\0';
	return 48;
}

string GetCPUID() {
	INT32 dwBuf[4];
	std::string strCPUId;
	char buf[32] = { 0 };
	__cpuidex(dwBuf, 1, 1);
	//printf("%08X%08X\n", dwBuf[3], dwBuf[0]);
	memset(buf, 0, 32);
	sprintf_s(buf, 32, "%08X", dwBuf[3]);
	strCPUId += buf;
	memset(buf, 0, 32);
	sprintf_s(buf, 32, "%08X", dwBuf[0]);
	strCPUId += buf;
	return strCPUId;
}

int main(int argc, _TCHAR* argv[])
{
	cpu_getvendor(szBuf);
	printf("CPU Vendor:\t%s\n", szBuf);

	cpu_getbrand(szBuf);
	printf("CPU Name:\t%s\n", szBuf);
	
	cout << "CPU ID:		" << GetCPUID() <<endl;
	return 0;
}

X86下不適用Intrinsics函數 獲得CPUID

#include "pch.h"
#include <iostream>
#include <string>
#include <windows.h>

using namespace std;

string GetCPUIDwin32()
{
	std::string strCPUId;
	unsigned long s1, s2;
	char buf[32] = { 0 };
	__asm {
		mov eax, 01h   //eax=1:取CPU序列號
		xor edx, edx
		cpuid
		mov s1, edx
		mov s2, eax
	}
	if (s1) {
		memset(buf, 0, 32);
		sprintf_s(buf, 32, "%08X", s1);
		strCPUId += buf;
	}
	if (s2) {
		memset(buf, 0, 32);
		sprintf_s(buf, 32, "%08X", s2);
		strCPUId += buf;
	}
	__asm {
		mov eax, 03h
		xor ecx, ecx
		xor edx, edx
		cpuid
		mov s1, edx
		mov s2, ecx
	}
	if (s1) {
		memset(buf, 0, 32);
		sprintf_s(buf, 32, "%08X", s1);
		strCPUId += buf;
	}
	if (s2) {
		memset(buf, 0, 32);
		sprintf_s(buf, 32, "%08X", s2);
		strCPUId += buf;
	}
	return strCPUId;
}

int main()
{
	cout << "CPUID:" << GetCPUIDwin32() << endl;
	getchar();
	return 0;
}
	
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章