C/C++:Windows获取电脑机器指纹

介绍很多时候我们需要为一台Windows设备生成一个机器指纹来标识一台设备。当然标识设备最好的是与硬件相关的标识,应该硬件一般不会被改变。笔者参考了获取设备唯一标识这篇博客。笔者将使用下面几个字段进行机器指...

介绍

很多时候我们需要为一台Windows设备生成一个机器指纹来标识一台设备。当然标识设备最好的是与硬件相关的标识,应该硬件一般不会被改变。笔者参考了获取设备唯一标识这篇博客。笔者将使用下面几个字段进行机器指纹的生成。

  1. 主板UUID
    wmic csproduct get UUID
    唯一值,缺陷并不是所有的厂商都提供UUID(可以使用)
  2. CPUID
    wmic cpu get processorid
    同一批次的PC,CPUID可能一样(可以使用)
  3. BIOS序列号
    wmic bios get serialnumber
    刷了BIOS系统可能导致BIOS序列号变动(刷BIOS概率很小,可以使用)
  4. 硬盘序列号
    wmic diskdrive get serialnumber
    多块硬盘,更换硬盘(概率较小,可以使用)
  5. 网卡MAC地址
    网卡更换,MAC地址易被更改 作为硬件不可靠(不建议使用)

代码

这里我们采用的策略是:主板UUID存在,就使用主板UUID生成机器指纹。主板UUID不存在,使用CPUID、BIOS序列号、硬盘序列号生成机器指纹。这里的散列算法用的标准库中自带。

#include <Windows.h>
#include <string>
#include <list>
#include <iostream>
#include <functional>

using namespace std;
#define BUFFER_SIZE 128

bool getDevcieInfo(char* cmd,list<string> &resultList) {
    char buffer[BUFFER_SIZE];
	bool ret = false;
    FILE* pipe = _popen(cmd, "r"); //打开管道,并执行命令 
    if (!pipe)
          return ret;                     
    
	char *name[20] = {"UUID","ProcessorId","SerialNumber"};
	int len0 = strlen(name[0]),len1 = strlen(name[1]),len2 = strlen(name[2]);
	bool isOk = false;
    while(!feof(pipe)) 
	{
		if(fgets(buffer, BUFFER_SIZE, pipe))
		{
			if( strncmp(name[0],buffer,len0) == 0 
				|| strncmp(name[1],buffer,len1) == 0 
				|| strncmp(name[2],buffer,len2) == 0 ) // 能够正确获取信息
			{
				isOk = true;
				continue;
			}
            if( isOk ==  false 
				|| strcmp("\r\n",buffer) == 0 ) //去掉windows无用的空行
			{
				continue;
			}
			ret = true;
			resultList.push_back(string(buffer));
        }
    }
    _pclose(pipe); // 关闭管道 
    return ret; 
}


string getDeviceFingerPrint(){
    list<string> strList;
	list<string>::iterator it;
	hash<string> str_hash;
	size_t num ;
	char tmp[11] = {0};
	
	// 主板UUID存在,就使用主板UUID生成机器指纹
    if( getDevcieInfo("wmic csproduct get UUID",strList)
		&& (*strList.begin()).compare("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF\r\n") != 0)
	{
		//cout << *strList.begin();
		//cout << str_hash(*strList.begin()) << endl;
		num = str_hash(*strList.begin());
		sprintf(tmp,"%u",num);
		//cout << string(tmp) << endl;
		return string(tmp);
    }
    
    // 主板UUID不存在,使用CPUID、BIOS序列号、硬盘序列号生成机器指纹
	string otherStr("");
	strList.clear();
	if( getDevcieInfo("wmic cpu get processorid",strList) ){
		otherStr.append( *strList.begin() );
    }
	strList.clear();
	if( getDevcieInfo("wmic bios get serialnumber",strList) ){
		otherStr.append( *strList.begin() );
    }
	strList.clear();
	if( getDevcieInfo("wmic diskdrive get serialnumber",strList) ){
		string allDiskNum("");
		// 硬盘可能有多块
		for(it = strList.begin();it != strList.end();it++)
		{
			allDiskNum.append(*it);
		}
		//cout << allDiskNum ;
		//cout << str_hash(allDiskNum) << endl;
		otherStr.append( *strList.begin() );
    }
	cout << str_hash(otherStr) << endl;
	//memset(tmp,0,11);
	num = str_hash(otherStr);
	sprintf(tmp,"%u",num);
	//cout << string(tmp) << endl;
	return string(tmp);
}

void test()
{
	string deviceFingerPrint = getDeviceFingerPrint();
	cout << deviceFingerPrint << endl;
}

int main(int args,char* argv[])
{
	test();
	system("pause");            
	return 0;
}

本文标题为:C/C++:Windows获取电脑机器指纹

基础教程推荐