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.

2
  • 1
    Have you looked at stackoverflow.com/questions/910619/… here on SO? Commented May 25, 2011 at 21:27
  • @Philip Bennefall, have you got a solution? I have the same problem. Commented Feb 9, 2017 at 18:08

6 Answers 6

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;
    }

}
Sign up to request clarification or add additional context in comments.

26 Comments

Thanks for this! That's another component to add to my list. Now I have teo questions.
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.
It is the physical address given by the hardware manufactured and guaranteed to be unique.
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?
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.
|
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.

Comments

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).

3 Comments

Actually it's easy to modify Windows registry to mask the burned in MAC address with something else, Example here. And it is possible to have duplicate burned in MAC addresses, so using MAC address is not reliable.
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!
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.
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.

Comments

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.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.