unique system ID

Does anybody know of a good way of uniquely identifying a computer in Windows 95 / Windows NT? (must work under both OS)

What I am looking for is a way to make a program run on one machine only via a registration file that contains system specific data. The data shouldn't change frequently because that would upset my users! (imagine adding some RAM to your system and some programs stop working!) On the other hand, the user should not be able to easily modify the underlying values, because that would break my "copy protection"... (users will mostly be computer science students! *sigh*)

The best thing would be to retrieve some hardware information from the bios, but that seems to be very hard or close to impossible from standard Win32 programs?? Here are some things I have thought of, but I'm not quite happy with them:
a) Windows user name / logon name -> can be changed easily
b) list of drives and types -> might also change even for fixed drives (I have a hard drive with 6 partitions in a 5½" slot and can remove it at will).
c) serial number of drives -> same problem, also might be too easily "faked"
d) RAM size -> changes too often
e) making a secret registry entry -> too easily detected (e.g. with tools like regmon)
f) creating a hidden file somewhere -> too easily copied :-((

Of course I could use some wild combination of all of the above (e.g. create a secret file somewhere and store the creation date/time in the registry for verification) which would make it a real pain to break the protection, but it I'm afraid it would also be a real pain to program it and it would be somehow messy...
Also, I would "prefer" the program to keep working even if Windows is reinstalled...

I really don't know what to do - any helpful ideas?? I'll increase the points to 200 for a "very good" solution that is not some weird patch...

Thanks a lot!!
Who is Participating?
rwilson032697Connect With a Mentor Commented:
There is a whole list of components on the Delphi Super Page that will do this for you (mostly free, some with source)


Take your pick and save yourself the hassle - its much easier.



I've got a FAQ here in HTML format that I ran across somewhere on the Net (can't remember where though).

If you give me you email address I'll mail it to you. It might have some, if not all of the answers you are looking for.

I'm sure others would like to see the FAQ, especially if they pay for the question ( assuming the answer is accepted)
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

I would like to stress that this FAQ is not my work. Unfortunately I can not remember which site I d/l the original HTML file from. I left the file and all text in it exactly as I d/l'ed it except for converting it to TXT format.


        Anti cracking FAQ
How to make cracking your programs a little harder


Finding out that the program on which you worked for months or
years has been cracked can really hurt and demotivate.
For me as a Shareware programmer, the reason has never been that
I've lost a few cents (I don't want to do propability
calculations here, it might hurt even more..), no, it was simply
that I've always tried to hold my programs as cheap as possible
to make them affordable for everyone, even for students or
freeware programmers.

Somehow I can understand the fascination of cracking programs (if
you are absolutely intolerant about software crackers and
hackers, please excuse, but one of my educations is
Psychotherapy, and I'm always searching for reasons...) -
cracking a restricted software program must be like solving a
(sometimes very tricky) riddle, and you might get addicted to the
feeling of solving them (I've found that when I saw my
grandmother doing crossword puzzles all over the time for some
months). The problem is (but at the latest, now we come to the
undoubtedly illegal part of the "game"): it doesn't really
satisfy the cracker if he is the the only one who knows about his
"genius"...thus, he has to spread the news. He has to publish his
"crack" (just see most crack packages: in most cases they just
consist of: 1. the cracking utility 2. a short description 3. a
big file containing claims that the producers are nothing less
than the greatest ones on Earth and that the cracked program is
another one which could not stop them with "its lame protection
But now the fun is completely over: by giving out this (let's try
to be fair: "study of feasibility") to other people, by spreading
it via Websites, newsgroups, mailing lists, anonymous FTP, CDROM
"abonnements" and whatever, they clearly damage the business of
everyone who puts time and energy in their software product. Even
if we assume that typical crackers wouldn't have bought your
product under normal circumstances: spreading the "crack" IS
criminal and no one could claim that none of the receivers or
downloaders would never have bought it. It's just like if someone
hands out copies of the key to your car on the marketplace - and
it doesn't really matter if he does that for money or not.

In earlier days, I have never put real energy in protecting my
programs against cracking, but after finding several cracks for
them around, I thought to myself: why make it too easy? As a
programmer, of course I know that no - really: NO! - program can
ever be crack-safe, and I know that of every interesting program
sooner or later cracks (or at least pirated or illegally copied
versions) will be around, but at least I could try to avoid the
worst mistakes.

Most of the typical 'high language' programmers don't know
Assembler anymore, so the 'protection ideas' they use are in most
cases quite weak.
I don't know much about Assembler myself, so I decided to open my
eyes and started to collect anti-crack protection tips wherever I
found them. Also I did my best to "learn from the other side" ..
many of the tips you can find here I've found by studying the
typical cracking techniques, the various "cracking guides" around
the web and by reading protection tips given even by professional
crackers themselves (some of them generously give us tips to
increase their challenge). Well, I hope I've learned my lessons
well enough, but also want to share my experiences with you on
this page.
Some rules given here were already stated in various essays on
other sites, but are listed here for completeness. Many of these
apply especially to windoze, but can be "ported" to other OS'es
or anywhere else.


   * This FAQ is brand new. If you think that I've missed some
     points or useful tips a typical Delphi programmer could
     easily add to his/her programs to improve protection, please
     let me know. If you allow it, I'll add it here, otherwise
     I'll inform you about my experiences with it.
   * Don't ask me questions - might be that I'm simply too
     overburden to answer.
     1) As mentioned, I don't have much knowledge of the
     low-level stuff.
     2) I can't send you demo sources, since I don't have
     anything ready for a publication. If I have something, you
     will read it here.
     3) Finally, I will not provide anyone with any of the URLs
     where I've found (or found out) some of these tips. Please
     understand, but this is a site dedicated to programming, but
     not to provide "step-in's" to available cracks or even to
     "Cracker hunting". Find more generic tips about
     crack-protection at my Delphi Tips page.

But finally, here is ..
How to make cracking your app a little bit harder:
(tips are not sorted by importance)

   * Never use meaningful procedure names such as

         function RegistrationOK: Boolean;

     How intelligent and complex your code inside this function
     might ever be - an experienced cracker will just take about
     10-20 seconds to remove it. Believe it or not.
     Alternatively, place some required code for your program in
     such a function. If the cracker disables the function, your
     program would produce incorrect results, for example.

   * Never use meaningful file names such as License.Dat. Why,
     you say? Please start reading here.

   * Play with asymetric encryption. Just using unusual filenames
     is often not enough. Good encryption, of course, could keep
     the cracker busy for months (if he likes).

   * Add long delays. Don't warn the user right after a violation
     is made. Wait later, maybe until the next day or two
     (crackers hate that).

   * Add short delays. Pause a second or two after a password
     entry or to your other checking routines to make brute force
     cracking unfeasible. Simple to do, but rarely done.

   * Use checksums in DLL's and in the EXE. Have them check each
     other. Far away from "safe", but it just makes it harder to

   * Self-heal your software. You know, things like the error
     correction modems and hard drives use. The technology has
     been around for years, and no one uses it on their software?
     The best thing about this is that if the cracker used a
     decompiler, they may be looking at a listing that is no
     longer valid.

   * Patch your own software! Change your code to call different
     validation routines each time. Beat them at their own game.

   * Store serial numbers in unlikely places like as a property
     of a database field. Often heard and read: "..give it a DLL
     file name and store it in the System directory." Too often
     heard, don't use it. ;-)

   * Store serial numbers in several places.

   * Don't rely on the system date. Get the date of several
     files, like SYSTEM.DAT, SYSTEM,DA0 and BOOTLOG.TXT and
     compare them to the system date. Require that the time be
     greater than the last run (but keep in mind that many users
     might do Y2K-checks these days).

   * Don't use literal strings that tell the user: "Sorry, but...
     (whatever)." These are the first things to look for. Build
     strings dynamically or encrypt them.

   * Flood the cracker with bogus calls and hard-coded strings.
     Decoys are fun.

   * Don't use a validation function. Every time you validate the
     user, write your validation code inline with the current
     process. That just makes more cracking for the cracker and
     bewares of just NUL'ing out your routine.

   * Use "reserved" names. When using hard-coded keys or
     passwords, make them look like program code or function
     calls (i.e., "73AF" or "GetWindowText"). This actually works
     very well and confuses some decompilers.

   * No "disabled" features. If your program doesn't save data in
     "crapware" edition, don't include a "grayed" menu item. No
     saving means no saving. That's it.

   * Avoid nags. The only way to tell the user that he is
     unregistered should be in the "about" dialog. This latter
     should be created dynamically for security reasons. 2
     reasons: some programmers have the philosophy that
     nagscreens are making enemies among your customers, which
     would then really be very stupid. The possibly more
     important reason is that nagscreens invite
     reverse-engineering your code and often directly leads to
     your protection code.

   * Update often. Frequent updates mean: frequently changing
     code, so the typical (simple) crack which is just patching
     hard-coded byte positions, will possibly already be outdated
     when published. Also prevent uploading them to public
     servers, so that you have better control about where your
     app sits around and people don't find older versions the
     cracks can still use. Yes, this doesn't prevent pirates from
     including the version to the crack package, but IF they do
     so, you can at least contribute to filling up their

   * Finally, take some time to think about protecting your
     software. Is it really worth the protection? Wouldn't it be
     better to improve your software, rather than improving
     protections? The problem of protecting software vanishes if
     no one will use your software. Don't overestimate your
     work's "importance to the world".

More tips you might take into consideration:

   * Use a serial which is several KB long of arithmetical
     transforms, to drive anyone trying to crack it insane. This
     makes a keygenerator almost impossible - Also, brute force
     attacks are blocked very efficiently.

   * Caution with the Runtime libary! Use it fully when writing
     the beta versions, in the final release rewrite some
     functions at least to make crackers life harder.

   * Mangle data. Protection that mangles data is usually a good
     Example: Imagine a charting program .. e.g., just disabling
     printing and later on enabling it basing on some
     registration# is the most often committed suicide. Let your
     thingo print. When creating data structures for printing,
     mangle them in some way. Unmangle them just before printing,
     using reg# or something other for that purpose. Even more,
     make this mangling subtle. Assume that you've got a pie
     chart to print. Don't alter anything, but add some not too
     big random numbers to values of data series - this is
     mangling then. The chart will look "not that bad", but will
     be otherwise unuseable (if the changes are random and on the
     order of 20%, for example). Finding such protection, if its
     connection with reg# is not self-evident can take much time.
     One has to delve inside your data structures and find that
     dreaded mangling and unmangling code.

   * Traps. A method I'm not sure about, but I have heard some
     apps are using it: do a CRC check on your EXE. If it is
     modified then don't show the typical error message, but wait
     a day and then notify the user using some cryptic error
     code. When they contact you with the error code, you know
     that it is due to the crack. Be aware: such traps could also
     be activated due to virus infection or incorrect downloads.
     Imagine the possible aftereffects if you are blaming your
     potential customer for software piracy.
   * Don't rely on "EXE-packers". For almost any tool which
     compresses EXE files (Shrinker, WWPack32, NeoLite - to list
     the most popular ones) there's an uncompressor around, so
     compressors capable for software-protection should at least
     support configurable encryption. Unpackers for the above
     (and other) tools are not very wide-spreaded, however, don't
     rely on them as your program's one and only "protection"!

Advanced tips ..given by assembler freaks.

   * The rcr/rcl trick
     If a rcr/rcl is performed on a value, it becomes much more
     of a pain to crack - you can't reverse it with by negating
     it's effects without knowing what the value of the carry
     flag was before the original operation. If the carry flag is
     created as a result of some other pain in the neck
     operation, you are probably onto a winner.
   * Stick conditional jumps in. Everywhere.
     Conditional jumps are not fun to reverse engineer. No loops,
     but jumps which conditionally bypass/include portions of
     your wonderful key manipulation code. There is no easy
     inverse operation to be performed here.
   * Use portions of the code as magic number tables.
     (preferably critical sections). You have no idea how
     annoying this can be, if you're like most crackers and like
     to change things around using softice (a popular cracking
   * Play with the cracker's mind.
     This one is fun :-) Stick series of nops in, as though you
     were doing self-modifying code (oh my god! what the heck!
     nops? Aha! Self-modifying code! Idiot spends next three
     years trying to find the code that should be there.). Pepper
     the code with junk instructions. Cut the code up into little
     pieces and put them all over the executable, with
     (preferably conditional) jumps between them. - Anything
     which you would find a pain in the neck.
   * Detect SoftIce. Early.
     Now crash the computer. You can crash a pentium or a pentium
     with MMX even without a vxd by the opcode: F0 0F C7 C8
     (illegal form of cmpxchg8b instruction with lock prefix).
     Beyond that, we have to resort to the tried and true
     methods. Using a vxd, take the CPU out of protected mode.
     Windows doesn't like that. Wonder why? .. On the other hand,
   * Don't loose too much time on writing anything that will kill
     disassemblers or debuggers.
     Doing it is worthless, believe me, people who made them or
     others will soon find the way around, so shift your interest
     to more important stuff. Just do things which are easily and
     fast to afford, like the above tip.

Special on Delphi VCL cracking
Quoted from a helpful cracking tutorial - just read and learn
from it!

"Let's learn something about the innards of new Borland's
programming tools. This knowledge will allow us to speed up
cracking sessions, as will teach shareware programmers who use
Delphi to be more careful and not to happily expose their
'secrets' to curious eyes B) [..]

VCL stands for "visual component library", a library used by
recent Borland visual languages as Delphi and BC++ Builder.
These environments use a proprietary resource format, that appear
as 'RCDATA' when listed by Resource Workshop. These resources
contain 'forms'. In Delphi jargon, forms are the windows of the
program. All the info about their design is stored there. When a
typical Delphi app is starting, the initialisation code creates
the forms, loading the required information from the resources.
Sometimes this loading is deferred - forms that aren't used very
often are created and destroyed as needed.
This system is the best and the worst of Delphi. It allows a very
fast way of programming but, for full-length apps, it can slow
down the loading.

The really interesting part of this information is that the
address of the routines - called in response to user interactions
with the elements of the form - are bound at run time by name. So
knowing these names we can find the appropriate addresses!

If you have cracked any Delphi apps, you have surely experienced
the long chain of calls inside the library, from the breakpoints
on the API calls to the "do something" code. I hoped that these
addresses could help in pinpointing the relevant code."

[..describes his installation of a quite well-known Delphi-writen
application..] I cracked it completely and without problems, as
you are about to see :=) After first installation the weeks
passed and I hadn't had the time to work on it... when I started
it, I found a nasty 'Your evaluation period has expired' message

The first step is to gather the information about the target exe
with a resource or form spy tool. You may be tempted to
investigate TVALIDATORDLG, the form where the user name and
registration key is obviously input. But all you'll find is a
mere dialog. The real work is accomplished from its caller:
TSPLASHFORM. This is the nag window that appears at the beginning
of the program, as well as when it's shutting down and from the
Help->About menu.

You can select TSplashForm and look at the text representation of
it. A lot of information about the buttons and labels will
appear. Let's concentrate on the following part, near the end:

  object RegButton: TButton

    Left = 200

    Top = 176

    Width = 97

    Height = 25

    Caption = 'Register'

    TabOrder = 1

    OnClick = RegButtonClick


What's that? This is the button with the caption "Register". You
can see its size, position... and something with a suggestive
name: "OnClick". "OnClick" tells us the name of the routine
invoked when the user presses this button. Once we have the name
(yes, "nomen est omen" :) we can search for the address of this
routine. This is because the routine is bound to the button at
run time by name.

Using a hex editor, I looked for "RegButtonClick" and I found it
twice. The second occurrence is the resource itself, the first is
within an address table:

000A4990 ____ ____ ____ BC57 4A00 0E52 6567 4275 ______.WJ..RegBu

000A49A0 7474 6F6E 436C 6963 6B__ ____ ____ ____ ttonClick_______

Now look at the magic numbers before the name. There is a byte
('0E') indicating the length of "RegButtonClick" (14 characters)
and before that an address: 004ABC57.

Some disassemblers seem to think that file is too long and it
doesn't disassemble this portion of the exe correctly - however,
with a special tool we can bpx on this and... right! It stops at
the point just when we push the button.

A couple of instructions forward you'll find a CALL. Tracing into
it you'll find a "standard stack frame" in 44ECC8:

0044ECC8 55     push ebp

0044ECC9 8BEC   mov ebp, esp


This is the kind of thing expected at the beginning of a high
level routine, made by the application programmer. We have
avoided the whole chain of library calls through the VCL from
Windows notifications, and landed in the right place!
From this point, there are some calls you can easily test by
setting breakpoints on them - you'll find that their purpose is
to show the dialog asking for the user name and registration key.
Then, the key is calculated from the user name and compared with
the one the user entered. You can enter the name you choose, and
anything as the key, after BPXing 44ED69. Here, a call to a
routine compares two strings. D EDX will show the fake key you
entered and D EAX will show the correct calculated key. Easy,
isn't it? A ten minute crack by a beginner!!

[description about spying the key generator routine comes next.
It's been an average routine of about 10-20 Object pascal code

How this way of cracking can be avoided?

Read my tips above. The basics are: don't use automatic methods
created by double clicking on the button or the object inspector.
Write your code somewhere else in your program, preferably in
another module, and bind it to the button using code such as:

  RegButton.OnClick := RegButtonClick;

Of course you'll need to enter this code after the form is
created and before it's called. Best if it's rounded by a lot of
unrelated stuff. This won't necessarily prevent your program from
being cracked of course, but things will not be as easy as you
have seen in the lines above O:)

Notes on registration numbers
(if you can't avoid them)

   * balance between security, feasiblity, programmability and
     end-user headaches
   * Too long, non-alphanumeric Reg#'s tend to be continuously
     entered badly. Think about requiring to enter a verification
     field (as commonly used with passwords) or, at least,
     provide a "non-persistent" Reg# entry field so that the user
     will rewrite the Reg# each time, possibly correctly at last.
     Many people will just "glance-compare" the entered Reg# and
     the one (possibly) emailed to them, arriving at the final
     thought that they did enter it correctly, whereas the font
     is too small or they are too tired to notice that this '1'
     and 'l' have been interchanged (in a reg# like
     'l83jjd_0)pH1lTe' )
   * Refrain from any user feedback. The Reg# entry box should
     accept strings of any length, without any validation. Don't
     give crackers the knowledge about the type of your Reg# - if
     you do "online-verification" which shows that it's 10 chars
     long or that is contains only uppercase chars helps - so
     don't help them!
   * Calculate the number of potential users! There's nothing bad
     like if you have to update 9,999 users because you didn't
     expect that there might be 10,000 of them and have to shoot
     out a new version which is capable for these Reg#'s...
   * If your Reg# is 10 numbers long, there are 10^10 possible
     Reg#'s. But since your app might find let's say only 10^4
     (10'000) users, you should invent an algorithm that assigns
     each one of 10^4 users one of 10^10 reg#'s, and does it
     somewhat uniformly. This prevents people and programs (some
     .vxd based "macro" players, for example) to be used for
     brute force approach. If there are only 10^4 users and you
     allow 10^9 "valid" Reg#s out of 10^10, on average each 10th
     Reg# tried brute-force will be valid, whereas on the case of
     10^4 prospective users, that many valid reg#'s and space of
     10^10 Reg#s, on average only each 10^6th Reg# tried brute
     force will be valid. Ever calculated how much time it would
     take to brute-force search 10^6 numbers, even using a fast
     machine and extremenly fast macro player (keystroke
     generator simulating Reg# entry and checking for results)?
   * the assignment operator that assigns User# to Reg# shouldn't
     be trivial, and it's implementation should be done in
     Assembler by someone experienced both in Maths and
     Assembler. Remember that Delphi still allows you to directly
     use ASM code in your source! Then, check your operator.
     create graphs of how it works. Understand your own work,
     especially its drawbacks and vulnerabilities
   * Be inventive. Don't use anything that seems simple, quick
     and effective unless you've come with something like
     Einstein's relativity theory, your approach is yes, simple,
     yes, quick, but no, not effective, and yes, easy to crack.
     I'm sorry, but we aren't geniuses and developing a good
     protection scheme takes some time.

Just some thoughts..

    Again: please e-mail me if you have tips or suggestions !
    If you want to support my work on this page or simply say
 "thanks" for opening my treasure box to you, I'd be happy if you
                  would register one of my apps!
   Based on your support, page will be updated frequently! Last
                        update: 29-Sep-98

        Copyright ) 1998 by Richard Fellner. All rights reserved.
                                                 [[Image] /10'98]
[Image]       Do not copy to other sites or include in commercial
          compilations without the written authorization from the

Ronald112197Author Commented:
hmmm.... thanks Gerhard - that was quite an interesting article and I might use some of the tips in my program - unfortunately, it did not relate to the question at all !!! It was useful, though, and I'd like to give you some points. I posted an extra question titled "anti cracking tips" for you and I'll accept the answer there.

So why does the article not work for me? The "specific problem" is that I'll have a "large" number of users (~20-50) who KNOW EACH OTHER. None of the above tips keeps someone from installing the program on - let's say - 30 computers and using the same key on each one. We all know the trick... "could I borrow the installation CD and the key?" "Sure, no problem!"

Due to the limited number of users, I can "afford" creating a "custom registration file" that will work for one specific computer only. That's what this question is all about!

Any ideas?
Try to use last 6 word on GUID generate on computer when install you program.
Ronald, you are not alone.  This question gets asked every few months.  There is no answer.  (It curretly is being asked on the C++ area where some less experienced experts have almost convinced the poor guy that there is a suitable answer.  Sorry but there is not.)  There is no unique ID in the computer that is obtainable.

If the computer has a network card, then the you can obtain a unique ID from it.  No two cards in the world will have duplicate IDs, but not all computers will have network cards.  

People in this possition often make do using the hard disk's volume ID.  This is not 100% unique and may be changed by the user, however.
GUIDGEN makes a "globally unique" identifier.  Part of its alogrithm is using the CPU serial #.  I don't know how to get this.  You would probably have to crack GUIDGEN (hope it doesn't have all that stuff in the previous post) and/or have some advanced knowledge of the intel architecture.
nietod is quite right there is no 100% safe method. Although, using a hardware key such as a dongle can offer a higher degree of protection. Most people in your situation employ one or a combination of the volume id, ip address, and the network card (if you have one). Another method is to write a unique id in the slack space after an executable (fseeking passed the end of the file) So if the file is copied the id is changed. Under UNIX you can access the manufacturers information on the hard disks. But not under 95 or NT, unless you write your own driver. So im afraid you were on the right track all along. All we can do is confirm this.

Given that no solution is 100% safe. May I suggest you adopt a solution that is easy to maintain. Create a encryption mechanism for the  "system specific" items you wish to use to identify the machine. Encode into your program a method of deciphering this information and verifying it to be correct.  For each machine create a  "licence file" which contains this information (the key). This can be a simple file placed anywhere on the machine. (Often this is simply an ascii file in the root directory, and not protected at all).  Create a separate program, solely under your control, that given the appropriate data, will encrypt it and generate a licence file.

This method is far from perfect, but allows you to generate licences very quickly for any machine.

Ronald112197Author Commented:
sorry, I'm in a hurry right now... what is GUID(GEN)? How do I get/create that value and how Do I stop people from duplicating it?

Which C++ question are you talking about? If they "almost" have the "poor guy" convinced, there might at least be some useable ideas... is it "number of motherboard"? Lots of nice ideas, but none of them work! *g* (all would be nice in DOS, but nothing works in Windows!!) If that's the question you're talking about, then the comment suggesting that the poor guy's in wayyy over his head might be right.
I guess/hope I'm not. I just don't know what the "smartest" way of doing this would be...

arunm: Thanks for your suggestion, but there's NOTHING in it I didn't know before, so I'm reluctant to give points for it.
I know that there is no 100% solution, but I'd like to find something better than the ideas I mentioned above. Isn't there anything nice in the registry? (windows CD-key? (the one displayed in system info)/reg.#?/installation date? Maybe use the timestamp of the Windows-Folder? *g*) I know there are "tools" published by PC-magazines that give all kinds of information about the system hardware. How do they work? Those programs are NOT device drivers!

I'm getting new ideas while I'm writing (this seems to be a productive discussion!) so I'm hoping that somebody has done something like this before or thought about it before (especially if it's asked a lot) and knows something I might come up with in 3 weeks... unfortunately, I need to implement this by next week :-((

P.S.: Does anybody know of a way to determine which logical drives reside on ONE physical drive? I could use total hard disk size of the physical disk my program is on, but the first PC where that might fail is my own *ggg* (I have a removable hard disk).
I am just looking for creative input here... best answer will get the points! (should be something I haven't mentioned yet *bg*)

Oh btw, for anyone who cares: I'll use RSA to encrypt the license info with 512 or 1024 bits key length. "Public key" is secret *g*, private key for decryption is stored in program - so this is what arunm suggested, but it was planned all along). There's little danger of somebody breaking the code, but that doesn't help much if they can simply "fake" the data I'm verifying... would be something like Alcatraz with a little back door and the key lying on the table *g*

Thanks a lot for all your comments so far!
Ronald112197Author Commented:
P.S.: the windows-CD-key I mentioned seems to be stored in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Productid.

hmmm... I wonder if you can simply change that value without annoying Windows? Same for "InstallDate" *g* -does anybody know if these values are available in Windows95?
just a suggestion (not even sure if it works):
since you mention the registry... how about these registry values?? They look very promising to me, but @ the moment, I can't tell which ones are available in Windows 95. Most of them should be there, though! I'm not sure if the user can modify them, but I guess most people wouldn't try because that could (seriously) affect system performance (? I guess). I also guess that I personally wouldn't mess with these values (at least not on my own computer!)

Here we go:

"Component Information"=hex:00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
"Identifier"="AT/AT COMPATIBLE"
"Configuration Data"=hex(9):ff,ff,ff,ff,ff,ff,ff,ff,00,00,00,00,02,00,00,00,05,\

"Component Information"=hex:00,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00
"Identifier"="x86 Family 6 Model 3 Stepping 4"
"Configuration Data"=hex(9):ff,ff,ff,ff,ff,ff,ff,ff,00,00,00,00,00,00,00,00
"Update Signature"=hex:00,00,00,00,33,00,00,00


.. [all kinds of weird stuff *g*] ...

.. [more weird stuff *g*] ...


"Component Information"=hex:60,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,ff
"Identifier"="b94abd6b-a5ff3583-A" <=== HOW ABOUT THIS ONE?? I wonder which ones of all these funny numbers are size (or at least CHS-data :-)
"Configuration Data"=hex(9):01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,05,\


"Component Information"=hex:00,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,ff
"Configuration Data"=hex(9):01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,05,\

[more hardware stuff... keyboard controller, parallel/serial controllers etc.]

I just found these and I'll experiment with them later... they look extremely promising to me. The only problem might be knowing if all of them are available in Win95, WinNT and Win98 (I guess your program should work in W98?) on all computers. I would assume most computers have a processor and a hard drive, though :-))

Good luck! Let me know if that helps!

To everybody: If anybody knows of a way of directly retrieving these from somewhere else, I'd be very interested!!
oh wow... I should have known :-((
I should have known that Windows95 only pretends being an operating system. I'm staring at the screen and can't believe that the Win95 registry is mostly empty. Nothing useful about hardware at all :-(( Just for comparison: The exported "hardware" branch in Win95 is 597 bytes (30 bytes data, rest is empty keys), in NT it's 31,515 bytes!

Well, I'm afraid complaining doesn't help (but it would have been sooo nice!).
The question is still open: How do all these little tools manage to display hardware information even in Windows95?
>> GUIDGEN and uniqueness
The uniqueness basically comes from the unique value in the net address of your computer plus the current time (GUIDs are used to generate sequences of not repeating values).  

The network part is kind of unique amoung all computers

Major problems with using
1. Not all PCs have network card
2. Easy to fake
3. Net Address Ccn change when PC is modified or because of s/w (including some Network environments)

-- suggestion - forget GUIDs, net address, and hardware that comes with the PC.

If you _really_ want a unique Id on a PC, the best way to get one is to burn memory/algorithm dongles (which can be truely unique, and in some cases much harder to fake) and ship them with your product.  You have to judge for yourself whether the cost of this, and the annoying aspects of them are worth it for you & your users.

Typical cost of dongles (in quantity) - approx $10, leading vendor - Rainbow - www.rainbow.com
I best liked the proposition to write a serial into the space after the exe. be carefule not to overrun cluster size though. but I guess for this, an 8 byte number would be fine.
I had some code which gave you the bios/motherboard/cpu serials (someone obtained it from Norton utils)...I am looking for it and if I find it you shall have it. It is in C though, but I guess you could translate it...
As for writing info directly into the EXE, this will have to be done with a seperate application since, as far as I know, Windows will not allow you to alter a program while it is running.

Let's face it, it doesn't matter how you generate the serial number (based on hardware, software, whatever), if the user re-installs windows/ add or remove hardware the serial number is not valid anymore. :(

How about this for an idea (I have know idea on how to actually do it since some of it might be low level stuff).

After your program is installed read on which cluster on the harddrive it starts (hey, don't ask me, I don't know how you're gonna do this ;) ). This info you can then write into the executable. Now the executable can check whether it's still sitting in the same place before running. Of course, you'll have to "tag" your app as "not-movable" so that a disk optimiser like defrag will not move it (again, I don't know how to do this).

This of course does create problems such as: this process will have to be repeated with a new intallation, even on the same machine and also when the program gets moved from one HD partition to another.

It will however solve the problem of removable hard drives.
Just came across this, maybe it will help.

If you are able to by a copy protection system have a look to

Have you considered using MAC address ?
I personally don't recommend using the registry. As It is possible to monitor registry activity using freely available tools.
The CopyControl Tool by micrososm does not use the registry
Ronald112197Author Commented:
#1) No, I cannot afford either a dongle or a lot of money for a copy protection system - as I mentioned, that's only for a handful of users (or so...) and I won't even charge money for it... too complicated to explain right now...

#2) As I have mentioned before (!) - yes, I know this thread is quite long, but please read at least MY comments - almost all "normal" copy protection programs will fail, because the users know each other and could use the same "installation version" to install the software on several systems... It HAS to ensure that the program will run on one PC only!

#3) writing past the end of file doesn't sound so bad, but the defrag-tools seem to be quite a problem. Also, I move programs once in a while and I'm sure other people do that too...
fixed position seems to be a very dangerous idea... move the folder and you're lost :-((

#4) MaDdUCK: PLeeeeeeeease find that code! That would be THE (one and only?) answer to my question. If a) it works in Win95 and WinNT b) from a standard program, the 200 points will be yours for sure ;-))

#5) Relying on the presence of a network card or even an internet connection is not an option :-(

#6) Any more ideas concerning my last posting (10-06 3:46 PM)?

Thanks for your patience everybody - I hope this is at least interesting for everybody who bothers reading this thread ;-))
MaDdUCK, I would like to see this code too.

I am still looking. I have about 10 CDs burnt with code and I did not catalog it yet, so I have to go through it one bhy one. Please be patient.
Ronald112197Author Commented:
I'm trying... *g*
Unfortunately, I really need to implement this by Monday ;-)
Ronald112197Author Commented:
btw: avico: What's a MAC address?
How about checken the CPU ID? In the Unixenvironment it works.
Send an E-Mail to as@ct.heise.de. He can tell you how to check the id. They have written a programm to Identify your IntelCPUs.
errr..... my german is a little rusty.........

they have an english page
you can send them an englich email. they wil answer. really
btw, I am still looking for the code...
Ronald112197Author Commented:
Keep looking MaDdUCK :-))
If you find the code and I get it to work, you'll get the points as I promised... also, some code is better than a suggestion to mail. On the other hand, if I get a good answer from c't magazine, that would be worth some points as well... I still think that should have been a COMMENT rather than a blocking answer!!
Give the duck a chance, he's trying to get his comm ports to work.

Get the exact processor speed in Mhz, the fact of the matter is, all processors run at slightly different speed, that would be a great protection to you software, in case it is moved from one PC to another, ....

Hey, now give me my points:)

Ronald112197Author Commented:
well... I just might give you the points IF you can tell me HOW to get the "exact" processor speed in MHz! Has to work in both Win95 and WinNT - even if you don't have admin privs! I know that processor speed is a good idea, but I can't get anything like that under NT :-((

kuehn: I'm not getting any answer from c't... if they answer within the next week, I'll let you know and you can "repost" that answer...

MaDdUCK: R U still looking or have you given up?
I'm afraid using the clock speed does not work. The difference in speed between processors is very small. Both temperature variations and voltage fluctuations can affect this speed. I have also heard the speed can vary according to the age of the chip, but I'm not sure whether this is true or not. Thus 1) you can not accurately measure it. 2) The value will overlap between processors.


Sorry to pooh pooh all the other answers but here I go again. Correct me if im wrong, but kuehn's cpu id suggestion consists of obtaining just the type, family, model and step of the processor. Useful if your trying to determine if you have a faked pentium, but pretty much useless as a unique id.

On unix boxes, as you probably know the machine contains a chip which has a unique id, but even this can be faked. And this is not relevant in this particular case. ( I think this is what kuehn may be talking about when he mentions unix )
Sorry again.

on AIX, for example, there is a system command, to get the CPU ID. This way is used by IBM, to licence there software like Catia. You have to read out the cpuid of the machine and send this key to IBM. Then they generate an licencekey, which based on this cpuid. This id has a Risc and PowerPC Processor. Intel has this ID, too. Write an E-Mail to the e-mail address I've written above, he can tell you really everything about CPUs by Intel.
I think the system command your refering to is the command "hostid".(AIX is a unix variant). As far as im aware Intel cpus do not contain a unique serial number. (I would be very interested if this isn't the case!)

If they did every software manufactuer interested in protection would be using it? Btw, what about AMD / Cyrix?

I have send an e-mail to the c't magazin. Keep holding on. ;-))))
Ronald112197Author Commented:
well... I guess you could "earn" 2000 points per hour by just posting 10 standard links for each question!!

If you can tell me about one specific component that will do what I want  - quite frankly, I doubt that you have read this entire thread or even half of it - and tell me which page it is on, I might give you the points. Source HAS to be included. I have nothing but trouble with components when I try to upgrade a project to the next Delphi version!

Try to mention a specific component because nothing I have seen so far gives me the (type of) information I am looking for!!

I can see this has been a long, tiring discussion :-)

Try IceLock2 (link below). It combines program serialisation, user registration keys and locks down to the hard disk serial number. Its free, has source and works on D1, D2 & D3 (d4 not known). I realise this still may not do everything you want - if not reject my answer and I'll begone :-)



I was hoping for somone to give a generic i.e. non-dephi specific answer, as in the original question........ one can only hope......
Ronald112197Author Commented:
well, the question may not have been Delphi-specific, but if you take a look at the topic area... *g*

I am NEVER satisfied with this "standard Delphi topic area answer": Take component X at http://Y.com/z.zip. I want to know my code and want to know how to do it. IF the component does what I want, I'll find out what it does and post it here.

This has taken so long that I have already implemented a solution myself. It takes various system parameters (the available FIXED drives in C: to J: mapped to one byte, their sizes and serial numbers, user name of logged on user, Windows registration number, installation date, date of Windows directory and under NT: CPU type and speed) and mixes all this in some (hopefully clever) way to one 64-bit checksum and also a 100 byte long string. In combination with some "pain-in-the-..." checks, I'm pretty sure it does what I want, but it's not as "nice" as it could be with a CPU-id (also, CPU-id is less likely to change than harddisk-serial-#!!!)

I am still waiting for MaDdUCK or kuehn to post an answer to that end. There MUST be a way of getting that information even under NT, because there's a dozen shareware (not to mention professional!) programs around that tell you about your hardware!
Ronald112197Author Commented:
HELLOOOOO??? Anybody there? Still waitin....

btw: I'll try to take a look at ilock as soon as I have some time...
Hey, I am still here and let me assure you that I am still looking. I am slowly starting to get pissed off because I have not found it yet. I am really sorry that I have not found it yet and set up your hopes. I actually would not mind using it for my current project either, so I will be looking all of next weekend. If I won't reply by Monday though, then I guess you have to count me out.
You could take some bytes form ROM BIOS, using the component form ivi@ufanet.ru, tools@entechtaiwan.com
May be too late, but I've just joined Experts-exchange...
Each hard disk have a physical serial number which different from volume serial number. It can not be modified. We can get the serial number by read IO port, but it doesn't work under windows by directly read/write IO port. Fortunately, we have component to read port under windows. Which compoent I used is SmallPort. Here is code to read the unique hard disk serial number using SmallPort:

  buffer:array[0..255] of word;
  With SmallPort1 do
      while ReadByte($1f7)<>$50 do ;
      while ReadByte($1f7)<>$58 do ;
      for i:=0 to 255 do buffer[i]:=ReadWord($1f0);
      for i:=10 to 19 do
        s:=s+chr(buffer[i] shr 8)+chr(buffer[i] and $ff);
  // the result in s

By the way, I am not good at write in English. I am a student in China.  :))
Again - the best way in the situation - is to use a dongle.
Say one of well known and available and if your problem need some unusual decision - look for some not too well known systems like:

As forget about other things like IDs codes, individual numbers etc (I'm not even sure if you could legally collect them from your customers).

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.