Question

How do I obtain the serial number of the CPU in a PC?

Was it helpful?

Solution

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.

OTHER TIPS

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

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.

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.

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.

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

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top