|
-
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)
-
Jan 5th, 2006, 02:12 AM
#9
New Member
Re: C# - PC fingerprint (for program piracy protection)
 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.
-
Jan 7th, 2006, 01:18 AM
#10
Thread Starter
Fanatic Member
Re: C# - PC fingerprint (for program piracy protection)
 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.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Apr 2nd, 2006, 02:49 AM
#11
New Member
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
-
Jul 14th, 2006, 10:19 AM
#12
New Member
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 ?
-
Mar 3rd, 2005, 07:16 AM
#13
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
#14
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
#15
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
#16
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
#17
New Member
Re: C# - PC fingerprint (for program piracy protection)
Yes, it does. It's excatly what my routine does as well...
Rgds
SolutionDeveloper
-
May 1st, 2005, 03:13 AM
#18
Thread Starter
Fanatic Member
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.
Brian
(Fighting with the RightToLeft bugs in VS 2005)
-
Jul 15th, 2006, 12:38 AM
#19
Junior Member
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.
-
Jul 15th, 2006, 06:25 PM
#20
Hyperactive Member
Re: C# - PC fingerprint (for program piracy protection)
 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.
I mean seriously, how many people change their computer configuration over once each month?
-
Jul 17th, 2006, 03:35 AM
#21
Junior Member
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.
-
Dec 28th, 2006, 11:18 PM
#22
New Member
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
-
Jan 12th, 2007, 11:03 AM
#23
New Member
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
-
Jan 12th, 2007, 02:15 PM
#24
New Member
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.
-
Apr 5th, 2007, 07:19 PM
#25
New Member
Re: C# - PC fingerprint (for program piracy protection)
Hello, My Name Is Mr. Chetachukwu I Will Really Like To Know Why Your Site Is Not Showing Me Where I Will Send Sms Message Please Advis Me Urgently
-
Apr 8th, 2007, 09:14 AM
#26
Hyperactive Member
Re: C# - PC fingerprint (for program piracy protection)
 Originally Posted by chetachukwu
Hello, My Name Is Mr. Chetachukwu I Will Really Like To Know Why Your Site Is Not Showing Me Where I Will Send Sms Message Please Advis Me Urgently
What?
And thanks again for this code, it's great. As I said before (as ..:RUDI:..), very effective.
» Twitter: @rudi_visser : Website: www.rudiv.se «
If Apple fixes security flaws, they are heralded as proactive. If Microsoft fixes a security flaw, they finally got around to fixing their buggy OS.
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
|