加密授权——获取计算机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;
}
	
发布了34 篇原创文章 · 获赞 21 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/lizhengze1117/article/details/102631058