Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating hardware based computerID

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.

like image 386
Philip Bennefall Avatar asked May 25 '11 21:05

Philip Bennefall


1 Answers

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

}
like image 62
ravenspoint Avatar answered Sep 22 '22 02:09

ravenspoint