关于x86:CPU序列号

关于x86:CPU序列号

CPU serial number

如何获得PC中CPU的序列号?


没有任何外部库,我对此有最终的答案。只需键入:

WMIC BIOS获取序列号

这将为您提供PC机箱上的序列号;)
(位于微软的知识库中)

问候!


请记住,如今大多数计算机出厂时在BIOS中都禁用了CPU ID。在Wikipedia上查看CPUID


根据您用于问题的"许可"标签,读取网络MAC地址可能会获得更好的结果。通过MAC地址识别PC并非完全牢不可破的复制保护方法,但有时仍会使用。


奔腾III在Intel CPU中没有CPU序列ID(PSN; CPUID edx位18" psn"处理器序列号);而且AMD芯片中从来没有任何psn:

https://software.intel.com/zh-CN/forums/watercooler-catchall/topic/308483(于2005年)

However, keep in mind that only the Pentium III Xeon, Mobile Pentium III and Pentium III processors support the processor serial number feature introduced by the Pentium III processor. No other Intel processor supports the processor serial number feature

https://zh.wikipedia.org/wiki/奔腾III#Controversy_about_privacy_issues

https://zh.wikipedia.org/wiki/CPUID#EAX=3:_Processor_Serial_Number

EAX=3: Processor Serial Number
See also: Pentium III § Controversy about privacy issues

This returns the processor's serial number. The processor serial number was introduced on Intel Pentium III, but due to privacy concerns, this feature is no longer implemented on later models (the PSN feature bit is always cleared). Transmeta's Efficeon and Crusoe processors also provide this feature. AMD CPUs however, do not implement this feature in any CPU models.


这是和旧线程。但是我有一个同样的问题,但是我得到了以下逻辑,而没有太多的if,ands或buts。

CPU序列号的问题在于它并非始终在虚拟环境中工作。

我对一组基于Windows的服务器执行了以下逻辑:

Win32_BIOS可以为您提供BIOS的序列号。我们需要记住,如果系统是虚拟化的,那么对于所有服务器,最终可能会使用相同的BIOS序列号。

Win32_NetworkAdapter可以为您提供可以使用的MAC。如果您有多个NIC,最终将得到多个MAC。

结合这两个ID,我在跨越物理和虚拟的6000台服务器中拥有了所有唯一的集合。使用ManagementClassManagementObject实施起来非常简单。

但这只是一个警告:当您尝试远程获取MO实例时,在延迟为<5ms的10Gbps光网络中,将花费超过几秒钟的时间。因此,如果您做数学运算,则我在单线程操作上花了3个多小时。因为这更像是低优先级的流量,所以我不想对网络进行垃圾邮件处理以收集多线程调用中的WMI数据。


即使启用了CPUID,现代处理器中实际上是否还有可用的序列号?我记得在奔腾3天,整个序列号问题都引起了强烈抗议。


Ivy Bridge CPU和更新的CPU均包含PPIN(受保护的处理器标识号)。计算机固件可能阻止对此功能的访问。

https://lore.kernel.org/patchwork/patch/736614/


__get_cpuid (unsigned int __level, unsigned int *__eax, unsigned int *__ebx, unsigned int *__ecx, unsigned int *__edx);

  • 标头:#include

注意:处理器序列号是在Intel Pentium III上引入的,但是由于隐私方面的考虑,此功能不再在以后的型号中实现。

资料来源:维基百科


使用CPUZ工具:http://www.cpuid.com/cpuz.php


使用正确的寄存器设置执行CPUID指令将检索EAX,EBX,ECX和EDX中的处理器序列号。但是,此功能仅在Pentium 3和更高版本的处理器上可用。同样在Pentium 4和更高版本的处理器上,指令在所有4个寄存器中始终返回0x00000000。更高版本的奔腾3可能还会返回0x00000000。该功能主要针对复制保护,允许将软件链接到特定处理器。它不能很好地与社区相处,随之而来的是诉讼。该功能已从较新的P3型号和所有较新的处理器中删除。由于兼容性原因,该功能在较新的处理器中具有。有传言称,您可以订购带有序列号的特殊处理器,但最低购买量约为100万个处理器。有关在执行CPUID指令之前的特定寄存器设置,请查看可通过其网站获得的Intel系统程序员PDF。

另外-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#include <Windows.h>
#include <stdio.h>
#include <xmmintrin.h>
#include <iphlpapi.h>
#include <Rpc.h>

static void GetMACaddress(void);
static void uuidGetMACaddress(void);

int main(){
    SYSTEM_INFO SysInfo;
    GetSystemInfo(&SysInfo);
    printf("Processors - %d\
" , SysInfo.dwNumberOfProcessors);
    DWORD a , b , c , d , e;
    DWORD BasicLeaves;
    char* VendorID = (char*)malloc(20);
    char* message = (char*)malloc(20);
    _asm {
        pusha
        pushfd
        pop eax
        push eax
        xor eax , 0x00200000
        push eax
        popfd
        pushfd
        pop ecx
        pop eax
        xor eax , ecx
        mov [a] , eax
        }
    if(a & 0x00200000){
        printf("CPUID opcode supported.\
");
        } else {
        printf("CPUID opcode not supported, exiting...\
");
        return 0;
        }

    //DWORD* pa = &a[0];
    //DWORD* pb = &a[1];
    //DWORD* pc = &a[2];
    //DWORD* pd = &a[3];
    //a[4] = 0;
    e = 0;
    __asm {
        mov eax , 0
        cpuid
        mov [BasicLeaves] , eax;
        mov [b] , ebx;
        mov [c] , ecx;
        mov [d] , edx;
        }
    memcpy(&VendorID[0] , &b , 4);
    memcpy(&VendorID[4] , &d , 4);
    memcpy(&VendorID[8] , &c , 4);
    VendorID[12] = 0;

    printf("%d Basic Leaves\
VendorID - %s\
" , BasicLeaves , VendorID);

    __asm {
        mov eax , 1
        cpuid
        mov [a] , eax;
        mov [b] , ebx;
        mov [c] , ecx;
        mov [d] , edx;
        }
    if(d & 0x00000001) printf("FPU\
");
    if(d & 0x00000200) printf("APIC On-Chip\
");
    if(d & 0x00040000) printf("Processor Serial Number Present\
");
    if(d & 0x00800000) printf("MMX\
");
    if(d & 0x01000000) printf("SSE\
");
    if(d & 0x02000000) printf("SSE2\
");
    if(d & 0x08000000) printf("Hyperthreading (HTT)\
");

    if(c & 0x00000001) printf("SSE3\
");
    if(c & 0x00000200) printf("SSSE3\
");
    if(c & 0x00080000) printf("SSE4.1\
");
    if(c & 0x00100000) printf("SSE4.2\
");
    if(c & 0x02000000) printf("AES\
");


    __asm {
        mov eax , 0x80000000
        cpuid
        and eax , 0x7fffffff;
        mov [a] , eax;
        mov [b] , ebx;
        mov [c] , ecx;
        mov [d] , edx;
        }

    printf("%d Extended Leaves\
" , a);

    printf("Processor Brand String -");
    __asm {
        mov eax , 0x80000002
        cpuid
        mov [a] , eax;
        mov [b] , ebx;
        mov [c] , ecx;
        mov [d] , edx;
        }
    memcpy(&message[0] , &a , 4);
    memcpy(&message[4] , &b , 4);
    memcpy(&message[8] , &c , 4);
    memcpy(&message[12] , &d , 4);
    message[16] = 0;
    printf("%s" , message);

    __asm {
        mov eax , 0x80000003
        cpuid
        mov [a] , eax;
        mov [b] , ebx;
        mov [c] , ecx;
        mov [d] , edx;
        }

    memcpy(&message[0] , &a , 4);
    memcpy(&message[4] , &b , 4);
    memcpy(&message[8] , &c , 4);
    memcpy(&message[12] , &d , 4);
    message[16] = 0;
    printf("%s" , message);

    __asm {
        mov eax , 0x80000004
        cpuid
        mov [a] , eax;
        mov [b] , ebx;
        mov [c] , ecx;
        mov [d] , edx;
        popa
        }
    memcpy(&message[0] , &a , 4);
    memcpy(&message[4] , &b , 4);
    memcpy(&message[8] , &c , 4);
    memcpy(&message[12] , &d , 4);
    message[16] = 0;
    printf("%s\
" , message);

    char VolumeName[256]; DWORD VolumeSerialNumber; DWORD MaxComponentLength; DWORD FileSystemFlags; char FileSystemNameBuffer[256];
    GetVolumeInformationA("c:\\\" , VolumeName , 256 , &VolumeSerialNumber , &MaxComponentLength , &FileSystemFlags , (LPSTR)&FileSystemNameBuffer , 256);
    printf("Serialnumber - %X\
" , VolumeSerialNumber);

    GetMACaddress();
    uuidGetMACaddress();

    return 0;
    }

// Fetches the MAC address and prints it
static void GetMACaddress(void){
    IP_ADAPTER_INFO AdapterInfo[16];        // Allocate information
                                            // for up to 16 NICs
    DWORD dwBufLen = sizeof(AdapterInfo);   // Save memory size of buffer

    DWORD dwStatus = GetAdaptersInfo(       // Call GetAdapterInfo
    AdapterInfo,                            // [out] buffer to receive data
    &dwBufLen);                             // [in] size of receive data buffer
    //assert(dwStatus == ERROR_SUCCESS);    // Verify return value is
                                            // valid, no buffer overflow

    PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo; // Contains pointer to
                                            // current adapter info
    do {
        printf("Adapter MAC Address - %X-%X-%X-%X-%X-%X\
" , pAdapterInfo->Address[0] , pAdapterInfo->Address[1] , pAdapterInfo->Address[2] , pAdapterInfo->Address[3] , pAdapterInfo->Address[4] , pAdapterInfo->Address[5]);
        printf("Adapter IP Address  - %s\
" , pAdapterInfo->CurrentIpAddress);
        printf("Adapter Type        - %d\
" , pAdapterInfo->Type);
        printf("Adapter Name        - %s\
" , pAdapterInfo->AdapterName);
        printf("Adapter Description - %s\
" , pAdapterInfo->Description);
        uuidGetMACaddress();

        printf("\
");
        //PrintMACaddress(pAdapterInfo->Address); // Print MAC address
        pAdapterInfo = pAdapterInfo->Next;      // Progress through
                                                // linked list
        } while(pAdapterInfo);                  // Terminate if last adapter
    }

// Fetches the MAC address and prints it

static void uuidGetMACaddress(void)
{
  unsigned char MACData[6];

  UUID uuid;
  UuidCreateSequential( &uuid );    // Ask OS to create UUID

  for (int i=2; i<8; i++)  // Bytes 2 through 7 inclusive
                           // are MAC address
    MACData[i - 2] = uuid.Data4[i];

  printf("UUID MAC Address - %X-%X-%X-%X-%X-%X\
" , MACData[0] , MACData[1] , MACData[2] , MACData[3] , MACData[4] , MACData[5]);
}//*/

在Windows中,我确定有一个系统调用,在Linux中,可以尝试" sudo lshw",但是大多数内核似乎不支持CPU序列号,并且初步研究似乎表明,对唯一可识别计算机的普遍愤怒意味着不是完美的答案。

你想做什么?几乎可以肯定,有人以前曾经做过,重用或模仿他们所做的事情可能是明智的。


请提供更多详细信息:操作系统,语言。

例如,在Windows上,您可以使用WMI并阅读Win32_Processor.ProcessorId来获取它。


我猜相当多的编译器确实提供了一些包装器或类似的东西
命令。这是一个例子

1
2
3
4
5
6
7
8
9
10
11
#include <stdlib.h>
#include <string.h>
#include <intrinsics.h>

_CPUID cpuinfo;
int main(void) {
_cpuid(&cpuinfo);
printf("Vendor: %s\
", cpuinfo.Vendor);
return 0;
}

输出:

1
Vendor: GenuineIntel

您可以使用CPUID命令。


推荐阅读