105

I need to write a function that generates an id that is unique for a given machine running a Windows OS.

Currently, I'm using WMI to query various hardware parameters and concatenate them together and hash them to derive the unique id. My question is, what are the suggested parameters I should use? Currently, I'm using a combination of bios\cpu\disk data to generate the unique id. And am using the first result if multiple results are there for each metric.

However, I ran into an issue where a machine that dual boots into 2 different Windows OS generates different site codes on each OS, which should ideally not happen.

For reference, these are the metrics I'm currently using:

Win32_Processor:UniqueID,ProcessorID,Name,Manufacturer,MaxClockSpeed
Win32_BIOS:Manufacturer
Win32_BIOS:SMBIOSBIOSVersion,IdentificationCode,SerialNumber,ReleaseDate,Version
Win32_DiskDrive:Model, Manufacturer, Signature, TotalHeads
Win32_BaseBoard:Model, Manufacturer, Name, SerialNumber
Win32_VideoController:DriverVersion, Name
bluish
  • 23,093
  • 23
  • 110
  • 171
HS.
  • 14,004
  • 8
  • 36
  • 46

15 Answers15

72

I had the same problem and after a little research I decided the best would be to read MachineGuid in registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography, as @Agnus suggested. It is generated during OS installation and won't change unless you make another fresh OS install. Depending on the OS version it may contain the network adapter MAC address embedded (plus some other numbers, including random), or a pseudorandom number, the later for newer OS versions (after XP SP2, I believe, but not sure). If it's a pseudorandom theoretically it can be forged - if two machines have the same initial state, including real time clock. In practice, this will be rare, but be aware if you expect it to be a base for security that can be attacked by hardcore hackers.

Of course a registry entry can also be easily changed by anyone to forge a machine GUID, but what I found is that this would disrupt normal operation of so many components of Windows that in most cases no regular user would do it (again, watch out for hardcore hackers).

bluish
  • 23,093
  • 23
  • 110
  • 171
Fabio Ceconello
  • 15,049
  • 5
  • 34
  • 49
  • 2
    Is this feasible? I mean that depending on this key alone is sufficient for a robust licensing system?? – Jey Geethan Jul 29 '09 at 07:47
  • Not at all. In my case, for instance, I use it for audit purposes only. Unfortunately there's no reliable DRM infrastructure in common PCs. A robust licensing system, as you mentioned, would need to make use of external (USB dongles) or non-standard (CPUID) sources for a unique number. – Fabio Ceconello Aug 06 '09 at 01:26
  • A major problem with HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography is that taking account of Registry virtualization (node VirtualStore) + Registry Wow64 process redirection (node wow6432node) it is hard to make sure to always get the same value depending ion the hosting process? – Patrick from NDepend team Nov 16 '10 at 13:07
  • 7
    You can use the KEY_WOW64_64KEY flag to make sure you always get the "real" version of the registry key, I think. – Colen Jun 08 '11 at 21:58
  • 13
    If you clone an drive image this will stay the same. So this is not at all tampersafe and very unsecure. – bitbonk Jul 08 '11 at 11:34
  • 2
    As with all the other DRM measures, there's a price point for breaking it. Happens that the price point for this is considerably lower than, say, a USB dongle. A protection will be effective if such price point (or the combined price of the multiple mesures used) is higher than the price you sell the software. Yes, there are hackers that will break it no matter what, just for fun. But those aren't the ones you should worry about. – Fabio Ceconello Jul 08 '11 at 15:45
  • 19
    To clarify the point, when I put DRM measures in software, my main goal is to prevent people from creating a crack that enables 'professional' pirates to sell illegal copies of the software without any limitation. I'm not that worried about an occasional hacker that clones the drive of his friend just to be able to use my software. In such cases those people usually have more time than money, and wouldn't be paying for it anyway. If the software costs $100 and your wage is more than $50/h, you just pay for it. The hassle will take more of your time than 2h. – Fabio Ceconello Jul 16 '11 at 20:22
  • 7
    In particular, in an environment where Windows is installed by cloning a master machine image, the MachineGuid will be identical for all of them. – nandhp Feb 10 '12 at 13:52
  • 8
    Not if you do that correctly and legally, using sysprep & all. For those that have pirated copies of windows and "just clone", that's another matter. But they wouldn't be stopped that easily, anyway. – Fabio Ceconello Mar 09 '12 at 17:44
  • I am pretty sure one of my customer's computers got their machine id changed recently. They had not reinstalled Windows, but they had replaced some hardware components including a new network card. Is that possible with this solution? – angularsen Jun 14 '12 at 06:07
  • 1
    @AndreasLarsen that would invalidate his license and require him to contact you to issue a new one. It happens to me, but is such a simple and rare case that it's no truble for support people to handle. You would be more worried about the opposite, two machines with the same ID. In my case, it's detected because the software has to contact regularly my server. – Fabio Ceconello Apr 30 '13 at 21:28
  • 2
    When I tried to read this key value from C# it was always returning null due to my project being built for x86. The solution to the issue is here - http://stackoverflow.com/a/26699672/507950 – dodgy_coder Jun 10 '15 at 02:17
  • 1
    @FabioCeconello is this still the best for you. – AbderrahimDz24 Nov 28 '16 at 21:02
  • 2
    @AbderrahimDz24 the product I mentioned is no longer sold; also the market has changed quite a bit; nowadays I don't rely on the standalone licenses model anymore. Instead, it's better to link the license to some cloud service account (which for most cases you'd want to have anyway, since now it's difficult to think about an "unplugged" application) and that will serve as DRM measure. Sure, the user may share his login with someone, but then all his data will be shared too. – Fabio Ceconello Nov 29 '16 at 12:59
34

With our licensing tool we consider the following components

  • MAC Address
  • CPU (Not the serial number, but the actual CPU profile like stepping and model)
  • System Drive Serial Number (Not Volume Label)
  • Memory
  • CD-ROM model & vendor
  • Video Card model & vendor
  • IDE Controller
  • SCSI Controller

However, rather than just hashing the components and creating a pass/fail system, we create a comparable fingerprint that can be used to determine how different two machine profiles are. If the difference rating is above a specified tolerance then ask the user to activate again.

We've found over the last 8 years in use with hundreds of thousands of end-user installs that this combination works well to provide a reliably unique machine id - even for virtual machines and cloned OS installs.

Paul Alexander
  • 30,715
  • 14
  • 93
  • 146
  • 1
    How do you determine which MAC address you use? A machine can have multiple NICs and these are added dynamically (connecting to a new VPN via an applet will add a virtual NIC). Some are virtual, have type Ethernet and are hard to identify as virtual. Others are Up/Down depending on network conditions (wifi) – Marek Sep 19 '12 at 11:06
  • We use all physical NICs - excluding virtual NICS, blue-tooth, etc. They're all combined to create unified hash. – Paul Alexander Sep 19 '12 at 23:13
  • Why you recommend not to use CPU serial number? – Mojtaba Rezaeian Apr 15 '16 at 09:59
  • 3
    The CPU serial number hasn't been enabled in an Intel chip for years. The system calls still exist, but it doesn't return a stable value. I can't remember what it returns - either dummy data or the same value for all machines. either way it's not a reliable hardware metric. – Paul Alexander Apr 15 '16 at 21:19
  • 1
    @PaulAlexander the tool that you referred to validates all the parameters you mentioned or few of them will work? Because systems now a days don't usually consists a CD-ROM – FaizanHussainRabbani Feb 10 '17 at 05:16
26

Parse the SMBIOS yourself and hash it to an arbitrary length. See the PDF specification for all SMBIOS structures available.

To query the SMBIOS info from Windows you could use EnumSystemFirmwareEntries, EnumSystemFirmwareTables and GetSystemFirmwareTable.

IIRC, the "unique id" from the CPUID instruction is deprecated from P3 and newer.

Jabberwocky
  • 40,411
  • 16
  • 50
  • 92
Jonas Engström
  • 4,825
  • 2
  • 35
  • 36
  • 14
    Note that these functions require at least Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008 or Windows Server 2003 with SP1. – jcoffland Mar 21 '11 at 20:43
  • 35
    A note to not do what I did, which was to call GetSystemFirmwareTable('RSMB'...); and hash the entire SMBIOSTableData buffer. It worked great until I ran into a workstation which wrote its cpu internal temperature to that table, meaning my unique id changed every few seconds. – Thomas Jan 05 '12 at 19:12
  • Is there any source code available for this solution? – Just Shadow Feb 12 '18 at 08:49
  • @Thomas so which solution did you finally choose? – Smith Oct 09 '18 at 10:10
  • @Smith My goal was a small 8 character id. Reading the spec, I made decisions about which fields might vary and excluded them. Then over many years I trimmed out more fields that are not constants from machines. Finally, I ended up storing an encrypted copy of the raw data I used as input and made a `closeEnough` function so that I would accept a non-matching id if it only varied in 2 fields. I also include details about the processor and system harddrive in my hash because early on I had collisions between identical systems. – Thomas Oct 09 '18 at 13:23
  • @Thomas what kind of system was that. It's weird that it wrote CPU temperature to that table. – Konrad Jul 26 '19 at 13:31
  • @Konrad Unfortunately, I don't know for sure. Looking at some emails from back then, I believe it was a set of Dell desktop stations we'd cobbled together as a set of processing farms. May have been a bug. I've seen many variables in there over the years. Laptop lids open/closed, Wifi connected, etc. – Thomas Jul 29 '19 at 18:41
3

What about just using the UniqueID of the processor?

bluish
  • 23,093
  • 23
  • 110
  • 171
gizmo
  • 11,597
  • 6
  • 42
  • 60
  • 14
    Isn't that a depreciated property these days? – Jake Wilson Jun 21 '10 at 03:19
  • 15
    Perhaps he means 'deprecated'... CPU manufacturers started putting unique IDs in at one stage but due to backlash over privacy matters, they stopped again. So you will find that some have a unique ID but most modern CPUs don't. – TripleAntigen Aug 29 '11 at 13:29
  • 1
    For reference, only a brief batch of Pentium IIIs ever had CPU serial numbers that could be read. While later versions had a serial number it was disabled by default. Pentium IV and later CPUs just didn't support it at all. – Paul Alexander May 05 '12 at 15:26
1

There is a library available for getting hardware specific informations: Hardware serial number extractor (CPU, RAM, HDD, BIOS)

ariwez
  • 1,208
  • 17
  • 19
  • 3
    It's a closed source commercial library. – Gab Jul 30 '14 at 12:24
  • @Gab-The source code is available. And the price of the DLL (29) is nothing compared with other libraries which are even close to $2000. So, yes, it does the job. – Z80 Apr 07 '15 at 16:39
1

In my program I first check for Terminal Server and use the WTSClientHardwareId. Else the MAC address of the local PC should be adequate.

If you really want to use the list of properties you provided leave out things like Name and DriverVersion, Clockspeed, etc. since it's possibly OS dependent. Try outputting the same info on both operating systems and leave out that which differs between.

bluish
  • 23,093
  • 23
  • 110
  • 171
AngelBlaZe
  • 184
  • 1
  • 8
1

For one of my applications, I either use the computer name if it is non-domain computer, or the domain machine account SID for domain computers. Mark Russinovich talks about it in this blog post, Machine SID:

The final case where SID duplication would be an issue is if a distributed application used machine SIDs to uniquely identify computers. No Microsoft software does so and using the machine SID in that way doesn’t work just for the fact that all DC’s have the same machine SID. Software that relies on unique computer identities either uses computer names or computer Domain SIDs (the SID of the computer accounts in the Domain).

You can access the domain machine account SID via LDAP or System.DirectoryServices.

bluish
  • 23,093
  • 23
  • 110
  • 171
cmcginty
  • 235
  • 1
  • 3
  • 8
1

You should look into using the MAC address on the network card (if it exists). Those are usually unique but can be fabricated. I've used software that generates its license file based on your network adapter MAC address, so it's considered a fairly reliable way to distinguish between computers.

Kyle Cronin
  • 72,761
  • 40
  • 144
  • 160
  • 6
    No, they aren't. A lot of manufacturer allows you to change them. This is very helpfull when working with clusters because some of the vendors gives you all the computer with the same MAC address (we ran into this issue a few years ago). – gizmo Sep 19 '08 at 05:40
  • This is valid idea in many cases, question does|t specify spoof-proodness or offline - you generaly want generate unique ID if you want to identify in a network – Hurda Mar 01 '12 at 13:20
  • It's possible to have multiple Network devices in the same machine; you're not guaranteed that they'll always be detected in the same order or that they won't be replaced at some point. It's better to use some hardware that's likely to be more permanent. – Agi Hammerthief Mar 08 '17 at 07:58
1

I hate to be the guy who says, "you're just doing it wrong" (I always hate that guy ;) but...

Does it have to be repeatably generated for the unique machine? Could you just assign the identifier or do a public/private key? Maybe if you could generate and store the value, you could access it from both OS installs on the same disk?

You've probably explored these options and they doesn't work for you, but if not, it's something to consider.

If it's not a matter of user trust, you could just use MAC addresses.

Jonathan Adelson
  • 3,105
  • 5
  • 27
  • 37
  • 6
    MAC addresses won't work if the machine doesn't have a network card. – Brian Jan 20 '09 at 19:54
  • 7
    @Brian - do you really need a unique value to identify a computer that doesn't have a network card? Seems a pretty safe bet the machine has a card. – romandas Mar 20 '09 at 22:54
  • You can spoof and change your MAC address in literally 2 minutes. – Gaspa79 Dec 16 '20 at 14:38
0

I had an additional constraint, I was using .net express so I couldn't use the standard hardware query mechanism. So I decided to use power shell to do the query. The full code looks like this:

Private Function GetUUID() As String
    Dim GetDiskUUID As String = "get-wmiobject Win32_ComputerSystemProduct  | Select-Object -ExpandProperty UUID"
    Dim X As String = ""
    Dim oProcess As New Process()
    Dim oStartInfo As New ProcessStartInfo("powershell.exe", GetDiskUUID)
    oStartInfo.UseShellExecute = False
    oStartInfo.RedirectStandardInput = True
    oStartInfo.RedirectStandardOutput = True
    oStartInfo.CreateNoWindow = True
    oProcess.StartInfo = oStartInfo
    oProcess.Start()
    oProcess.WaitForExit()
    X = oProcess.StandardOutput.ReadToEnd
    Return X.Trim()
End Function
0

Why not use the MAC address of your network card?

Brian Matthews
  • 8,115
  • 6
  • 41
  • 67
  • 15
    Mac address can be spoofed – Henry B May 22 '09 at 11:26
  • This is valid idea in many cases, question does|t specify spoof-proodness or offline - you generaly want generate unique ID if you want to identify in a network – Hurda Mar 01 '12 at 13:19
0

Maybe cheating a little, but the MAC Address of a machines Ethernet adapter rarely changes without the motherboard changing these days.

bfabry
  • 1,849
  • 1
  • 11
  • 20
  • A lot of manufacturer allows you to change them. This is very helpfull when working with clusters because some of the vendors gives you all the computer with the same MAC address (we ran into this issue a few years ago). – gizmo Sep 19 '08 at 05:39
  • 1
    MAC is totally unreliable because it can be so easily changed (just to a google search and you will see lots of free tools that are doing this). The same for WMI. – Z80 Apr 07 '15 at 16:40
0

Can you pull some kind of manufacturer serial number or service tag?

Our shop is a Dell shop, so we use the service tag which is unique to each machine to identify them. I know it can be queried from the BIOS, at least in Linux, but I don't know offhand how to do it in Windows.

Christopher Cashell
  • 670
  • 3
  • 10
  • 20
-1

Try this one, it gives a unique hard disk ID: Port of DiskId32 for Delphi 7-2010.

bluish
  • 23,093
  • 23
  • 110
  • 171
wahm sarab
  • 89
  • 5
-1

Look up CPUID for one option. There might be some issues with multi-CPU systems.

bluish
  • 23,093
  • 23
  • 110
  • 171
BCS
  • 67,242
  • 64
  • 175
  • 277