How do I obtain the serial number of the CPU in a PC?
Based upon 'licensing' tag you have used for your question, you might get better results reading network MAC address. Identifying PC by a MAC address isn't totally unbreakable method for copy protection, still it is sometimes used.
I have the ultimate answer for this without any external libraries. Simply type this:
wmic bios get serialnumber
This will give you the Serial Number on the PCs chassis ;) (found in microsoft's knowledge base)
Regards!
Remember that most computers these days ship with CPU ID disabled in the BIOS. See CPUID on Wikipedia
There is no CPU serial ID (PSN; CPUID edx bit 18 "psn" Processor Serial Number) after Pentium III in Intel CPUs; and there was never any psn in AMD chips:
https://software.intel.com/en-us/forums/watercooler-catchall/topic/308483 (at 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://en.wikipedia.org/wiki/Pentium_III#Controversy_about_privacy_issues
https://en.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.
Even with CPUID enabled is there actually a serial number available in modern processors? I remember there being a big outcry in the Pentium 3 days when this whole serial number issue was raised.
This is and old thread. But I had a same problem, but I got the following logic working without too many ifs, ands or buts.
The problem with CPU serial number is that it does not always work in virtualized environment.
I did the following logic with a set of Windows-based servers:
Win32_BIOS
can provide you a serial number of the bios. We need to keep in mind that if the system is virtualized, you could end up with same bios serial number for all servers.
Win32_NetworkAdapter
can provide you a MAC that you can use as well. In cases where you have multiple NICs, you will end up with multiple-MACs.
Combining both these IDs, I had all unique set over a set of 6000 servers spanning across physical and virtual. This was really simple to implement using ManagementClass
& ManagementObject
.
But just a caveat: when you try to get the MO
instance remotely, it'll take more than a few seconds on a <5ms latency 10Gbps optical network. So if you do the math it took me over 3 hours on a single thread operation. Since this is more like a low-priority traffic I didn't want to spam my network for gathering WMI
data on multi-threaded call.
Use the CPUZ tool: http://www.cpuid.com/cpuz.php
__get_cpuid (unsigned int __level, unsigned int *__eax, unsigned int *__ebx, unsigned int *__ecx, unsigned int *__edx);
- Header:
#include <cpuid.h>
Note: The processor serial number was introduced on Intel Pentium III, but due to privacy concerns, this feature is no longer implemented on later models.
Source : wikipedia
Ivy Bridge CPUs and newer all include a PPIN (Protected Processor Identification Number). Access to this feature can be blocked by the computer's firmware.
Some more details please: operating system, language.
For example on Windows you can get it by using WMI and reading Win32_Processor.ProcessorId.
In windows, I am sure there is a system call, In linux one could try "sudo lshw" but most kernels do not seem to support CPU serial numbers, and preliminary research seems to indicate that the general outrage against uniquely identifiable computers means that there is no perfect answer.
What are you trying to do? Almost certainly someone has done it before and it may be wise to reuse or emulate what they have done.
Executing the CPUID instruction with the proper register settings will retrieve the processor serial number in EAX, EBX, ECX, and EDX. However, this functionality is only available on Pentium 3 and later processors. Also on Pentium 4 and newer processors the instruction always returns 0x00000000 in all 4 registers. Later model Pentium 3's may also return 0x00000000's. The feature was primarily aimed at copy protection, allowing software to be linked to specific processors. It did not go over well with the community, and lawsuits ensued. The feature was removed from late model P3's and all newer processors. The feature is present in newer processors for compatibility reasons. it is rumored than you can special order processors with serial numbers, btu the minimum purchase is something like 1 million processors. For the specific register settings prior to executing the CPUID instruction, check Intels system programmer PDF available through their website.
Also -
#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\n" , 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.\n");
} else {
printf("CPUID opcode not supported, exiting...\n");
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\nVendorID - %s\n" , BasicLeaves , VendorID);
__asm {
mov eax , 1
cpuid
mov [a] , eax;
mov [b] , ebx;
mov [c] , ecx;
mov [d] , edx;
}
if(d & 0x00000001) printf("FPU\n");
if(d & 0x00000200) printf("APIC On-Chip\n");
if(d & 0x00040000) printf("Processor Serial Number Present\n");
if(d & 0x00800000) printf("MMX\n");
if(d & 0x01000000) printf("SSE\n");
if(d & 0x02000000) printf("SSE2\n");
if(d & 0x08000000) printf("Hyperthreading (HTT)\n");
if(c & 0x00000001) printf("SSE3\n");
if(c & 0x00000200) printf("SSSE3\n");
if(c & 0x00080000) printf("SSE4.1\n");
if(c & 0x00100000) printf("SSE4.2\n");
if(c & 0x02000000) printf("AES\n");
__asm {
mov eax , 0x80000000
cpuid
and eax , 0x7fffffff;
mov [a] , eax;
mov [b] , ebx;
mov [c] , ecx;
mov [d] , edx;
}
printf("%d Extended Leaves\n" , 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\n" , 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\n" , 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\n" , pAdapterInfo->Address[0] , pAdapterInfo->Address[1] , pAdapterInfo->Address[2] , pAdapterInfo->Address[3] , pAdapterInfo->Address[4] , pAdapterInfo->Address[5]);
printf("Adapter IP Address - %s\n" , pAdapterInfo->CurrentIpAddress);
printf("Adapter Type - %d\n" , pAdapterInfo->Type);
printf("Adapter Name - %s\n" , pAdapterInfo->AdapterName);
printf("Adapter Description - %s\n" , pAdapterInfo->Description);
uuidGetMACaddress();
printf("\n");
//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\n" , MACData[0] , MACData[1] , MACData[2] , MACData[3] , MACData[4] , MACData[5]);
}//*/
You can use CPUID command.
I guess quite a few compiler do offer some wrapper or the like around the mentioned command. Here's an example
#include <stdlib.h>
#include <string.h>
#include <intrinsics.h>
_CPUID cpuinfo;
int main(void) {
_cpuid(&cpuinfo);
printf("Vendor: %s\n", cpuinfo.Vendor);
return 0;
}
Output:
Vendor: GenuineIntel
来源:https://stackoverflow.com/questions/90462/cpu-serial-number