-
Jun 21st, 2003, 08:41 AM
#1
Thread Starter
Fanatic Member
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);
}
}
}
Last edited by BrianHawley; Jun 21st, 2003 at 08:50 AM.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Jul 7th, 2003, 10:49 PM
#2
Addicted Member
-
Jul 12th, 2003, 10:26 AM
#3
Fanatic Member
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.
Don't Hate Me Cause You Ain't Me
-
Jul 12th, 2003, 12:52 PM
#4
Member
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.
i will be come a better programmer some day! thanks to vbforums.com
-
Jul 13th, 2003, 11:01 PM
#5
Addicted Member
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....
ßädbö¥ Rü£z
ICQ # : 204178672
AOL SN : Badboy9jan
badboy9jan<img src="images/smilies/s...g" />gmail.com
-
Jul 15th, 2003, 08:52 AM
#6
Thread Starter
Fanatic Member
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.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Jul 26th, 2003, 06:22 AM
#7
So Unbanned
Dongles aren't even secure.
-
Jul 27th, 2003, 01:05 AM
#8
Thread Starter
Fanatic Member
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.
Last edited by BrianHawley; Jul 27th, 2003 at 01:10 AM.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Mar 3rd, 2005, 07:16 AM
#9
New Member
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
-
Mar 5th, 2005, 12:59 AM
#10
Thread Starter
Fanatic Member
Re: C# - PC fingerprint (for program piracy protection)
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Mar 7th, 2005, 01:54 AM
#11
New Member
Re: C# - PC fingerprint (for program piracy protection)
Originally Posted by BrianHawley
Cool!
Thx, Brian.
But my question is still open
What happens if you multiply a char value within C#?
Rgds
SolutionDeveloper
-
Mar 7th, 2005, 03:31 AM
#12
Thread Starter
Fanatic Member
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.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Mar 7th, 2005, 04:22 AM
#13
New Member
Re: C# - PC fingerprint (for program piracy protection)
Yes, it does. It's excatly what my routine does as well...
Rgds
SolutionDeveloper
-
Mar 7th, 2005, 05:22 AM
#14
Thread Starter
Fanatic Member
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.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Mar 16th, 2005, 07:54 AM
#15
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?
I don't live here any more.
-
Mar 17th, 2005, 01:41 AM
#16
Thread Starter
Fanatic Member
Re: C# - PC fingerprint (for program piracy protection)
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!
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Mar 17th, 2005, 04:07 AM
#17
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.
-
Mar 17th, 2005, 04:09 AM
#18
Re: C# - PC fingerprint (for program piracy protection)
Yep, nice one
I don't live here any more.
-
Mar 17th, 2005, 04:33 AM
#19
Re: C# - PC fingerprint (for program piracy protection)
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.
Last edited by wossname; Mar 17th, 2005 at 04:37 AM.
I don't live here any more.
-
Mar 18th, 2005, 05:50 PM
#20
New Member
Re: C# - PC fingerprint (for program piracy protection)
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
-
Mar 19th, 2005, 01:05 AM
#21
Thread Starter
Fanatic Member
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.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Mar 29th, 2005, 12:28 AM
#22
New Member
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').
-
Mar 29th, 2005, 01:03 AM
#23
Thread Starter
Fanatic Member
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!
Last edited by BrianHawley; Mar 29th, 2005 at 01:17 AM.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Mar 29th, 2005, 01:21 AM
#24
New Member
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
-
Mar 29th, 2005, 02:56 AM
#25
Thread Starter
Fanatic Member
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.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Mar 29th, 2005, 06:49 AM
#26
New Member
Re: C# - PC fingerprint (for program piracy protection)
Last edited by pixolut; Mar 29th, 2005 at 07:07 AM.
Joe Cincotta
http://www.itokhome.com
http://www.pixolut.com
-
Apr 3rd, 2005, 12:23 PM
#27
New Member
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?
-
Apr 4th, 2005, 03:02 AM
#28
Thread Starter
Fanatic Member
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.
Last edited by BrianHawley; Apr 4th, 2005 at 03:23 AM.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Apr 5th, 2005, 02:32 AM
#29
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();
}
-
Apr 5th, 2005, 06:32 AM
#30
Thread Starter
Fanatic Member
Re: C# - PC fingerprint (for program piracy protection)
Originally Posted by mendhak
This method works only in XP and 2003:
Is anybody running any other version of Windows these days ?
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Apr 17th, 2005, 09:07 AM
#31
New Member
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
Alexandros Zountas
Odyssey Software Europe
-
Apr 18th, 2005, 12:59 AM
#32
Thread Starter
Fanatic Member
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?
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Apr 18th, 2005, 01:56 AM
#33
New Member
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.
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:
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
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.
Joe Cincotta
http://www.itokhome.com
http://www.pixolut.com
-
Apr 18th, 2005, 02:26 AM
#34
Thread Starter
Fanatic Member
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.....
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Apr 18th, 2005, 03:41 AM
#35
New Member
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 )
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?
Alexandros Zountas
Odyssey Software Europe
-
Apr 18th, 2005, 03:59 AM
#36
Thread Starter
Fanatic Member
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.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Apr 18th, 2005, 09:27 PM
#37
New Member
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.
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).
-
Apr 18th, 2005, 10:22 PM
#38
New Member
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.
-
Apr 19th, 2005, 05:26 AM
#39
Thread Starter
Fanatic Member
Re: C# - PC fingerprint (for program piracy protection)
Cool stuff. Glad it worked.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Apr 25th, 2005, 03:42 AM
#40
Re: C# - PC fingerprint (for program piracy protection)
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.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|