Reliable way of generating unique hardware ID - windows

Question: I have to come up with unique ID for each networked client, such that:
it (ID) should persist once client software is installed on target computer, and should continue to persist if software is re-installed on same computer and same OS installment,
it should not change if hardware configuration is modified in most ways (except changing the motherboard)
When hard drive with client software installed is cloned to another computer with identical hardware configuration (or, as similar as possible), client software should be aware of that change.
A little bit of explanation and some back-story:
This question is basically age old question that also touches the topic of software copy-protection, as some of the mechanisms used in that area are mentioned here. I should be clear at this point that I'm not looking for a copy-protection scheme. Please, read on. :)
I'm working on a client-server software that is supposed to work in a local network. One of the problems I have to solve is to identify each unique client in the network (not so much of a problem), so that I can apply certain attributes to every specific client, retain and enforce those attributes during the deployment lifetime of a specific client.
While I was looking for a solution, I was aware of the following:
Windows activation system uses some kind of heavy fingerprinting mechanism that is extremely sensitive to hardware modifications,
Disk imaging software copies along all Volume IDs (tied to each partition when formatted), and custom, uniquely generated IDs during installation process, during first run, or in any other way, that is strictly software in its nature, and stored in registry or on hard drive, so it's very easy to confuse two.
The obvious choice for this kind of problem would be to find out BIOS identifiers (not 100% sure if this is unique through identical motherboard models, though), as that's the only thing I can rely on that isn't duplicated, transferred by cloning, and that can't be changed (at least not by using some user-space program). Everything else fails as either being not reliable (MAC cloning, anyone?), or too demanding (in terms that it's too sensitive to configuration changes).
Sub-question that I'd like to ask is, am I doing it correctly, architecture-wise? Perhaps there is a better tool for the task that I have to accomplish...
Another approach I had in mind is something similar to a handshake mechanism, where a server maintains an internal lookup table of connected client IDs (which can be even completely software-based and non-unique at any given moment), and tells the client to come up with a different ID during handshake, if a duplicate ID is provided upon connection. That approach, unfortunately, doesn't play nicely with one of the requirements to tie attributes to specific client during lifetime.

It seems to me that you should construct the unique ID corresponding to your requirements. This ID can be constructed as a hash (like MD5, SHA1 or SHA512) from the information which is important for you (some information about software and hardware component).
You can make your solution more secure if you sign such hash with your private key and your software verify during the starting, that the key (signed hash value) is signed (only public key must be installed together with your software). One can expand such kind of solution with different online services, but corporate clients could find online services not so nice.

What you're looking for is the Windows WMI. You can get the motherboard ID (which is unique across the same type of motherboard) or many many other types of unique identifiers and come up with some clever seeded function to generate a UHID. Whoa did I just make up an acronym?
And if you're looking specifically for getting the Motherboard (BIOS) ID:
WMI class: Win32_BIOS
Namespace: \Root\Cimv2
Documentation: http://msdn.microsoft.com/en-us/library/aa394077(VS.85).aspx
Sample code: http://msdn.microsoft.com/en-us/library/aa390423%28VS.85%29.aspx
Edit: You didn't specify a language (and I assumed C++), but this can be done in Java (with a COM driver), and any .NET language, as well.

Many programs use the hostId in order to build a license code (like those based on FlexLM). Have a look at what Matlab does depending on the operative system:
http://www.mathworks.com/support/solutions/en/data/1-171PI/index.html
Also have a look at this question:
Getting a unique id from a unix-like system
Once I also saw some programs basing their licenses on the serial number of the hard drive, an maybe that is the less likely thing to change. Some would suggest to use the MAC of your ethernet card, but that can be reprogrammed.

MAC
DON'T RELY ON MAC! EVER. It is not permanent. The user can easily change it (under 30 seconds).
Volume ID
DON'T RELY ON Volume ID! EVER. It is not permanent. The user can easily change it. It also changes by simply formatting the drive.
WMI
WMI is a service. Can be easily disabled. Actually, I tried that and I find out that on many computers is disabled or broken (yes, quite often broken).
License server
Connection to a validation server may cause you also lots of troubles because:
* your customers may not always be connected to the Internet.
* your customers may connect with special settings (router/NAT/proxy/gateway) that they need to input into your program in order to let it connect to the validation server.
* they may be behind a firewall that will block all programs except a few (my case). In some cases the firewall may not be under their control (valid for MOST corporate users)!
* it is super easy to redirect your program to a local fake webserver that emulates your licensing server.
Hardware data
If you need strong protection you need to rely on hardware. Something that cannot be edited by the user. Something like CPU ID instruction available in the Intel/AMD CPUs and the serial number written into the drive's IDE interface.
The CPU ID and HDD ID are permanent. They will never change, not even after you format the computer and reinstall Windows.
It is doable. For example this library reads the hardware ID of a computer. There is a compiled demo and also sourcecode/DLL. Disclaimer: the link leads to a commercial product (19€/no royalties).

Related

How to get Mac address of system using snmp?

I am using snmpwalk for retrieve my system(localhost) or remote system's mac address and I am using this command:
snmpwalk -v2c -c public localhost .1.3.6.1.2.1.2.2.1.6
and get an error like noSuchObject.
How can I solve this error? Is there another way to get system mac address using snmp?
There is no such thing as "system MAC address". Systems do not have MAC addresses; network interfaces do, and a system may have zero, one, two or more network interfaces.
That's why you use snmpwalk: because .1.3.6.1.2.1.2.2.1.6 (i.e. ifPhysAddress) is a column in a table of interfaces and you don't know in advance how many conceptual rows you'll get back (and what unique numerical index each row will use as its key).
So, you're using the command properly. But next we have to consider that times have changed since the SNMP and SMI RFCs were written, well before the dot-com boom and back when the internet was a relatively pleasant and happy place. Nowadays, implementations tend to be far more conservative in the information they disclose, because every piece of information you disclose is potentially another way to attack your system. Why does anyone need access to know your system's MAC address? They probably don't. I created an SNMP Agent recently and its support for "standard" objects doesn't go anywhere near listing network interfaces. And many of the RFC1213 packet/status counters in snmp were deliberately made obsolete when a "safe" subset was adopted into RFC1907.
What does this mean for you? Well, the remote system must have a network interface otherwise you wouldn't be able to talk to it. So, the SNMP Agent you're polling/querying (you didn't say which) is either hardcoded or configured not to provide this information. You can't get around that, except by talking to the person who created the software and asking whether it is configurable; prepare for the answer to be "no".

how can I Uniquely identify a computer

I would like to develop an application that can connect to server and uniquely identify clients then give them permissions to run a specific query on server's database.
How can I identify clients in a unique way. Is MAC address reliable enough? or should I use something like CPU id or something else?
clarification : I do not what to create a registration code for my app. As it's suppose to be a free application. I would want to detect each client by an id and decide which one could have the permissions to run a specific method on server or not.
The usual approach is to give each client a login (name + password). That way, it's easy to replace clients when they need upgrade or when they fail.
MAC address should be unique but there is no central registry which enforces this rule. There are also tools to change it, so it's only somewhat reliable.
CPU and HD IDs are harder to change but people will come complaining when their hard disk died or when they upgrade their system.
Many PCs have TPM modules which have their own IDs but they can be disabled and the IDs can be wiped. Also, there are privacy issues (people don't like it when software automatically tracks them).
Another problem with an automated ID approach is how to identify them on the server. When several clients connect for the first time in quick succession, you will have trouble to tell them apart.
This question appears to have already been asked and answered in detail (although, you may not like the answers, since they appear to add up to: it's problematic.) I agree with Xefan's comment that more details would help define your question. Here's a link to earlier discussion on this:
What is a good unique PC identifier?

is it reasonable to protect drm'd content client side

Update: this question is specifically about protecting (encipher / obfuscate) the content client side vs. doing it before transmission from the server. What are the pros / cons on going in an approach like itune's one - in which the files aren't ciphered / obfuscated before transmission.
As I added in my note in the original question, there are contracts in place that we need to comply to (as its the case for most services that implement drm). We push for drm free, and most content providers deals are on it, but that doesn't free us of obligations already in place.
I recently read some information regarding how itunes / fairplay approaches drm, and didn't expect to see the server actually serves the files without any protection.
The quote in this answer seems to capture the spirit of the issue.
The goal should simply be to "keep
honest people honest". If we go
further than this, only two things
happen:
We fight a battle we cannot win. Those who want to cheat will succeed.
We hurt the honest users of our product by making it more difficult to use.
I don't see any impact on the honest users in here, files would be tied to the user - regardless if this happens client or server side. This does gives another chance to those in 1.
An extra bit of info: client environment is adobe air, multiple content types involved (music, video, flash apps, images).
So, is it reasonable to do like itune's fairplay and protect the media client side.
Note: I think unbreakable DRM is an unsolvable problem and as most looking for an answer to this, the need for it relates to it already being in a contract with content providers ... in the likes of reasonable best effort.
I think you might be missing something here. Users hate, hate, hate, HATE DRM. That's why no media company ever gets any traction when they try to use it.
The kicker here is that the contract says "reasonable best effort", and I haven't the faintest idea of what that will mean in a court of law.
What you want to do is make your client happy with the DRM you put on. I don't know what your client thinks DRM is, can do, costs in resources, or if your client is actually aware that DRM can be really annoying. You would have to answer that. You can try to educate the client, but that could be seen as trying to explain away substandard work.
If the client is not happy, the next fallback position is to get paid without litigation, and for that to happen, the contract has to be reasonably clear. Unfortunately, "reasonable best effort" isn't clear, so you might wind up in court. You may be able to renegotiate parts of the contract in the client's favor, or you may not.
If all else fails, you hope to win the court case.
I am not a lawyer, and this is not legal advice. I do see this as more of a question of expectations and possible legal interpretation than a technical question. I don't think we can help you here. You should consult with a lawyer who specializes in this sort of thing, and I don't even know what speciality to recommend. If you're in the US, call your local Bar Association and ask for a referral.
I don't see any impact on the honest users in here, files would be tied to the user - regardless if this happens client or server side. This does gives another chance to those in 1.
Files being tied to the user requires some method of verifying that there is a user. What happens when your verification server goes down (or is discontinued, as Wal-Mart did)?
There is no level of DRM that doesn't affect at least some "honest users".
Data can be copied
As long as client hardware, standalone, can not distinguish between a "good" and a "bad" copy, you will end up limiting all general copies, and copy mechanisms. Most DRM companies deal with this fact by a telling me how much this technology sets me free. Almost as if people would start to believe when they hear the same thing often enough...
Code can't be protected on the client. Protecting code on the server is a largely solved problem. Protecting code on the client isn't. All current approaches come with stingy restrictions.
Impact works in subtle ways. At the very least, you have the additional cost of implementing client-side-DRM (and all follow-up cost, including the horde of "DMCA"-shouting lawyer gorillas) It is hard to prove that you will offset this cost with the increased revenue.
It's not just about code and crypto. Once you implement client-side DRM, you unleash a chain of events in Marketing, Public Relations and Legal. A long as they don't stop to alienate users, you don't need to bother.
To answer the question "is it reasonable", you have to be clear when you use the word "protect" what you're trying to protect against...
For example, are you trying to:
authorized users from using their downloaded content via your app under certain circumstances (e.g. rental period expiry, copied to a different computer, etc)?
authorized users from using their downloaded content via any app under certain circumstances (e.g. rental period expiry, copied to a different computer, etc)?
unauthorized users from using content received from authorized users via your app?
unauthorized users from using content received from authorized users via any app?
known users from accessing unpurchased/unauthorized content from the media library on your server via your app?
known users from accessing unpurchased/unauthorized content from the media library on your server via any app?
unknown users from accessing the media library on your server via your app?
unknown users from accessing the media library on your server via any app?
etc...
"Any app" in the above can include things like:
other player programs designed to interoperate/cooperate with your site (e.g. for flickr)
programs designed to convert content to other formats, possibly non-DRM formats
hostile programs designed to
From the article you linked, you can start to see some of the possible limitations of applying the DRM client-side...
The third, originally used in PyMusique, a Linux client for the iTunes Store, pretends to be iTunes. It requested songs from Apple's servers and then downloaded the purchased songs without locking them, as iTunes would.
The fourth, used in FairKeys, also pretends to be iTunes; it requests a user's keys from Apple's servers and then uses these keys to unlock existing purchased songs.
Neither of these approaches required breaking the DRM being applied, or even hacking any of the products involved; they could be done simply by passively observing the protocols involved, and then imitating them.
So the question becomes: are you trying to protect against these kinds of attack?
If yes, then client-applied DRM is not reasonable.
If no (for example, you're only concerned about people using your app, like Apple/iTunes does), then it might be.
(repeat this process for every situation you can think of. If the adig nswer is always either "client-applied DRM will protect me" or "I'm not trying to protect against this situation", then using client-applied DRM is resonable.)
Note that for the last four of my examples, while DRM would protect against those situations as a side-effect, it's not the best place to enforce those restrictions. Those kinds of restrictions are best applied on the server in the login/authorization process.
If the server serves the content without protection, it's because the encryption is per-client.
That being said, wireshark will foil your best-laid plans.
Encryption alone is usually just as good as sending a boolean telling you if you're allowed to use the content, since the bypass is usually just changing the input/output to one encryption API call...
You want to use heavy binary obfuscation on the client side if you want the protection to literally hold for more than 5 minutes. Using decryption on the client side, make sure the data cannot be replayed and that the only way to bypass the system is to reverse engineer the entire binary protection scheme. Properly done, this will stop all the kids.
On another note, if this is a product to be run on an operating system, don't use processor specific or operating system specific anomalies such as the Windows PEB/TEB/syscalls and processor bugs, those will only make the program even less portable than DRM already is.
Oh and to answer the question title: No. It's a waste of time and money, and will make your product not work on my hardened Linux system.

What's a good way to uniquely identify a computer?

I'm developing some desktop software for a client to resell. The client wants to restrict the software so that the registration code will be specific to one and only one computer.
Besides using the MAC from the network card, does anyone have any other techniques (that work on both Windows and Mac OS X) for uniquely identifying a computer?
Another solution is to use a licensing technology with a dongle. This is a small device that plugs into USB or another I/O port on the host, and serves as a unique, physical key to activate the software.
A third solution is to provide a license manager. That is, when the software starts up, it queries a server on the network (either on the customer's LAN or else accessed at your company via the internet) that validates that the customer's usage of the software is legitimate. This is a good solution for "concurrent licenses" so customers can install your software on many hosts, but you license it for simultaneous use on a limited number of hosts. FLEXnet Publisher is an example of a license management solution.
The MAC address of the network card is the solution I used last time I worked for a company that licensed software to run on a specific host.
However, I want to offer a caution: if you do this type of licensing, you have to anticipate that it'll become an ongoing administrative chore to track your customers' licenses. Once you have a few hundred customers, you'll be amazed at how frequently you get phone calls with requests to change keys
"We upgraded our server to a gigabit
network adapter, and now the license
won't work because the new adapter has
a different MAC address."
Or else the customers may replace their whole machine, and need an updated license to run your software on the new machine. We got these calls practically every day at the company I worked for.
You also need to trust the customer to stop using your software on the old computer (or network adapter) if you give them a new key. If you couldn't trust them to obey the license in the first place, how can you trust that they'll throw away the old key?
If you don't plan how you're going to support this administrative activity, don't license your product in this way. You'll only inconvenience your good customers, who would have cooperated anyway.
best way is taking the UUID using C# in Windows
The Best Way To Uniquely Identify A Windows Machine
public string GetUUID()
{
var procStartInfo = new ProcessStartInfo("cmd", "/c " + "wmic csproduct get UUID")
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
var proc = new Process() { StartInfo = procStartInfo };
proc.Start();
return proc.StandardOutput.ReadToEnd().Replace("UUID", string.Empty).Trim().ToUpper();
}
The idea I am toying with is using a few serial numbers or unique id's related to the hardware and hashing them together.
Things that get upgraded:
-Memory
-MACs (can be spoofed, usb adapters get plugged in, etc.)
Things that don't get upgraded often:
-CPU
-BIOS
-Motherboard
Using WMIC can be a great way to grab some info, I would start by grabbing things that don't change often as the first and preferred choice, I would like to be able to fingerprint at least 2 serial numbers or devices to use for generating a registration key.
wmic cpu get DeviceId /format:value
That will grab the CPU ID, you could run that command for:
1 - CPU (cpu:DeviceID)
2 - Motherboard (baseboard:serialnumber)
3 - BIOS (bios:serialnumber)
if you don't get at least 2 populated values, then grab
4 - Network Adapter - (nic:MACAddress)
5 - RAM - (memphysical:SerialNumber)
Depending on your business logic you can use the first two serial numbers available to create your registration number, and if you always follow the same order then on re-installs the registration number will still work, however if a device changes or a user tries to install on a secondary computer the id's change invalidating the registration number. To reduce the amount of tech support calls the least amount of hardware you fingerprint will give the least amount of headaches and if you try to fingerprint the least likely items to be upgraded that further reduces headaches. My preference is the order above.
You could use a Diffie-Hellman key exchange scheme to have the user generate a private/pulic key pair with their hardware id's as a payload, then pass this information up to a registration server where the registration server would use a public/private key to decrypt the payload and compute the registration key to return back to the end user. I like to use JWT to pass things back and forth witht he public keys included in the payload of the JWT. Hope that helps.
UUID was mentioned above and is a great idea you can get that by using the below command from your windows cmd.exe:
wmic csproduct get UUID /format:value
Disclaimer these command only work for Windows I think 2000 and above but you would need to verify, they maybe available for systems below 2000 but at that point I really try not to support those devices. Good luck. *Looks like WMI is being deprecated in favor of powershell so to keep this post current here are the power shell commands.
Get-CimInstance -ClassName Win32_Processor | Select SerialNumber
Get-CimInstance -ClassName Win32_BaseBoard | Select SerialNumber
Get-CimInstance -ClassName Win32_Bios | Select SerialNumber
Get-NetAdapter -Physical | Where-Object Status -like Up | Select-Object MacAddress
Get CimInstance -ClassName Win32_PhysicalMemory | Select SerialNumber
The network adapter cmdlet will only check for physical adapters so a virtual adapter couldn't be used and manipulated and I like to use the first adapter that is Up or being used so that a spare NIC can't be swapped around for install reasons.
On Mac:
system_profiler | grep "Serial Number (system)"
On Linux (debian):
sudo dmidecode -t system | grep "Serial Number"
dmidecode and system_profiler has other components it can grab serial numbers from similar to wmic in windows. I don't work on macs so I can't confirm a list of exact specs but creating a list of LCD (least common denominator) the serial numbers for the parts that all three commands can access is put together and groomed to the least likely parts to be upgraded or changed. Then a combination of the top 2-3 numbers hashed can make for a unique machine id that's a bit more robust and allows a cross platform app to be activated even on a device with it's operating system updated.
There is no sure way to uniquely identify a computer, if you assume a computer is built with many parts that can be replaced eventually.
Some hardware parts - MAC address, HDD disk serial number, even motherboard serial, etc - are a few good sources of "uniqueness" but as you may know if a client decides to upgrade the part the license depends on... be prepared for some customer support.
Also to keep in mind is that some parts can be spoofed (the MAC being one of them).
An online license check is another good way to go - you can manage everything on the server side and even define your own rules for it (how many licenses per client/install, concurrency, etc) but the big thing to note is what happens when connection can't be established?
I would just use the MAC address to generate a request key, then require users to register with your client. Your client will have a special application that takes that request key and produces an activation key which the user can then use for activating the software. Once activated, the software works, just works - no occasionally phoning home for verification and such.
That's if it were a real requirement. My first task would be to try and convince the client that this was a bad idea.
The reason is that these schemes practically never prevent your code from being cracked. They do however make the lives of your genuine customers harder. I find it hard to think of any other industry that goes out of its way to annoy its genuine customers with schemes that never achieve their goals (other than government service, of course :-).
If you must do this, I'd just do a token effort to meet the contractual obligation (don't tell your client this however). Taking the MAC address (or a random number if, $DEITY forbid, the computer didn't have a network card) as the request key and using a program to just XOR it with an ASCII string to get the activation key, seems like a workable approach. I would also store both keys since you don't want the software to de-activate if they just change their network card (or even motherboard) - they still see that as the same computer and will not be happy if the software stops working.
Your code's going to be cracked regardless (unless the program is rubbish which I'm sure is not the case) - this method will give your genuine customers an avenue for moving their software to another machine if your client's company becomes unresponsive somehow (drops support, goes out of business, and so on).
The main trouble with all schemes that rely on the uniqueness of a bit of hardware is that the customer may choose to change that bit of hardware:
ghosting their disk contents to a larger hard disk makes HD serial numbers change.
using CPU serial numbers means upgrading to the latest Intel bigmutha CPU kill your software.
using the MAC address means they can't change their NIC.
These can all be fixed by using those values to create a key at install time and only check against that key, not the changed value six months down the track. It means you have to store the request and activation values but upgrades will not require your users to go through the process of re-activating their software. Believe me, they will despise you for having to do that.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
"MachineGuid” key is generated uniquely during the installation of Windows and it won’t change regardless of any hardware swap (apart from replacing the boot-able hard drive where the OS are installed on). I am not sure about this.
MY SUGGESTION
You can Use that MachineGuid, Hard Disk Serial Number, Mother Board Serial Number and UUID. Together HASH it using SHA 256 or any other HASH function.
UUID - wmic csproduct get UUID
MachineGuid - HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
Hard Disk Serial Number - wmic diskdrive get serialnumber
BIOS Serial Number - wmic bios get serialnumber
Mother Board Serial Number - wmic baseboard get serialnumber
How about using MotherBoard unique serial number?
One can create a serial key that the user has to enter once.
It should include the user's eMail address (something like someuser#mailprovider.com-9828372-398232). This will stop many people from trying to tamper with it or give it to other people.
During activation, the software should check against an online db if the serial key exists.
Open up Registry and navigate to
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
Find the key called “MachineGuid” this key is generated uniquely during the installation of Windows and it won’t change regardless of any hardware swap (apart from replacing the boot-able hard drive where the OS are installed on). That means if you want to keep tracking installation per OS this is another alternative. It won’t change unless you do a fresh reinstall of Windows.
There used to be a serial number imprinted into the CPU's, as far as I have seen though; this information (PSN, Pentium Serial Number) has been deprecated. The information may possibly still exist, but at least in the P3 world it was gone. Also, I think the obvious choice of MAC address on the NIC for the main interface used for the host should be considered as a real possibility. Unless your client is not expecting ethernet interfaces to be present on the hosts that they sell to.
You might consider a third-party licensing utility which will more likely get this "right" and also provide you (or your client) with additional options should requirements change (and don't they always?). I'd mention some specific ones by name, but I'm really not intimately familiar them.
I have some experience on this. In my solution we issue service key when we sell the product to the client.
At the time client install the application it generate a key by reading the motherboard serial of the client machine. Client is supposed to email the service key and the key generated at the installation to our organization to activate the product.
We maintain an admin application at the organization at issue activation keys. We offer only one activation key for key for a particular service key.
We sold number of copies and it runs without an issue. But then we found out some computers that does not provide a motherboard serial number. Those machines return null value as the motherboard serial number. still we trying to fix this issue.
Or you could simply have no activiation code and ensure you have audit rights written into the EULA and exercise your right to audit from time to time.
Works wonders for Oracle.
how about hashing anything that has a burned-in SN, harddrive, proc, ram, etc... this hash will remain with the computer until it has it's parts replaced.

Generating a unique machine id

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
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).
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.
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.
What about just using the UniqueID of the processor?
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.
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.
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.
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.
There is a library available for getting hardware specific informations: Hardware serial number extractor (CPU, RAM, HDD, BIOS)
Maybe cheating a little, but the MAC Address of a machines Ethernet adapter rarely changes without the motherboard changing these days.
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.
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
Look up CPUID for one option. There might be some issues with multi-CPU systems.
Try this one, it gives a unique hard disk ID: Port of DiskId32 for Delphi 7-2010.

Resources