c++ intellectual property protection

This forum can be used to talk about general design strategies, new ideas and questions in general related to wxWidgets. If you feel your questions doesn't fit anywhere, put it here.
Post Reply
mael15
Super wx Problem Solver
Super wx Problem Solver
Posts: 387
Joined: Fri May 22, 2009 8:52 am
Location: Bremen, Germany

c++ intellectual property protection

Post by mael15 » Wed Nov 13, 2019 4:59 pm

After 10 years of only in house usage, the windows c++ app I am developing will be sold to an outside customer. So now I have to come up with some ways of intellectual property protection, so some way of licence authentification and raising the bar for reverse engineering.
The app will be pre-installed by me on a laptop and it will be used offline.
How can I protect the app from being copied to some other machine? Maybe checking some windows/computer hardware ID that does not change over time? And saving that ID encrypted in a database?
I am thinking about code obfuscation to make reverse engineering more difficult. Thing is, dotfuscator only works with managed c++ code. How can I find out if my code is managed?! Seems like a strange question from someone using c++ for 10 years now, but I always worked alone and never had to think about it. Another option I found is http://stunnix.com/prod/cxxo/, can anyone recommend it? Other options?
Or are there other roads to explore?
Thank you!

mael15
Super wx Problem Solver
Super wx Problem Solver
Posts: 387
Joined: Fri May 22, 2009 8:52 am
Location: Bremen, Germany

Re: c++ intellectual property protection

Post by mael15 » Fri Nov 15, 2019 12:17 pm

I am in the unique situation that my program will be sold together with a laptop. And it will probably be less than 20 per year, so I could make a manual encrypted computer ID database inside my app or in a separate file. When starting, the programm creates the laptop´s hardware ID (cpu serial? what else is possible?), creates an encrypted hash and compares it to the database values.
Is that a reasonable approach?

User avatar
doublemax
Moderator
Moderator
Posts: 14314
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: c++ intellectual property protection

Post by doublemax » Fri Nov 15, 2019 12:37 pm

Seems viable.

For the hardware ID there are also MAC addresses and serial numbers of hard drives. Another option would be a simple USB stick, most of them have unique serial numbers, so they can act as a simple dongle. But for a laptop based application that's probably not an option as the stick would be physically exposed and in danger of getting lost or damaged.

When it comes to code protection, it all depends on the user base. If it's some kind of industrial app, the chances that some (probably big) company cracks it in order to use it commercially is very slim, the legal danger for them is just too big. So i wouldn't care about that.
Use the source, Luke!

mael15
Super wx Problem Solver
Super wx Problem Solver
Posts: 387
Joined: Fri May 22, 2009 8:52 am
Location: Bremen, Germany

Re: c++ intellectual property protection

Post by mael15 » Fri Nov 15, 2019 1:15 pm

thanx! could you point me in the right direction on how to read different hardware ids?
as for the code protection: it is an industrial app, but there are competitors who might want to take a closer look, I actually did it myself in the past, so I need some protection there.

User avatar
doublemax
Moderator
Moderator
Posts: 14314
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: c++ intellectual property protection

Post by doublemax » Fri Nov 15, 2019 2:16 pm

Here's something for the MAC address:
viewtopic.php?p=45811#p45811

And some code for USB serials, Windows only:

Code: Select all

#include "wx/msw/registry.h"

wxRegKey reg(wxT("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\USBSTOR\\Enum"));

long count = -1;
if(reg.QueryValue(wxT("count"), &count) && count > 0)
{
  for(long i = 0; i < count; i++) 
  {
    wxString data;
    if( reg.QueryValue(wxString::Format(wxT("%d"), i), data) )
    {
      wxArrayString tokens = wxSplit(data, '\\');
      if(tokens.Count() == 3)
      {
        wxLogMessage("usb serial #%d: %s", i, tokens[2]);
      }
    }
  }
}
Getting the CPU serial should be possible using the __cpuid instruction, but i've never used that.
https://docs.microsoft.com/en-us/cpp/in ... ew=vs-2019

I have no experience with code protection. I know there are a few commercial solutions, but that's all i know about it.
Use the source, Luke!

mael15
Super wx Problem Solver
Super wx Problem Solver
Posts: 387
Joined: Fri May 22, 2009 8:52 am
Location: Bremen, Germany

Re: c++ intellectual property protection

Post by mael15 » Fri Nov 15, 2019 3:53 pm

Okay, I am pretty happy with this way of collecting unique hardware data. May it help someone with the same problem:

Code: Select all

#define WIN32_LEAN_AND_MEAN
#include <windows.h>      
#include <intrin.h>       
#include <iphlpapi.h>     


// we just need this for purposes of unique machine id. So any one or two mac's is       
// fine. 
int hashMacAddress(PIP_ADAPTER_INFO info)
{
	int hash = 0;
	for (int i = 0; i < info->AddressLength; i++)
	{
		hash += (info->Address[i] << ((i & 1) * 8));
	}
	return hash;
}

void getMacHash(int& mac1, int& mac2)
{
	IP_ADAPTER_INFO AdapterInfo[32];
	DWORD dwBufLen = sizeof(AdapterInfo);

	DWORD dwStatus = GetAdaptersInfo(AdapterInfo, &dwBufLen);
	if (dwStatus != ERROR_SUCCESS)
		return; // no adapters.      

	PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;
	mac1 = hashMacAddress(pAdapterInfo);
	if (pAdapterInfo->Next)
		mac2 = hashMacAddress(pAdapterInfo->Next);

	// sort the mac addresses. We don't want to invalidate     
	// both macs if they just change order.           
	if (mac1 > mac2)
	{
		int tmp = mac2;
		mac2 = mac1;
		mac1 = tmp;
	}
}

int getVolumeHash()
{
	DWORD serialNum = 0;

	// Determine if this volume uses an NTFS file system.      
	GetVolumeInformation(wxT("c:\\"), NULL, 0, &serialNum, NULL, NULL, NULL, 0);
	int hash = (int)((serialNum + (serialNum >> 16)) & 0xFFFF);

	return hash;
}

int getCpuHash()
{
	int cpuinfo[4] = { 0, 0, 0, 0 };
	__cpuid(cpuinfo, 0);
	int hash = 0;
	int* ptr = (int*)(&cpuinfo[0]);
	for (int i = 0; i < 8; i++)
		hash += ptr[i];

	return hash;
}
One has to link against Iphlpapi.lib for the GetAdaptersInfo magic.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2094
Joined: Sun Jan 03, 2010 5:45 pm

Re: c++ intellectual property protection

Post by PB » Fri Nov 15, 2019 5:53 pm

I thought that the MAC address as well as the volume ID (unlike HDD ID) can be (easily) changed? AFAIK CPUID is not a unique CPU ID, it is just features the CPU has, so it is the same for all CPUs with the same model?

BTW, on Windows, there is WMI interface for obtaining many low-level HW information, see e.g. here
https://stackoverflow.com/a/48741695/7267315

I think e.g. Windows activation basically used to work like this:
During activation collect several different unique data about the PC (e.g., CPU, motherboard, disk IDs, MAC address, RAM size)
Periodically check if they changed, and if a significant number of them changed, claim that this is a different computer and require a reactivation.
See e.g. here for some more (who knows how valid) information: https://www.pcsteps.com/4484-how-window ... ion-works/

As always, things like this are often balancing on a thin rope between preventing piracy and annoying the paying user...

mael15
Super wx Problem Solver
Super wx Problem Solver
Posts: 387
Joined: Fri May 22, 2009 8:52 am
Location: Bremen, Germany

Re: c++ intellectual property protection

Post by mael15 » Mon Nov 18, 2019 3:01 pm

PB wrote:
Fri Nov 15, 2019 5:53 pm
AFAIK CPUID is not a unique CPU ID, it is just features the CPU has, so it is the same for all CPUs with the same model?
Yes, I noticed that. I thought I could just use it as one more rarely changing number to include into calculating a unique hardware ID.
PB wrote:
Fri Nov 15, 2019 5:53 pm
BTW, on Windows, there is WMI interface for obtaining many low-level HW information, see e.g. here
https://stackoverflow.com/a/48741695/7267315
Very useful, thanx!
PB wrote:
Fri Nov 15, 2019 5:53 pm
As always, things like this are often balancing on a thin rope between preventing piracy and annoying the paying user...
After some more reading I guess I am going to use Themida and concentrate on the core features of my program.
Thank you, everyone! :)

Post Reply