6

I had a question regarding generating a specific computer ID for licensing purposes. Preferably this ID should be hardware based, and thus should not change if the user reformats for example. Also it should not be easy (or preferably even impossible) for the user to change the information that the ID is generated from. Currently I only have two components that I combine, the CPUID standard and feature flags and the geometry and total size of the first physical drive in the machine. While this seems to be good for most general PC's, a lot of netbooks for example are made with the exact same hardware and so you would get the same ID for many machines in that case. Can any of you suggest some other hardware component I could use?

I have two requirements:

  1. It must not use WMI.

  2. It must work in a large number of situations (including for users with no or few privileges). I thought of using the serial of the physical drive, but that seems hard to retrieve if the user is not in administrator mode.

I am working in C++ on Windows.

Thanks in advance for any suggestions.

plasmacel
  • 8,183
  • 7
  • 53
  • 101
Philip Bennefall
  • 1,477
  • 5
  • 20
  • 33

6 Answers6

4

You can use the first MAC address, which is assigned by the manufacturer of the hardware and will never change.

Something like this:

/** 

  return string containing first MAC address on computer

 requires adding Iphlpapi.lib to project

*/
string GetMac()
{
    char data[4096];
    ZeroMemory( data, 4096 );
     unsigned long  len = 4000;
    PIP_ADAPTER_INFO pinfo = ( PIP_ADAPTER_INFO ) data;
    char sbuf[20];
    string sret;

    DWORD ret = GetAdaptersInfo( pinfo, &len );
    if( ret != ERROR_SUCCESS )
        return string("**ERROR**");

    for(int k = 0; k < 5; k++ ) {
        sprintf(sbuf,"%02X-",pinfo->Address[k]);
        sret += sbuf;
    }
    sprintf(sbuf,"%02X",pinfo->Address[5]);
    sret += sbuf;

    return( sret );
}

IMHO, this is sufficient for licensing software valued up to a thousand dollars, where all that is necessary is to prevent casual consumers from sharing your software with their neighbours. A motivated pirate can get around it, but pirates with sufficient knowledge and motivation are not frequent enough to make it worthwhile for you to spend any more effort trying to defeat them and, even more important, you do not want to inconvenience your honest clients.

If your software is so valuable that motivated pirates are a real threat, then the cost and inconvenience of a hardware dongle becomes justified.

Neither do I believe in piling on more hardware signatures, disk drive IDs, motherboard configurations and so on. The increase in security is minimal and the chance that something may go wrong increases greatly so that you will end up wasting hours supporting clients with unusual setups and pissing off unknown numbers who simply give up on you.

Implement a simple system with the MAC address, which always seems to work. Accept that an occasional pirate may get their kicks from breaking your licence. Focus your efforts on improving your software so that you will gain more honest clients.

A system may have more than one network card ( e.g. ethernet and wireless ) and it is possible for the user to change the presentation order ( why would a user do this? ). To handle this, a licence would need to match a network card present anywhere on the system, requiring code something like this:

/**

  The MAC addresses of ethernet network cards present on computer

  @param[out] vMAC vector of strings containing MAC addresses in XX-XX-XX-XX-XX-XX format

  returns empty vector on error

  See discussion of this 
  http://stackoverflow.com/questions/6131123/generating-hardware-based-computerid/6131231#6131231

*/

void cLicenser::GetMac( vector < string >& vMac )
{
    vMac.clear();
    char data[4096];
    ZeroMemory( data, 4096 );
    unsigned long  len = 4000;
    PIP_ADAPTER_INFO pinfo = ( PIP_ADAPTER_INFO ) data;

    DWORD ret = GetAdaptersInfo( pinfo, &len );
    if( ret != ERROR_SUCCESS )
        return;

    while ( pinfo )
    {
        // ignore software loopbacks
        if( pinfo->Type != MIB_IF_TYPE_LOOPBACK )
        {
            char sbuf[20];
            string sret;
            for(int k = 0; k < 5; k++ )
            {
                sprintf(sbuf,"%02X-",pinfo->Address[k]);
                sret += sbuf;
            }
            sprintf(sbuf,"%02X",pinfo->Address[5]);
            sret += sbuf;
            vMac.push_back( sret );
        }
        pinfo = pinfo->Next;
    }

}
plasmacel
  • 8,183
  • 7
  • 53
  • 101
ravenspoint
  • 19,093
  • 6
  • 57
  • 103
  • Thanks for this! That's another component to add to my list. Now I have teo questions. – Philip Bennefall May 25 '11 at 21:36
  • Apologies, my browser messed up my post. I meant to say that I have one question. Is this the true physical hardware MAC address, or is it the address assigned by Windows to the adapter? The problem I can see is if a user has several drivers, even virtual ones, that could be uninstalled at any time; then the ID would change. – Philip Bennefall May 25 '11 at 21:38
  • It is the physical address given by the hardware manufactured and guaranteed to be unique. – ravenspoint May 25 '11 at 21:41
  • Again, MAC Addresses are not guaranteed to be unique. For example Intel recently shipped products that had duplicate MAC addresses burned in. [Here](http://www.intel.com/support/netport/10100/sb/cs-015197.htm) is their recall notice. Intel noticed it but a lot of companies with sub-standard quality control do not. – user258808 May 25 '11 at 21:47
  • @user258808 The MAC address is guaranteed to be unique by the manufacturer. If you or your clients buy hardware from manufacturers whose guarantees are worthless, you will have all sorts of problems ... – ravenspoint May 25 '11 at 21:50
  • @ravenspoint, I agree they are supposed to be unique, but the problem is their have been many instances of NIC's with duplicate MAC addresses. Also its easy to fake the MAC address, example [here](http://www.nthelp.com/NT6/change_mac_w2k.htm). If the OP wants this for the purpose of preventing piracy then I think there are better alternatives. – user258808 May 25 '11 at 22:05
  • @user258808 I would be glad to hear of a better method - by which I mean one that is simple, works on every machine, and does not require more effort than is justified by the tiny chance that a pirate could get hold of reliable equipment with duplicate MAC addresses. – ravenspoint May 25 '11 at 22:14
  • @ravenspoint: I was going to suggest using it in combination with CPU ID, MB ID etc. But it seems OP is already doing this. Honestly, I tried and failed to do something similar. At one point my company started shipping a hardware dongle with our product. Since then I have moved to a company that uses GPL so I do not have to deal with this anymore. – user258808 May 25 '11 at 22:28
  • user258808 I have been this business for many decades, and have not come across a better system, nor a real neccessity for a better system, for licensing software values at under $1000. For multi-thousand dollars software, a hardware dongle is the way to go. – ravenspoint May 25 '11 at 22:37
  • 1
    Looking at the description for the function used here on MSDN, I see the following remark: "The order in which adapters appear in the list returned by this function can be controlled from the Network Connections folder: select the Advanced Settings menu item from the Advanced menu." This could be a real problem for me since now we are depending on a software configuration parameter again. How is this usually handled? – Philip Bennefall May 26 '11 at 05:27
  • @user749473 How many of your clients have machines with two network cards? How many of that tiny number have any reason to change the order they appear in? This is a non problem! If you want to spend time on it anyway, then if more than one adapter is present, always use the one with the lowest numerical MAC address. – ravenspoint May 26 '11 at 11:42
  • My thought is that a lot of laptops, for instance, will have at least two. Ethernet, and whireless. And also one can install virtual network drivers for various reasons, which could also replace the lowest Mac address which could mean that when this virtual driver was uninstalled, the ID could change again. Are these guaranteed to be hardware only, e.g. no virtual ones show up in this list? – Philip Bennefall May 26 '11 at 12:14
  • @user749473 You may be correct about the presence of the multiple network cards. You are certainly correct that choosing the numerically lowest MAC address is a bad idea! I will stick with using the first MAC address, and assume that the order rarely changes – ravenspoint May 26 '11 at 12:31
  • This is a very good idea. Then the only question yet to be answered is, can one tell a software driver apart from a hardware one? When making the initial choice of which network card to make use of, I'd like to find the one that is least likely to be uninstalled. Order is obviously no longer a problem, but if the first network adapter should happen to be a virtual one that the user installed temporarily, then the ID would break as soon as this was uninstalled. So in short, can one determine from this list whether an adapter is actually hardware based? – Philip Bennefall May 26 '11 at 13:08
  • I have no experience with virtual network cards. My guess would be that new installations would appear at the end of the list. Can you try it and see? If so, please let us know. – ravenspoint May 26 '11 at 13:22
  • Will do that. Thanks a million to all of you for taking the time to help. – Philip Bennefall May 26 '11 at 13:32
  • I have now got a solution working where it enumerates all Mac addresses and matches them with the original ID. The only difference is that I am using the slightly more complex GetAdaptersAddresses function, since the function mentioned here has been depricated. All seems to work fine thus far, but I will be doing some more testing. Thanks to all of you for helping! – Philip Bennefall May 26 '11 at 17:10
  • 1
    I can verify that when a virtual network driver is installed, at least on my machine it shows up as the first available adapter. There is no way to tell it apart from the real card, e.g. they both show up as type Ethernet etc even though the virtual driver is only a loopback. Will dig deeper into this. – Philip Bennefall May 26 '11 at 18:25
  • @user749473 perhaps you might look at the IfType member. It is supposed to be the type of interface. 6 = ethernet 24 = software loopback – ravenspoint May 26 '11 at 18:41
  • I examined this member, and they are both set as Ethernet adapters; so no way to tell them apart. Also, if I go into my control panel and disable the local area connection which refers to my physical adapter, the Mac address is irretrievable. In other words I do not have to uninstall the driver, just temporarily disable it to throw the system off guard so to speak. – Philip Bennefall May 26 '11 at 19:13
  • @user749473 It is interesting that your newly installed virtual network driver showed up at the beginning of the list. I assumed it would be the end. I now wonder if the licenser should choose the last address in the list to use as its basis. Is the last address in the list the most stable? – ravenspoint May 27 '11 at 13:31
  • I'm not quite sure (I have only tried with two drivers which is to say my actual card and the virtual one), so I am not certain how it behaves if you had 4 or 5 cards installed. But yes, based on this fact alone it would seem appropriate to pick the last one in the list. – Philip Bennefall May 27 '11 at 20:48
  • http://stackoverflow.com/questions/6162404/where-does-a-newly-installed-network-card-appear-in-list-returned-by-getadaptersa – ravenspoint May 28 '11 at 15:01
  • What is that extra parenthesis in `if ( pinfo->Type == MIB_IF_TYPE_ETHERNET ) (`? – plasmacel May 06 '20 at 11:14
  • @plasmacel fixed – ravenspoint May 06 '20 at 14:09
  • @ravenspoint You still have a `continue` at the beginning of the `if` block. The remaining code in the branch after `continue` will never run. – plasmacel May 06 '20 at 19:08
3

I tried doing something similar a few years ago and failed. I tried using a combination of hardware ID's that I could read. Most CPU's have a CPUID, a unique number that is used to uniquely identify and track them. However the problem is that its not garunteed that each CPU out there will have this ID. In fact, when I tried it the Intel Celeron series did not have this ID. Certain Motherboards(mainly Intel) also shipped with a unique ID that you can use.

Here is a link to an article that describes how to get this information.

I also used any / all MAC ID's in combination with the CPU ID & MB ID as a seed to generate unique GUID. The more hardware ID's you use as seed the better this performed.The problem is that if you do upgrade any of the hardware components the ID changes and the software Key gets invalidated.

Also keep in mind that Virtual Machines complicate this even further. I think your best bet would be to do what Microsoft does.

Microsoft does use a similar approach where they take a Hardware fingerprint of a machine on which the OS is installed and communicate it along with the Registration Key to activate a copy of the OS / Office suite. If you upgrade your hardware significantly(I think 4 hardware components) the Key will change and you will have to contact Microsoft and provide proof to re-validate your copy of Windows.

user258808
  • 734
  • 4
  • 5
2

If you only need to generate it once, the a GUID will be unique to the machine that created it. The problem is you'll get a different value every time you generate one. But if it's a one-off per machine, a GUID will work.

If it needs to be the same per machine and generated multiple times, the the MAC address is the universal ID for machines (though you may have multiple MACs to choose from).

Daniel Williams
  • 8,912
  • 15
  • 68
  • 107
  • Actually it's easy to modify Windows registry to mask the burned in MAC address with something else, Example [here](http://www.nthelp.com/NT6/change_mac_w2k.htm). And it is possible to have duplicate burned in MAC addresses, so using MAC address is not reliable. – user258808 May 25 '11 at 21:37
  • If you're expecting to get around a user altering the MAC address, then you've got quite a challenge. What if a user replaces the hard drive - should the ID remain the same? What if they switch ethernet card, disk and CPU? When does the machine become different machine? I was thinking you just wanted a reliable way to ID a machine from a "pull a unique ID" point of view. But it seems you're looking to ensure an identity, quite different. Good luck! – Daniel Williams May 25 '11 at 21:44
  • To be more specific, if the actual hardware changes then it's a new machine as far as the program is concerned. What I am trying to avoid is the ID changing through software changes, such as if someone installs a virtual Ethernet driver that might show up as the first MAC address. In other words, I am trying to get information about hardware components only that stays fixed unless the physical hardware itself changes. – Philip Bennefall May 25 '11 at 22:01
0

Maybe this method will help you. http://www.codeproject.com/Articles/319181/Haephrati-Searching-for-a-reliable-Hardware-ID

Michael Haephrati
  • 3,660
  • 1
  • 33
  • 56
0

If such a thing were easy and reliable, Microsoft would have found and patented it long ago.

There have been attempts to protect software by some hardware doo-dad, including shipping a thing called a 'dongle' with every licensed software package. Hey Valuable New Customer! Just plug in the dongle and run your new software!

It was a riot to see a Rube Goldberg arrangement of three or four dongles plugged one into the next and hanging off the parallel port, each enabling its own software package.

Pete Wilson
  • 8,610
  • 6
  • 39
  • 51
0

One of many options is to use CPU ID. Better than Windows Registry, or network card, for example. You don't want users to bother you each time they change network card etc. I think cpuid project can be used as an example and starting point.