-
C# - PC fingerprint (for program piracy protection)
The following code returns an 8 digit number that is the 'fingerprint' of the hardware of the PC it is running on.
Note that this is C# code and will not run on VB. Will probably adapt to VB.NET ok (any volunteers?)
Call with something like:
Code:
Fingerprint fp = new Fingerprint();
MessageBox.Show(fp.Value());
You can play around with what you test. This example tests quite
a few things and might be too slow for some uses - but testing
fewer things is less secure.
Note that not all PC's have all items. e.g. may not have network
card. Will not hang in this case as returns default values. Older
PC's may not have things like unique CPU or motherboard serial
numbers, so don't rely on this.
Normal use for this type of application is to generate 'activation'
codes for software. Customer sends you his fingerprint and you
send him a matching code to activate the software. If he posts
the code on the Internet, you don't need to worry too much as it
will only run on machines with the same fingerprint.
Advantages: more secure than universally reuseable activation
code, which will soon be on the serialz sites. Cheaper than a
dongle and nothing to ship.
Disadvantage: If legit user changes hardware then needs a new
code. May disuade/irritate some purchasers. (Best used with a
website where users can generate their own reactivation codes
to be sent only to their registered email address - and kill that
address if it generates an unreasonable number requests on the
same serial number. If app is guaranteed Internet access - e.g.
it's a browser or an FTP tool - then this process can be invisible to
the customer - just do it in background.)
Code:
using System;
using System.Globalization;
using System.Threading;
using System.Resources;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;
using System.Text;
namespace Whatever
{
public class Fingerprint
//Fingerprints the hardware
{
public string Value()
{
return pack(cpuId()
+ biosId()
+ diskId()
+ baseId()
+ videoId()
+ macId());
}
private string identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue)
//Return a hardware identifier
{
string result="";
System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
System.Management.ManagementObjectCollection moc = mc.GetInstances();
foreach(System.Management.ManagementObject mo in moc)
{
if(mo[wmiMustBeTrue].ToString()=="True")
{
//Only get the first one
if (result=="")
{
try
{
result = mo[wmiProperty].ToString();
break;
}
catch
{
}
}
}
}
return result;
}
private string identifier(string wmiClass, string wmiProperty)
//Return a hardware identifier
{
string result="";
System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
System.Management.ManagementObjectCollection moc = mc.GetInstances();
foreach(System.Management.ManagementObject mo in moc)
{
//Only get the first one
if (result=="")
{
try
{
result = mo[wmiProperty].ToString();
break;
}
catch
{
}
}
}
return result;
}
private string cpuId()
{
//Uses first CPU identifier available in order of preference
//Don't get all identifiers, as very time consuming
string retVal = identifier("Win32_Processor","UniqueId");
if (retVal=="") //If no UniqueID, use ProcessorID
{
retVal = identifier("Win32_Processor","ProcessorId");
if (retVal=="") //If no ProcessorId, use Name
{
retVal = identifier("Win32_Processor","Name");
if (retVal=="") //If no Name, use Manufacturer
{
retVal = identifier("Win32_Processor","Manufacturer");
}
//Add clock speed for extra security
retVal +=identifier("Win32_Processor","MaxClockSpeed");
}
}
return retVal;
}
private string biosId()
//BIOS Identifier
{
return identifier("Win32_BIOS","Manufacturer")
+ identifier("Win32_BIOS","SMBIOSBIOSVersion")
+ identifier("Win32_BIOS","IdentificationCode")
+ identifier("Win32_BIOS","SerialNumber")
+ identifier("Win32_BIOS","ReleaseDate")
+ identifier("Win32_BIOS","Version");
}
private string diskId()
//Main physical hard drive ID
{
return identifier("Win32_DiskDrive","Model")
+ identifier("Win32_DiskDrive","Manufacturer")
+ identifier("Win32_DiskDrive","Signature")
+ identifier("Win32_DiskDrive","TotalHeads");
}
private string baseId()
//Motherboard ID
{
return identifier("Win32_BaseBoard","Model")
+ identifier("Win32_BaseBoard","Manufacturer")
+ identifier("Win32_BaseBoard","Name")
+ identifier("Win32_BaseBoard","SerialNumber");
}
private string videoId()
//Primary video controller ID
{
return identifier("Win32_VideoController","DriverVersion")
+ identifier("Win32_VideoController","Name");
}
private string macId()
//First enabled network card ID
{
return identifier("Win32_NetworkAdapterConfiguration","MACAddress", "IPEnabled");
}
private string pack(string text)
//Packs the string to 8 digits
{
string retVal;
int x = 0;
int y = 0;
foreach(char n in text)
{
y ++;
x += (n*y);
}
retVal = x.ToString() + "00000000";
return retVal.Substring(0,8);
}
}
}
-
Stop piracy of software.....
Hey.... BrianHawley .....
I think this is very lenthy process... :( :(
The easier 1 is.....:D Just detect the the serial no of HDD and just check serial no in ur programme. If serial no matches then allow user to use the software.... I think this is the easy way....
What do u think :confused:
-
Well this is not handy. I use your software (both ideas) and then my computer needs to be formatted. Hey that's not nice I get a new HDD serial. Hmm, now both of your codes are not usefull anymore.
-
im not gonna mention any names *coughs* volid *coughs* but it changes ur hard drive serial # So whats the point doing it that way? Theres no easy way to do it. So that code is useless.
-
No problem....!!
If user format his HDD and serial # get changed then he've to send new serial no to a programmer who made the software. and programmer have to send his new password according to his serial # if the user has a legal copy of the software...!
Just put a code which shows the Serial # of HDD when user enters a worg password....
belive me this is the best idea and i've used this technique in on of my programme...
Just think abou it....
:D ;)
-
Only checking the hard-drive serial number is not very secure as it can be changed. It's only included as a fall-back because some PC's do not have individual CPU serials etc. However only a certain proportion of your users will know how to do this, so there is still some security in this method.
If you change something on the PC, then yes, you will need a new unlock code - which is why this mehtod is best if there is a website where users can generate codes without calling you.
If you want to get fancy, you could mod the code so that a user can change any one thing on the PC at a time without breaking the lock. i.e. recalculate and accept the fingerprint for everything, so long as a few things remained the same.
Problem with any type of software locking is that user convenience and program security lie in opposite directions, so it is always a compromise.
-
Dongles aren't even secure.
:p
-
No they are not 100% secure.
They can vary between almost no security and 99.99% depending on how they are used.
1) You must use a dongle with an ASIC (Application specific IC) chip. ASIC means that the manufacturer makes or has made a special chip, so nobody can buy the chip. Some cheap dongles have off-the shelf EPROMS that any idiot can clone with standard parts and an EPROM writer.
2) You must use a dongle with an algorythm that is not crackable in a practical time with present technology. (The algorythm sends back an encoded reply in response to a string sent to it.)
3) You must use the algorythm by sending ten or twenty different strings at random times and checking you get the expected replies. NOT just check that the dongle is there.
4) You must also periodically send random strings to the dongle, where you ignore the reply. This is to defeat dongle breakers that simply record the traffic between the PC and dongle, then clone the right response. This method overloads them, or fills up the drive with data.
5) Usual anti-hack rules apply. i.e. call the dongle from many places in the program, not just one. Keep security code isolated and encapsulated in different places - don't just call the same routine from different places. Checksum the EXE using a non-standard method. Have several layers of security that cut in at different and increasing time intervals - hacker breaks the daily one and sells your code, then the weekly one cuts in - he breaks that then the monthly one cuts in etc. etc.
6) If the protection trips, don't use obvious messages. Hackers search for them. Use a generic error routine you call from many places. Will take a lot of time for a hacker to back-track them all. Also a generic error message might make the customer call your help desk. He may not know he has a pirated copy and you might get a sale or catch a pirate.
7) Don't use dongle makers wizards to apply protection. Write your own.
8) Challenge a good hacker you trust to break it! If he/she succeeds, identify the weak points.
Dongles can get pretty near 100% if you use them properly - but I've seen 'dongle protected' programs that could be hacked in a few hours because they did not follow the above rules.
We have been selling dongle-protected software for ten years and have never ever had a single security break.
Remember that you are not trying to build a hack-proof program. That's impossible. You are trying to make it easier for a hacker to write a look-alike of your program from scratch than to break the protection.
You might also be interested to know that as well as dongles, Rainbow make an almost identical hardware device that is used by the US Military for data-encryption - so the technology is pretty good if used correctly.
-
Re: C# - PC fingerprint (for program piracy protection)
For you, guys ...
Code:
Imports System
Imports System.Globalization
Imports System.Threading
Imports System.Resources
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
Imports System.Reflection
Imports System.Text
Public Class Fingerprint
Public Function Value() As String
Return pack(cpuId() + biosId() + diskId() + baseId() + videoId() + macId())
End Function
Private Function identifier(ByVal wmiClass As String, ByVal wmiProperty As String, ByVal wmiMustBeTrue As String) As String
Dim result As String = ""
Dim mc As System.Management.ManagementClass = New System.Management.ManagementClass(wmiClass)
Dim moc As System.Management.ManagementObjectCollection = mc.GetInstances()
Dim mo As System.Management.ManagementObject
For Each mo In moc
If mo(wmiMustBeTrue).ToString() = "True" Then
If result = "" Then
Try
result = mo(wmiProperty).ToString()
Exit For
Catch
End Try
End If
End If
Next
Return result
End Function
Private Function identifier(ByVal wmiClass As String, ByVal wmiProperty As String) As String
Dim result As String = ""
Dim mc As System.Management.ManagementClass = New System.Management.ManagementClass(wmiClass)
Dim moc As System.Management.ManagementObjectCollection = mc.GetInstances()
For Each mo As System.Management.ManagementObject In moc
If (result = "") Then
Try
result = mo(wmiProperty).ToString()
Catch
End Try
End If
Next
Return result
End Function
Private Function cpuId() As String
'Uses first CPU identifier available in order of preference
'Don't get all identifiers, as very time consuming
Dim retVal As String = identifier("Win32_Processor", "UniqueId")
If retVal = "" Then
retVal = identifier("Win32_Processor", "ProcessorId")
If retVal = "" Then
retVal = identifier("Win32_Processor", "Name")
If retVal = "" Then
retVal = identifier("Win32_Processor", "Manufacturer")
End If
'Add clock speed for extra security
retVal += identifier("Win32_Processor", "MaxClockSpeed")
End If
End If
Return retVal
End Function
Private Function biosId() As String
Return identifier("Win32_BIOS", "Manufacturer") + identifier("Win32_BIOS", "SMBIOSBIOSVersion") + identifier("Win32_BIOS", "IdentificationCode") + identifier("Win32_BIOS", "SerialNumber") + identifier("Win32_BIOS", "ReleaseDate") + identifier("Win32_BIOS", "Version")
End Function
Private Function diskId() As String
Return identifier("Win32_DiskDrive", "Model") + identifier("Win32_DiskDrive", "Manufacturer") + identifier("Win32_DiskDrive", "Signature") + identifier("Win32_DiskDrive", "TotalHeads")
End Function
Private Function baseId() As String
Return identifier("Win32_BaseBoard", "Model") + identifier("Win32_BaseBoard", "Manufacturer") + identifier("Win32_BaseBoard", "Name") + identifier("Win32_BaseBoard", "SerialNumber")
End Function
Private Function videoId() As String
Return identifier("Win32_VideoController", "DriverVersion") + identifier("Win32_VideoController", "Name")
End Function
Private Function macId() As String
Return identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled")
End Function
Private Function pack(ByVal text As String) As String
Dim retVal As String
Dim x As Integer = 0
Dim y As Integer = 0
Dim n As Char
For Each n In text
y += 1
x += (AscW(n) * y)
Next
retVal = x.ToString() + "00000000"
Return retVal.Substring(0, 8)
End Function
End Class
My only problem is this bold marked line. VB.net does not allow to multiply a character with an integer. So what happend, if you do so in C#? Is my solution by creating an Ascii value ok?
SolutionDeveloper
MCSD
-
Re: C# - PC fingerprint (for program piracy protection)
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by BrianHawley
Cool!
Thx, Brian.
But my question is still open :afrog:
What happens if you multiply a char value within C#?
Rgds
SolutionDeveloper
-
Re: C# - PC fingerprint (for program piracy protection)
The char is implicitly converted to its ascii value before being multiplied.
so...
Code:
{
int x = 2;
int y = 0;
string s = "abc";
char c = s[1];
y = c * x;
}
...works okay.
But there are people who will tell you is bad practice to rely on implicit conversion.
Hope this helps.
-
Re: C# - PC fingerprint (for program piracy protection)
Yes, it does. It's excatly what my routine does as well...
Rgds
SolutionDeveloper
-
Re: C# - PC fingerprint (for program piracy protection)
Maybe the behaviour is a little less obvious once we get into Unicode strings, so perhaps better to convert explicitly as the purists recommend. I generally avoid implicit conversion, but that's more to do with readability.
-
Re: C# - PC fingerprint (for program piracy protection)
Brian, where did you find these strings:
"Win32_BIOS", "Win32_DiskDrive", "Win32_Processor" and so on...?
I can't find any list of these in MSDN.
What others are available?
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by wossname
Brian, where did you find these strings:
"Win32_BIOS", "Win32_DiskDrive", "Win32_Processor" and so on...?
I can't find any list of these in MSDN.
What others are available?
It is in MSDN. I'm guessing you have an MSDN content filter turned on.
Here is an on-line verison:
http://msdn.microsoft.com/library/de...win32_bios.asp
Hope that helps!
-
Re: C# - PC fingerprint (for program piracy protection)
That method also uses clock speed? So if I over clock my CPU by 1MHz, your software will no longer work? That is definately not a good idea. Writing security code like this in .Net is not a good idea either since it can be disassembled easily.
The best idea I've come accrossed is to have the person setup a username and password on your server(s). Then, when they purchase your software, attach it to the username, then make them login when they use the software. Just don't allow more than two connections at the sametime. It's a very good scheme if the user has an always on connection or requires it for your program, otherwise it could be cumbersom but you could always have an off-line mode where it verifies that it's a legal copy once every few days or so just by login in and checking if anyone else is using it.
-
Re: C# - PC fingerprint (for program piracy protection)
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by kasracer
That method also uses clock speed? So if I over clock my CPU by 1MHz, your software will no longer work?
I don't think it works that way. I reckon it would take the number that is hardwired into the CPU at the factory. Say its a 3ghz when it leaves the factory, and you clock it up to 3.5ghz I think it would still return 3ghz.
But I agree that this fingerprint should not be based upon customizable things like Ram, framework version and so on because they do not affect the validity of the software. Companies upgrade their hardware all the time they don't want to pay for new software every time they stick another gig of ram in their workstation. HDD serial number would be an exception of course.
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by wossname
I don't think it works that way. I reckon it would take the number that is hardwired into the CPU at the factory. Say its a 3ghz when it leaves the factory, and you clock it up to 3.5ghz I think it would still return 3ghz.
If it gets it the from the same place windows does that is shown by going to properties in my computer then if you change the clock speed then it will show a different clock speed. you can even get a processor to post as a different one that what you have by simply over/underclocking the fsb enough. I.E making a amd 2500+ post as a 2800+ or vice versa
-
Re: C# - PC fingerprint (for program piracy protection)
You can check anything you like (or not).
I agree clock speed is not the best choice!
Yes DotNet code can be pulled apart - but that's an argument against writing in DotNet at all - not against this methodology. You could use the same methodology in C++ for example.
The idea of having unique log-ons to a server is interesting, but what happens if the server is down? What about non-Internet apps or people with dial-up? What happens when you sell a hundred billion copies and overload your server?
There is no perfect method. They all have a down-side. It's an individual choice.
-
Re: C# - PC fingerprint (for program piracy protection)
Consider the following instead of using the Pack method (I had converted this whole thing to VB.Net, so the example is in VB.Net here):
VB Code:
Public Function Value() As String
Dim output as String = CPUID() & BIOSID() & DISKID() & BASEID() & VIDEOID() & MACID()
Dim SHA As New SHA1Managed
Dim tmpOutput as String
tmpOutput = Convert.ToBase64String(SHA.ComputeHash(ASCIIEncoding.ASCII.GetBytes(output)))
Return HttpUtility.UrlEncode(tmpOutput).Replace("%", "")
End Function
Also, you must add this to your imports:
VB Code:
Imports System.Text
Imports System.Security.Cryptography
Imports System.Web
Rationale:
The SHA1 hash algorithm will provide a strong unique key for the 'finger print' whereas the pack algorithm takes strongly unique data and dilutes it by packing it in to 8 digits! The extra encoding (Base64) and conversions (HTTP URL) do not reduce the strength of the hash - they only serve to simplify transmission by making it URLEncoded without any escape characters it becomes a 'plaintext' key which can be transmitted over an HTTP URL query or stored in a database without any string checks or conversions required.
Finally, the SHA1Managed is used as it is a 100% managed implementation of encryption engine. This code should work on Windows 98 as well as other .Net reference platforms without banging native security APIs(hence 'managed').
-
Re: C# - PC fingerprint (for program piracy protection)
Yes, ok.
Maybe I'm missing something, but why would you want to encrypt the hardware fingerprint? It's not as if it is something secret. The pack routine was just to reduce the size.
As for loss of discrimination, 8 digits gives 100 million possible fingerprints. We have been using this for a while and have over 800 fingerprints registered - none the same so far. Of course it can happen, but this is not intended to be military grade security. In DotNet they can always pull the code apart anyway if they want to break in!
-
Re: C# - PC fingerprint (for program piracy protection)
Brian, I have not encrypted the fingerprint at all - I have created a hash. The purpose of a hash key is to provide some level of uniqueness algorithm between keys. For example, a 1 bit hash would have a 50% chance of collission - right?
The strength of the hash determines its uniqueness. Thus, an 8 digit ascii packer provides a 'weak' hash (many ways to get the same numeric result) whilst SHA512 would provide a insanely 'strong' hash; that is the possibility of a conflict is increadibly remote.
Therefore, using SHA1 you get pretty solid level of uniqueness in the fingerprint value... this is important if you are talking self generating software serial numbers through internet auto activation or some such mechanism.
More information on SHA1:
http://www.answers.com/topic/sha-family
Regards
Joe
-
Re: C# - PC fingerprint (for program piracy protection)
Yes, you are right of course.
And I should have read your post properly before jumping to conclusions!!
Sorry about that. :blush:
-
Re: C# - PC fingerprint (for program piracy protection)
-
Re: C# - PC fingerprint (for program piracy protection)
Hello,
Can some please help me. I am trying to get a key for my hardware fingerprint. I am really new to this stuff, can you please show me how to do that?
-
Re: C# - PC fingerprint (for program piracy protection)
If you just cut and paste the code in the post at the top of this thread, it should work for you. You can then step through the code and see how it works.
-
Re: C# - PC fingerprint (for program piracy protection)
This method works only in XP and 2003:
PHP Code:
class HardDrive
{
private string model = null;
private string type = null;
private string serialNo = null;
public string Model
{
get {return model;}
set {model = value;}
}
public string Type
{
get {return type;}
set {type = value;}
}
public string SerialNo
{
get {return serialNo;}
set {serialNo = value;}
}
}
PHP Code:
ArrayList hdCollection = new ArrayList();
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach(ManagementObject wmi_HD in searcher.Get())
{
HardDrive hd = new HardDrive();
hd.Model = wmi_HD["Model"].ToString();
hd.Type = wmi_HD["InterfaceType"].ToString();
hdCollection.Add(hd);
}
searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
int i = 0;
foreach(ManagementObject wmi_HD in searcher.Get())
{
// get the hard drive from collection
// using index
HardDrive hd = (HardDrive)hdCollection[i];
// get the hardware serial no.
if (wmi_HD["SerialNumber"] == null)
hd.SerialNo = "None";
else
hd.SerialNo = wmi_HD["SerialNumber"].ToString();
++i;
}
// Display available hard drives
foreach(HardDrive hd in hdCollection)
{
Console.WriteLine("Model\t\t: " + hd.Model);
Console.WriteLine("Type\t\t: " + hd.Type);
Console.WriteLine("Serial No.\t: " + hd.SerialNo);
Console.WriteLine();
}
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by mendhak
This method works only in XP and 2003:
Is anybody running any other version of Windows these days ? :)
-
Re: C# - PC fingerprint (for program piracy protection)
Hi all,
Does anybody know if the WMI code shown at the top of thread works under specific security (or other) circumstances?
I have been using BIOSSN and MACADDRESS for my software, and it seems it works OK on some PCs, while not working at all on others.
Thanks
-
Re: C# - PC fingerprint (for program piracy protection)
MAC Address would of course depend on having a network card (or equivalent) present and is perhaps not the best choice as network cards tend to be changed. There is also the possibility of changing the MAC address with a utility to whatever the users wants, when it is in firmware.
Bios serial should be okay as far as I know. Maybe some generic BIOS chip sets with no number, but I guess they should return something, if only a row of zeros or a null.
Can you define "not working". Does it cause a hang, or you just don't get back a number you can use?
If you restrict your software to XP and above (i.e. check the OS), I THINK that can only run on PCs with a modern CPU - i.e. with a serial number. Anybody know more about that?
-
Re: C# - PC fingerprint (for program piracy protection)
Funny thing, after going to all the trouble of updating this software to generate strong hash keys etc. I had to finally abandon the entire approach in my application. We had deployed the application to a broad consumer base with a crossection of different platforms.
We were never able to get WMI to work correctly under Windows98 - even with the Windows 9x WMI update from Microsoft:
http://www.microsoft.com/downloads/d...displaylang=en
Thats not too bad - and we were willing to use a fallback manual registration scheme for those clients and use the WMI approach for Windows 2000, XP and 2003. The problem we found however, was that lots of security apps lock down aspects of WMI. We have never been able to establish where exactly the lockdown occurs - but it seems to be in the system policies. (thats an educated guess, so if you figure the real place let me know)... so even in latter versions of the OS - the ability to rely on WMI in a customer installation was not there.
:confused:
Some (edited) error reports follow; you will notice they reresent the two key issues WMI message filter and the non existance of WMI component registration:
Quote:
SYS: Microsoft Windows NT 5.1.2600.0
CLR: 1.1.4322.2032
System.Runtime.InteropServices.COMException (0x80010002): Call was canceled by the message filter.
at System.Management.ManagementScope.Initialize()
at System.Management.ManagementObject.Initialize(Boolean getObject)
at System.Management.ManagementClass.GetInstances(EnumerationOptions options)
at System.Management.ManagementClass.GetInstances()
at pixolut.itoknet.CommonObjects.Hardware.get_CPUID() in C:\itok\iTOKNET\Common\CommonObjects\Security\Hardware.vb:line 67
at pixolut.itoknet.CustomerClient.Main.TestCompatability() in C:\itok\iTOKNET\Client\CustomerClient\Main.vb:line 417
Quote:
SYS: Microsoft Windows NT 5.1.2600.0
CLR: 1.1.4322.573
System Info: Microsoft Windows NT 5.1.2600.0
System.Runtime.InteropServices.COMException (0x80040154): Class not
registered at System.Management.ManagementScope.Initialize()
at System.Management.ManagementObject.Initialize(Boolean getObject)
at System.Management.ManagementClass.GetInstances(EnumerationOptions options)
at System.Management.ManagementClass.GetInstances()
at pixolut.itoknet.CommonObjects.Hardware.identifier(String wmiClass,String wmiProperty) in C:\itok\iTOKNET\Common\CommonObjects\Security\Hardware.vb:line 98
at pixolut.itoknet.CommonObjects.Hardware.CPUID() in C:\itok\iTOKNET\Common\CommonObjects\Security\Hardware.vb:line 113
at pixolut.itoknet.CommonObjects.Hardware.FingerPrint() in C:\itok\iTOKNET\Common\CommonObjects\Security\Hardware.vb:line 73
at pixolut.itoknet.CommonObjects.Hardware.get_ID() in C:\itok\iTOKNET\Common\CommonObjects\Security\Hardware.vb:line 60
at pixolut.itoknet.CustomerClient.Main.TestCompatability() in C:\itok\iTOKNET\Client\CustomerClient\Main.vb:line 416
I finally ended up going with a different approach;
1. We take a sample of certain registry keys in HKLM\Software\Microsoft\Windows\CurrentVersion and HKLM\System\CurrentControlSet\Enum to create a similar kind of 'fingerprint'
2. Then we write a random key ( using [GIUD].newGuid().toString() ) to a place in the registry. This acts as a 'salt' for our hardware profile: it is *technically possible* for the same registry values from hardware and os details in the registry - so we salt it using a very random key.
3. To perform our fingerprint we read the registry 'fingerprint' values and simply append them to a string. The guid registrykey is read and appended too. Then make a single hash key from it (using the SHA1 example in this thread). This acts like a pseudo hardware lock akin to the original finger print approach above but with less chance for failure which WMI introduces.
Using the above technique, the license key can not be hacked from the registry - even if you copy the GUID.
It CAN be recreated by knowing what the registry keys are which we use to compose it are, however since it comes from the \system\...\CurrentControlSet it uses a dynamic portion of the registry hive and therefore would not really be a viable crack. Of course, if you were that good you could just disassemble and remove jsr's to the fingerprint method in the first place!
Hope this sheds some light on the problems.
-
Re: C# - PC fingerprint (for program piracy protection)
That's very interesting. Not something we have come across at all - but you've got me worried. I would have a go at cracking it, but I can't reproduce it! Very strange. Presume you have tried the 'bare' code outside oyur application in case something in the app is conflicting?
Personally I would generally steer clear of the registry for any security related matters. There are lots of utilities that will "photograph" the registry and give you the changes before and after installing software, so the keys at least are easily known.
Well, there's always dongles.....
-
Re: C# - PC fingerprint (for program piracy protection)
The approach is the following:
1. Display a reg form into which the user enters company name and product code.
2. Calculate an MD5 using the BIOSSN, MACADDRESS. Send the MD5 and the info of step 1 to me.
3. MD5 the above and send them back as an unlock key.
When the user launches the reg form, sometimes BIOSSN is empty and/or MACADDRESS is empty, or both are returned.
The MD5 algorithm works with either empty or not BIOSSN, MACADDRESS (but returns the same when BIOSSN, MACADDRESS are empty). I chose these two because the software is targeted to corporate users (they all have NICs) and I use BIOSSN not CPUID or something else (modern).
My software runs well on both 2000Pro and XPPro.
I cannot tell my customers who run on 2k to upgrade to XP (their IT will freak out :mad: )
I don't like the registry HKLM solution, because I have seen problems on accessing HKLM keys when users do not have local admin rights.
I am thinking of writing a more "low level" routine to get those values.
Any ideas?
-
Re: C# - PC fingerprint (for program piracy protection)
Hmm... well you got me stumped. All I can say is that the original code I posted has worked perfectly for me every time. There may be circumstances in which it does not, but I have not come across them. I might have another look at it when I get time.
-
Re: C# - PC fingerprint (for program piracy protection)
All I can say is bloody brillant . I googed a few of security terms (looking for code like this) - and google brought me right here. Copy/paste in VS.Net - compile errors, then add System.Management.dll ref - compiles and WORKS!
Good explaination of software protection trade off's Brian. :thumb:
I used a CAD program that required a dongle, the dongle died and I couldn't work. Took it apart, left a note saying F* U in it - I hate dongles.
You can easily lock down much of the registry and WMI in Win03 - which would return those errors. You can get most of these values in native Win32 but then you'd have to step outside of .Net (but it would solve the protection problem).
I have code getting most of these ( Win32/C++/ATL )
The require connection to the network before your app can run is unacceptable to most people. I do my best programming on an airplane.
The SHA hash is the way to go - you get it for free and it makes the code unbreakable. Compressing all the data into an 8 bit hash has the flaw that if some of the data is predicitable(which I'm sure it is), you end up with more like a 4 bit hash. That's how 128 bit encryption was cracked (time has was predictable).
-
Re: C# - PC fingerprint (for program piracy protection)
adding a modicum to pixoluts excellent post, here is the C# version
VB Code:
using System.Security.Cryptography; // SHA.ComputeHash
using System.Web; // HttpUtility.UrlEncode
// add ref to System.Web.dll
string rSHA(string str){
ASCIIEncoding AE = new ASCIIEncoding();
SHA1 shaM = new SHA1Managed();
string sTmp = Convert.ToBase64String(shaM.ComputeHash(AE.GetBytes(str)));
return HttpUtility.UrlEncode(sTmp);
}
Note I change'd it to pass in whatever strings you want. I'll probably use CPU_ID and MAC Addr
I could write a web site that would let you register GUIDS (to enable cust code) - custs could connect to my site and get hash. I could charge say 5 cents for each customer I serviced. Not everybody wants to set up a web site to issue codes.
-
Re: C# - PC fingerprint (for program piracy protection)
Cool stuff. Glad it worked.
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by BrianHawley
The idea of having unique log-ons to a server is interesting, but what happens if the server is down? What about non-Internet apps or people with dial-up? What happens when you sell a hundred billion copies and overload your server?
Redundancy. Dial-up doesn't matter since you're only sending a few bytes (not entire applications).
I also doubt selling a crapload of copies will overload the server unless the server admin doesn't know what he's doing and/or the programmer create a huge amount of overhead.
Like I said, you'd only be transfering a few bytes verifying that someone's login.
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by kasracer
Redundancy. Dial-up doesn't matter since you're only sending a few bytes (not entire applications).
I also doubt selling a crapload of copies will overload the server unless the server admin doesn't know what he's doing and/or the programmer create a huge amount of overhead.
Like I said, you'd only be transfering a few bytes verifying that someone's login.
Hmm...
Well if I had bought, for instance, a word processor and it had to establish a dial-up connection and swap even a few bytes each time I wanted to use it, I think I would not be a happy customer. Particularly if I was using my lap-top on an airplane. But it's a free world. We can all protect our apps (or not) as we think best.
-
Re: C# - PC fingerprint (for program piracy protection)
Veeery good point Brian. Customers have very set expectations when it comes to app protection. High-end and specialist apps are EXPECTED to have a dongle or 'call to base' and be hard to install. A lot of customers actually LIKE this with their high end software as it validates for them the high cost of the software - good examples are high end 3D software packages like Houdini or management software like ShortCuts. Brian's point is valid - because a low end software package is not expected to have high-end security features to protect it. Its all relative and very much built in to the psychology of software consumers.
In the software we built using the authentication scheme above we were using it to enable web based services which were 'pay per use' so customers were very happy to have software which 'chatted' on the internet to validate it was authorized.
Note - they don't like getting feedback about the chats. We found that some of the errors which were raised that were network related were best ignored. We started out showing them to customers (like 'could not connect to server') but found later that since the software was not being used, the error was useless. Customers get the transport errors when they try to use the software - even if they have been going on all day before hand - thats the first they find out about it. Its all in the psychology...
-Joe
-
Re: C# - PC fingerprint (for program piracy protection)
Well put.
Use the appropriate tool for the job.
Don't use your Ferrari to transport 20 bags of cement and don't race your 18-wheeler (although there are some people who will do both!)
-
Re: C# - PC fingerprint (for program piracy protection)
I move that we go back to putting programs on cassette tapes - or better yet, punch cards - yes punch cards - that would stop piracy.
-
Re: C# - PC fingerprint (for program piracy protection)
I've got an old Commodore PET (1970s PC) with programs on tape. Still works! A whole 8 Kilobytes of RAM.
-
Re: C# - PC fingerprint (for program piracy protection)
paper tape was the bomb! 300 baud also!
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by BrianHawley
If you just cut and paste the code in the post at the top of this thread, it should work for you. You can then step through the code and see how it works.
Hello,
can you please help me do this. So I put this code in the program(forgot the name) as C#, now what, how do I make into a exe file?
using System;
using System.Globalization;
using System.Threading;
using System.Resources;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;
using System.Text;
namespace Whatever
{
public class Fingerprint
//Fingerprints the hardware
{
public string Value()
{
return pack(cpuId()
+ biosId()
+ diskId()
+ baseId()
+ videoId()
+ macId());
}
private string identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue)
//Return a hardware identifier
{
string result="";
System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
System.Management.ManagementObjectCollection moc = mc.GetInstances();
foreach(System.Management.ManagementObject mo in moc)
{
if(mo[wmiMustBeTrue].ToString()=="True")
{
//Only get the first one
if (result=="")
{
try
{
result = mo[wmiProperty].ToString();
break;
}
catch
{
}
}
}
}
return result;
}
private string identifier(string wmiClass, string wmiProperty)
//Return a hardware identifier
{
string result="";
System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
System.Management.ManagementObjectCollection moc = mc.GetInstances();
foreach(System.Management.ManagementObject mo in moc)
{
//Only get the first one
if (result=="")
{
try
{
result = mo[wmiProperty].ToString();
break;
}
catch
{
}
}
}
return result;
}
private string cpuId()
{
//Uses first CPU identifier available in order of preference
//Don't get all identifiers, as very time consuming
string retVal = identifier("Win32_Processor","UniqueId");
if (retVal=="") //If no UniqueID, use ProcessorID
{
retVal = identifier("Win32_Processor","ProcessorId");
if (retVal=="") //If no ProcessorId, use Name
{
retVal = identifier("Win32_Processor","Name");
if (retVal=="") //If no Name, use Manufacturer
{
retVal = identifier("Win32_Processor","Manufacturer");
}
//Add clock speed for extra security
retVal +=identifier("Win32_Processor","MaxClockSpeed");
}
}
return retVal;
}
private string biosId()
//BIOS Identifier
{
return identifier("Win32_BIOS","Manufacturer")
+ identifier("Win32_BIOS","SMBIOSBIOSVersion")
+ identifier("Win32_BIOS","IdentificationCode")
+ identifier("Win32_BIOS","SerialNumber")
+ identifier("Win32_BIOS","ReleaseDate")
+ identifier("Win32_BIOS","Version");
}
private string diskId()
//Main physical hard drive ID
{
return identifier("Win32_DiskDrive","Model")
+ identifier("Win32_DiskDrive","Manufacturer")
+ identifier("Win32_DiskDrive","Signature")
+ identifier("Win32_DiskDrive","TotalHeads");
}
private string baseId()
//Motherboard ID
{
return identifier("Win32_BaseBoard","Model")
+ identifier("Win32_BaseBoard","Manufacturer")
+ identifier("Win32_BaseBoard","Name")
+ identifier("Win32_BaseBoard","SerialNumber");
}
private string videoId()
//Primary video controller ID
{
return identifier("Win32_VideoController","DriverVersion")
+ identifier("Win32_VideoController","Name");
}
private string macId()
//First enabled network card ID
{
return identifier("Win32_NetworkAdapterConfiguration","MACAddress", "IPEnabled");
}
private string pack(string text)
//Packs the string to 8 digits
{
string retVal;
int x = 0;
int y = 0;
foreach(char n in text)
{
y ++;
x += (n*y);
}
retVal = x.ToString() + "00000000";
return retVal.Substring(0,8);
}
}
}
-
Re: C# - PC fingerprint (for program piracy protection)
I would respectfully suggest that before you start with code of this complexity, you learn the fundamentals of how to use Visual Studio .NET and how to generate EXE programs. There is a lot of help documentation included with Visiual Studio itself, as well as a lot of free information on the Internet. If you run into specific problems, then I'm sure if you post them in the appropriate places on this fiorum, people wil be glad to help.
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by BrianHawley
5) Keep security code isolated and encapsulated in different places - don't just call the same routine from different places. Checksum the EXE using a non-standard method. Have several layers of security that cut in at different and increasing time intervals - hacker breaks the daily one and sells your code, then the weekly one cuts in - he breaks that then the monthly one cuts in etc. etc.
Hi
Can you elaborate on this? What do you mean "security code isolated and encapsulated in different places"? Like have a real code class then a dozen 'empty' fn/cls that just forward to the real one?
Checksum - difficult in the .net obfuscation world
"Have several layers of security..." that would require more than once code right? I don't see how you can have diff checks for one reg code.
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by Malf
Hi
Can you elaborate on this? What do you mean "security code isolated and encapsulated in different places"? Like have a real code class then a dozen 'empty' fn/cls that just forward to the real one?
Checksum - difficult in the .net obfuscation world
"Have several layers of security..." that would require more than once code right? I don't see how you can have diff checks for one reg code.
Most hackers will break your protection by finding the block of code in your application that does the security, then modifying it or commenting it out.
If you have two (or more) completely separate code blocks that each independently do security, then the hacker might find one (and remove it) but not the other(s).
What I mean by layers, is that if one block checks security every time the program starts, and stops the program if it is pirated, then the hacker might find this block and remove it. But if there is a completely separate second block that only checks security, say every 9th hour, then he/she may not at first notice this and may release the program as 'hacked'.
But anyone who uses it will find it stops working after nine hours (preferably with a storm of false warnings about it being a hacked/infected version, to frighten-off any illegal user) . The hacker becomes aware of this and hacks the second block - but there is a third block that impliments security only on Friday 13th - and so on for as far as you want to go. You can keep a hacker tied up for a long time until he loses interest and his "client base" loses faith in the hacked version.
Not a war you can win against someone persistant and skilled, but there is no need to make it easy for them.
We have a message that pops up in hacked versions of our software that tell the user we will give them a free copy if they help us find and succesfully prosecute the person who gave them the illegal version. We have nailed 2 people so far.
-
Re: C# - PC fingerprint (for program piracy protection)
Hi Brian,
Really interesting, and long running !, thread.
I'm trying to implement a "low-end" license key and at first sight your fingerprint (with the SHA1 hash mod.) seemed ideal. However when I did some testing I found the return values were regularly changing and in particular I found, surprisingly, that Win32_Processor can change even when there has been no hardware change.
Have you or anyone else come across this problem ?
The answer may lie in the value WMI returns for Win32_Processor. For "convenience" here's what the MSDN docs less than helpfully say on the subject:
" Processor information that describes the processor features.
For an x86 class CPU, the field format depends on the processor support of the CPUID instruction. If the instruction is supported, the property contains 2 (two) DWORD formatted values.The first is an offset of 08h-0Bh, which is the EAX value that a CPUID instruction returns with input EAX set to 1. The second is an offset of 0Ch-0Fh, which is the EDX value that the instruction returns.
Only the first two bytes of the property are significant and contain the contents of the DX register at CPU reset—all others are set to 0 (zero), and the contents are in DWORD format. "
So that's perfectly clear, eh !
It's a while since I've hacked at assembler but I thinks it saying that what's returned depends on the status of the EAX register. This may account for the lack of consistency.
Appreciate any inspiration - on reflection maybe it'd be better to drop processor id altogether as I've also noticed from my download logs that some machines just don't return any value (maybe this is the security policy issue pixolit came up against). And of course the above doc only applies to x86 CPUs.
I'd appreciate views on what's the best fingerprint combination - your original concept was "the more the better" but given the above problems, I'd like to balance comprehensiveness with reliability.
There's also the question of giving weightings to fingerprint items and scoring the overall value against a threshold failure point - I believe this is how MS others do it.
Hope this keeps the thread going. In fact come to think of it this subject is worth a dedicated site !
Jon
http//www.fm-alive.com
-
Re: C# - PC fingerprint (for program piracy protection)
I've used this mechanism in my program licencing and it works pretty well.
I was worried that the fingerprint would change on every configuration change, so I only combine macID, motherboardID (only the serial#) and biosID (only the id code and serial#). I only resort to cpuID, diskID, or videoID if the default IDs return nothing (possible I suppose).
Only one of my 20 users has needed a new key so far (in 2 active months) because of a fingerprint change; I haven't found out exactly why yet though. If it becomes more frequent I'll have to look into building the fingerprint from something that changes less often - perhaps just the motherboard serial number only.
The more things you make it dependent on, the more unique and secure it may be, but the more likely it is to change frequently I suppose - it's a trade off.
But, does
identifier("Win32_BaseBoard", "SerialNumber")
always return a value ?
-
Re: C# - PC fingerprint (for program piracy protection)
A certain proportion of users will install a second copy on another machine and ask for a new code. That's just one of the drawbacks of this method, You have to use judgement if a user requests several codes in a short time and decide if they are honest or not. But at least you can limit each dishonest user to half-a-dozen pirate copies (or whatever you decide). They do not have the capacity to give away thousands.
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by batgurl
A certain proportion of users will install a second copy on another machine and ask for a new code. That's just one of the drawbacks of this method, You have to use judgement if a user requests several codes in a short time and decide if they are honest or not. But at least you can limit each dishonest user to half-a-dozen pirate copies (or whatever you decide). They do not have the capacity to give away thousands.
Hmm, I remember purchasing a game where it used something like this hardware validation method, and it only let your request a key 3 times per 2 months, that seems to be an effective method. :wave:
I mean seriously, how many people change their computer configuration over once each month? :ehh:
-
Re: C# - PC fingerprint (for program piracy protection)
That's a good idea. Limiting installs by time sounds fair.
You could also perhaps do something with upgrades. Only allow upgrades to the system with the most recently issued activation key.
If the program has an automatic 'check for updates over internet' facility, you could even build in automatic deactivation (or revert to demo version) - although that's a bit risky. You would need to be very sure your code was robust.
-
Re: C# - PC fingerprint (for program piracy protection)
Quote:
Originally Posted by BrianHawley
Yes, ok.
In DotNet they can always pull the code apart anyway if they want to break in!
That's not totally true. In that matter .NET can be just as secure as C++. All you need to do is precompile it to native code, after compilation. You can do this with Ngen.exe (The Native Image Generator).
In fact not only is it good for security, but also for the speed. People who claim that C# is too slow should just use this little program because it makes C# code as fast as C++.
By the way, there are a lot of people who always compile their code in Debug mode, and who forget to compile in Release mode when releasing software. This also makes a big difference in speed and in security too I guess.
-
Re: C# - PC fingerprint (for program piracy protection)
Unfortunately that's not true. NGEN still requires the original meta data to be available which makes it easy to read and disassemble. And if the NGEN'd assembly is not valid for the given machine - say compiled on x86 machine and run on x64 - then the original assembly is used instead. There are other conditions where the original file is used in place of the NGEN assembly but I don't recall off hand. The only thing NGEN is good for is a potential increase in load time. It has 0 benefit to run time since the code is JITTed exactly once by the runtime and runs with the same performance characteristics as an NGEN assembly. While Microsoft warns that NGEN assembly use might prevent the JIT from taking advantage of advanced scheduling and instruction ordering for the specific machine, in practice the NGEN code and JIT code are generally the same.
The only way to protect your assembly from prying eyes and modification is to use an assembly encryption system.
[advertisements snipped]
-
Re: C# - PC fingerprint (for program piracy protection)
Nice code. That's what I was looking for. I do have one suggestion though; consider removing the macId() since I ran into a problem. I have a wireless card and a Lan card in my laptop and some days I use either. The Fingerprint I received was different because of this and my code did now work.
Thanks
Nick
-
Re: C# - PC fingerprint (for program piracy protection)
This is a very nice code.
I am somewhat new to this, so sorry if the question is a bit basic.
If I put the check on the fingerprint as follows. The idea is: if the person tried to run the program, the person would get a windows that would allow him or her to generate the fingerprint.
if (fp.Value() == "some number")
{
Application.Run(new frmSTABL());
}
else
{
Application.Run(new frmActivationMsg());
}
then the user will have to reinstall software he/she may have already downloaded and installed. Is there a better way?
Thanks,
RS
-
Re: C# - PC fingerprint (for program piracy protection)
After thinking about this, it seems that the idea is to use the encryption functions of .NET so that all I have to send the user is a file with the encrypted computer fingerPrint. If I am not correct, I hpe someone will point me in the right direction.
Thanks.