Key generator

This topic is 4921 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I need to create a keygenerator where you can specify some options (data) and a company name. This results in a Registration key (licensekey). This key together with the company name can restore the settings at a later time (in a program). In this program a customer(company) must enter the key which is given to them along with their company name. If they enter a wrong company name the key will not be accepted. If the key is altered it will not work. This means that the generated key must be able to verify the company name and contain info about settings (data). The company name is to be displayed in the title bar of the program so that they do not distribute their key to others. I don't know where to start. Can anyone point me in the right direction? I'm using c# and .NET

Share on other sites
The easiest way is to take the data and then XOR over it the company name again. If you then XOR over that your "master key", you'd end up with a key of some description.
Unfortunaltely, this doens't give a readable string - it'd end up being a string of random-looking ASCII. At this point you could convert it to a HEX string. For example;
Data = 1234567890ABCDEFGHIJ
Company = Good Corp

You'd XOR them; repeating the shorter one
1234567890ABCDEFGHIJGood CorpGood CorpGo--------------------hjdsa76h873ghjasd82g

I don't know what the XOR'd version would look like; but it would be a mess [grin] Let's say it's that string underneath (in reality it would be garbled ASCII). Now we apply the master key:
hjdsa76h873ghjasd82gmasterkeymasterkeyma--------------------ghjk321413ghjk321gy3

Even more garbled ASCII - now just convert each character into it's HEX value, so you'd get something like:
ghjk321413ghjk321gy3--------------------BN3214B4C1A0F23F023CF0E9C1D100024BC34CB3

You could split it into groups of 5 characters for legibilty.
Now, to revert to the original data, just convert back to ASCII, XOR with the master key, XOR that with the company details and you've got your data back!

[Edited by - benryves on September 3, 2004 6:10:54 AM]

Share on other sites
Where did that master key come from ?

Share on other sites
Quote:
 Original post by granatWhere did that master key come from ?

You [grin]
If you're trying to make keys uncrackable, then it's a good idea to lay as much extra crap on top of the original.
XOR is entirely reversable; it's very simple and no doubt very easy to crack anyway, but it's the best I know of.
You make up the master key to add more protection. Of course, you could also switch every two characters, so ABCDEF would become BADCFE as well.

Share on other sites
I suggest standard encryption, like maybe using the AES algorithm. First, use SHA to generate a hash from the company name. Next, put the settings in a simple binary buffer and append a simple CRC32 checksum of the company name and also a checksum of the settings data (including the other checksum). Then, encrypt this buffer using the hash generated from the name. Next, use MIME64 to convert the binary buffer to something readable. You might want to change the encoding scheme to eliminate simmilar-looking characters if it will be typed in, so maybe replace zero, one, and lowercase 'el'(or uppercase i) with other characters. If it will just be copies from an email to the program, then you don't need to worry about the letter replacement.

MIME64 is much better than converting it to hex, because it gives 6 bits of information per character instead of only 4, which means MIME codes will be 2/3 of the length of the hex version, and only 4/3 the length of the binary version instead of double like hex would be.

Since you can find easily implementable source for things like AES and SHA, there really isn't any reason to use XOR encryption unless this is just a proof of concept or somesuch. Of course, just doing this won't make it secure because somebody could take apart your program and figure out what it does, then just decrypt the settings themselves and then encrypt them with a new company name or something like that, but it would be slightly more difficult than if you used XOR.

Share on other sites
A simple xor isn't cryptographically secure nor is that character switching method.
Use standard encryption AES, RSA and SHS for each purpose, .NET has some libs for that look'em up at msdn.

Share on other sites
Quote:
 Original post by White RabbitA simple xor isn't cryptographically secure nor is that character switching method.Use standard encryption AES, RSA and SHS for each purpose, .NET has some libs for that look'em up at msdn.

No; I know it isn't, but it's nice and easy to implement and your average Joe Bloggs will probably not be able to work it out.

Share on other sites
One of the common problems with using XOR is that people don't notice that XOR'ing a plaintext with a whole bunch of keys is really the same thing as using a single key. Plaintext^k1^k2^k3^k4^k5 may seem safe, since it's hard to guess k1, k2, k3, k4, and k5. But say K=(k1^k2^k3^k4^k5)? Now I just need to guess K; the values that it's made up of are irrelevant. Next order of business, if you really are considering using XOR, *never* use a key that's anything less than random. That's because it works both ways. While foo^bar might equal @m8, with foo as the plaintext and bar as the key, not only is there the normal decryption method of @m8^bar=foo, but you can also get the key by @m8^foo=bar. Furthermore, repeating keys verbatim is unsafe. "Some random plaintext"^"foofoofoofoofoofoofoo" is how that's normally done, but say I, as an attacker, can have some influence on the plaintext, like in a chat program? by knowing only that the word "random" is part of that plaintext, I can try XOR'ing it in with various offsets, and I'll eventually find something that goes (jarbled text is simulated, as I'm not actually calculating this out) "5,w9?foofootg|\!9db @2". When I see that repeating "foofoo", I've got the key. Even if you use a key that's longer than the known piece of the plaintext, if it's a non-random key like "The quick brown fox jumped over the lazy dog", when I decrypt via my known piece, and I find in the middle of jarbled text, "ox jumped over t", I'll know where to go from there. A simple solution to keep it random and not repeat, is let n = some random number. XOR the first 16 bytes to MD5(n), the next to MD5(n+1), etc. It's still breakable though, and while it might now suffice for both Joe Bloggs and Johnny Justlearningmywayaroundencryption, it won't work on everyone. Use a real encryption function: TEA (the Tiny Encryption Algorithm) is fast and small, and public domain source code is easy to find. I'd recommend hashing whatever you get at the end with an algorithm like MD5 or SHA-1, to keep the keylength the same size. MD5(TEA(Plaintext,Your key)) is getting much safer. XOR it to MD5(TEA(Your key,Plaintext)) if you want even more. If you're really worried, keep a database where each user has a different version of your key. That way, even if one breaks it, they don't all get it. Or heck, you can use a public key encryption system, where the key is dependant on your server as well, not just the client. That'll help fend off keygens. Of course, you don't need to do all this. But it should give you some idea of the weaknesses of XOR, and what other choices you have.

Share on other sites
Unfortuantely, your average Joe Bloggs does not need to work it out. Joe merely downloads a crack or key generator that someone else has written.

Ambrosia Software on software keys (good points here):
http://www.ambrosiasw.com/webboard/Forum14/HTML/000052.html

I think the big thing here is the key having an expiry date.

Share on other sites
From our recent experience (well... I guess "current" is better :) : the way you generate your key do not matter, unless you are sure that the key verification is hard to crack. We've done several experiments here with cracking our own code. What we've done so far :

a) neat, MD5 based, key generation
b) async key verification
c) useless unsafe code (to fool up th cracker)
d) async random errors (from bad execution to software crash) when we detect cheaters.

Finally, to crack the stuff, we simply found the code which was used to generate the comparison key, and filled the comparison key with something known. :|

It hurts. A 30 min cracking to destroy 4 days of work.

But we won't stop here :) Next point : detecting exe patching, and silently do Very Bad Things. Hope this one will be hard to catch :)

BTW, there are tools here that really helps crackers. Using them, they can get a lot of symbol references (MFC, STL, Win32 API) that will help them locating your protection code. One thing we'll also try next week to defeat this tools : creating some of the protection code at run time, as well as some important code, using softwire.

HTH,

Share on other sites
How it can be possible to protect something that does not use internet...result of some thoughts about it:
cracker only have to replace several jz/jnz - i think by comparing runs with wrong key, and with several different right ones. In fact process may be 100% automated, no intellect needed :(

If your "dobadthing" system is sensitive, it will do bad things to your legal users(that have some unknown antivirus),and then they will do _very_ bad thing with you. While users of cracked soft will be safe.
Debugger probably intercepts bad system calls, so crackers will be safe too (and you'll have to especially make it not work with wine under linux, where you probably just can't do bad things).

edit:and as about _obfuscated_ code,i would code something in stripped-down version of my one-instruction virtual mashine (there was a thread...),that does nand_and_jump,not subtract_and_jump , and would implement my cooladd,coolsub,coolmul,and cooldiv line (discussed in math and physics forum there) with it... :-) and would use my coolnand for nand. :)))(and after such abuse of sanity,there's enough performance left) It's funny but probably it can't protect anything anyway.

Share on other sites
If you're going for something that won't get cracked for a while, do like Dmytry says and implement a one instruction virtual machine. Then you could make a macro assembler and make a million and one macros for every normal opcode you want, but only include the final nand-based code in the exe. If you made significant portions of your program like that, I think most crackers would just give up. Of course, this would probably only work for business apps since I imagine that using nand-code for game logic (for ex) would have a _LOT_ of instructions and thus be _REALLY_ slow.

I'm not sure on the specifics of his nand machine, but if you want to be evil you could make the nand take two jump locations instead of one, where the second one is where to go if whatever condition is false. Then, during compilation, the assembler could randomly reorder ALL instructions and adjust the jumps to the proper location. It could also have '?' as a jump instruction for when you _KNOW_ a jump won't be taken because of the program's logic, and then the assembler could fill in a random spot to make the worst code you've ever seen =-P Of course, it'll execute slower as well.

The above is me

Share on other sites
Quote:
 Original post by DmytryHow it can be possible to protect something that does not use internet...result of some thoughts about it:cracker only have to replace several jz/jnz - i think by comparing runs with wrong key, and with several different right ones. In fact process may be 100% automated, no intellect needed :(

We get a chance here : the process cannot be fully automated. How do your automate know wether this particular jump instruction deals with a wrong key ?

Quote:
 Original post by DmytryIf your "dobadthing" system is sensitive, it will do bad things to your legal users(that have some unknown antivirus),and then they will do _very_ bad thing with you. While users of cracked soft will be safe.Debugger probably intercepts bad system calls, so crackers will be safe too (and you'll have to especially make it not work with wine under linux, where you probably just can't do bad things).

Fortunatly, the legal users are well known and controlled. They are not customers. So if there is a problem, this can be solved easily. And by "Very Bad Things" I wanted to say anything from a nag screen to a software crash. And we do not target anything but Windows. This is industrial software, not a "Cool Piece of Soft You Can Use To Do Whatever You Want". So I believe this is a particular case which allows us to do so.

To be able to safely do bad things (ie do not perform anything that should hurt a legal user), you must not rely on anything but your software : no registry key, no file, etc. Only your algorithm. The user need to enter his key each time he wants to use the software. If the key is not the good one, then do not allow the user to use the software. It will not hurt him since he did the error. If you detect that the software has been cracked, then you can do whatever you want with your product.

Of course, the main thing (the user enter the key each time he want to use the software) may not be applicable in a lot of cases.

Quote:
 Original post by Dmytryedit:and as about _obfuscated_ code,i would code something in stripped-down version of my one-instruction virtual mashine (there was a thread...),that does nand_and_jump,not subtract_and_jump , and would implement my cooladd,coolsub,coolmul,and cooldiv line (discussed in math and physics forum there) with it... :-) and would use my coolnand for nand. :)))(and after such abuse of sanity,there's enough performance left) It's funny but probably it can't protect anything anyway.

Evaluating a scripted function is a good idea indeed, since that the cracker need to understand you virtual machine before he can do anything with it. It can protect things if it is not used only to test the validity of a key. The program can also do some important maintenance operation (like, say, allocates some memory which may be needed in another thread).

A sidenote : do not use neither CString nor std::string in critical code when compiling with both VC6 abnd VC.NET. If the hacker get the correct DBG files. I thought that std::string would be totally inlined in release mode, this is not the case.

Your checking functions should be written using spagghetti code, no function call, multiple checks, embedded vital code, and so on. This make the hacker's task harder.

HTH,

Share on other sites
Quote:
Original post by Emmanuel Deloget
Quote:
 Original post by DmytryHow it can be possible to protect something that does not use internet...result of some thoughts about it:cracker only have to replace several jz/jnz - i think by comparing runs with wrong key, and with several different right ones. In fact process may be 100% automated, no intellect needed :(

We get a chance here : the process cannot be fully automated. How do your automate know wether this particular jump instruction deals with a wrong key ? [...]
If you give any kind of message on a wrong key, it can be automated. If not, a legal user can make a typo and find your program extremely buggy or whatever.

Quote:
 [...]Your checking functions should be written using spagghetti code, no function call, multiple checks, embedded vital code, and so on. This make the hacker's task harder.HTH,
Of course, this also makes the initial programming, debugging, and maintainence more difficult as well. Like I said, using the scripting language with an automated spagghetti-code-generator would probably be the best bet, since you can keep the 'normal assembly' around for editing purposes.

Share on other sites
Another technique (I apologize if this is repetitive, I only scanned the above comments) is to ensure that you verification routines are very passive in their enforcement. There was a good article on all of this somewhere and I really wish I could remember the link. Most likely, on Gamasutra - so take a look. anyhow, the idea is that if you return a defiant "NO!" when a bad key is entered or hack is performed, then the cracker will be have a definitive response to his crack attempt.

Before you get ideas of grandeur, you will eventually lose. There is *no possible way* to prevent someone from eventually cracking your software. The real goal, sadly, is to make it difficult enough so that most people will buy the software rather than cheat and steal it. One way of extending this is making the crack more difficult to test. For example, if the cracker develops what (s)he believes is a successful hack and only checks to see if the program runs, they will publish it (keep in mind, they would rather spend 30 minutes to break your software and steal it, rather than work 20-40hrs and buy it..). However, if 1/3 the way through the game a player cannot get the key from the wizard and the wizard's dialog reads "The player is a scoundrel, who has stolen the software and is unfit for the key!", then the cracker must re-do the crack. He also must go through all the various points of game testing to verify that the crack works all through the game.

The idea is to intersperse these check throughout the game, in slightly obfuscated and randomly selected areas. If it takes 4 months for a successful crack to be completed, you have done well. This should ensure that for the bulk of your shelf time expectancy, there was no crack to steal your software. Eventually you will lose, or they will have to invent some sort of mechanism that violates privacy laws.

Anyhow, this is a bit off-topic but I thought relevant to the conversation and worth contributing. I hope that it helps..

#dth-0

Share on other sites
Well, if your target audience is small enough, or if your sole method of software delivery is online you could always just take the information they give you, use MD5/SHA to create a hash, use that hash as the key for AES and use AES on the code segment of the executable. So each executable would have a unique key. Maybe toss in some public-key encryption method of them giving you the information for the hash so that someone can't steal it over the network.

Share on other sites
Quote:
Original post by Extrarius
Quote:
 Original post by Emmanuel DelogetWe get a chance here : the process cannot be fully automated. How do your automate know wether this particular jump instruction deals with a wrong key ? [...]
If you give any kind of message on a wrong key, it can be automated. If not, a legal user can make a typo and find your program extremely buggy or whatever.

We finnaly ended up by having a first test to limitate typos. The user enter its key, if the key is wrong then we display a message. The protection here is simple and easily crackable by changing a jump - but this is not a real problem since we do not compare the whole key but only a part of it - the goal is to act as if we really do an important check here. So this will be the first part of the software that will be hacked. In the next days, this code section will be monitored in order to find wether it has been hacked or not (this was the goal of my address of a C++ member function question).

The important tests are done in a separate thread - one different test each 50 ms or so. The same thread does very important code too and it is somewhat difficult to remove the protection while not acting on the important code. Another thread may produce an action or a report when the software has been hacked. And, of course, as I already said, some tests allow us to introduce bogus behavior in our program.

Our main problem is to protect the code from modification - a local checksum should help here. Another problem is to prevent the creation of a keygen - I believe this can be done using proper code obfuscation (not testing everything in the same place should help) and runtime code generation and evaluation (not tested, but we will implement that next week too).

We have strings in the code that help to fool a hacker during some time (strings like "PerformSha1Encoding" or "RSA_array" are always interesting and may catch cracker's attention...).

Anti-cracking measures is a very exciting field, and very immportant. Consider that if I and my co-worker failed to provide a good anti-cracking protection to a very small piece of software, we'll get a lot of trouble :|

Yours,

Share on other sites
anyway, legal codes will leak some day,if your software can leak...
(if can not, protection is not needed).If key is only needed to ideintify leaker,you can better make each program to be unique (say,by doing something random with assembly that doesn't change program itself).

Share on other sites

and,the beauty of OISCVM is that it will take long time for hacker to even ideintify it as teh VM. I don't even sure OISC can be named VM at all,in fact,it's just only _crazy_ data processing.You can do OISC without any jumps,in single loop.
ip+=(s[s[ip+2]]=s[s[ip]]-s[s[ip+1]]) < 0 ? 4 : s[ip+3];

you can remove all jumps(except processing loop,of course) by defining
#define q(a,b,c) ((((signed_int)(a)-1)>>31)&&((c)-(b))+(b))
and use q(a,b,c) instead of a?b:c

edit:

or even better, use

ip+=((s[s[ip+2]]=s[s[ip]]-s[s[ip+1]])>>31)&&(s[ip+3])+4;
but count jumps relatively to next instruction.

Or even more crazy, use uberkiller code:
ip^=((s[s[ip+2]]=s[s[ip]]-s[s[ip+1]])>>31)&&(s[ip+3])+s[ip+4];
and define ip as s[1234] for uberkillereffect.

How it works:If result of subtraction is <0 ,summ of jump adresses is xor'ed with current ip pointer. If >0 , second jump adress xor'ed with current ip pointer.

Jumps must be randomly placed by Extrarius's idea :)

It's no longer an VM. At all. It's hyperperversion.

Double-instruction VM is more practical,and also can be done without any jumps :))) and might be even MORE weird !

and you can put your serial number as part of OISCVM program.
You can allow OISC to write/read your program's ram,by accessing outside of array.
Also i think it's possible to make VM that melds data and code into single thing,every data change is a code change.

[Edited by - Dmytry on September 4, 2004 3:37:29 AM]

Share on other sites
The question is what you want to do with that protection. Do you want to keep an ambitioned hacker/cracker from disabling your control scheme, or do you want to keep Joe Average from picking up a CD-ROM from somewhere and run your software for free?

In the second case, you could use a crypto loader using proven algorithms. For example, you could write a GPG frontend. You encrypt some incredibly important part of the program (like the main executable) to a customers key and sign it with your own. The customer gets your public key and his public/private pair.

The loader uses the customer's private key to decode the executable and verifies the signature. Thereby, it should be pretty much guaranteed that the customer has a good copy (you can sign all files).

For the program to be stolen, a customer who already paid good money for the privilege to use the program had to pull the decoded binary from memory, hack out any potential safeguards you put in and then redistribute it. So security in this case boils down to (a) the customer not being willing to allow others access to your program, and (b) the customer being responsible in his use of the issued keypair, which of course has to be used in all support transactions and software updates.

Share on other sites
no.
The real risk is that key, company name, and code will just leak from one of users/customers (using a trojan,for instance),or from distributer. And then some man will JUST REDISTRIBUTE it together with key and company name. Then if it will be needed hacker will write a keygen.

edit: and another risk, if customer want to run more copies than he have right to run. There's no way to protect unless it's communication-related application (so program have to check if all endpoints in communication have different codes).

Share on other sites
Quote:
 Original post by Dmytryno. The real risk is that key, company name, and code will just leak from one of users/customers (using a trojan,for instance),or from distributer. And then some man will JUST REDISTRIBUTE it together with key and company name. Then if it will be needed hacker will write a keygen.

Last time I checked, there were no really good "keygens" for PGP/GPG (which would mean fast attacks on DES, ElGamal, et al.). So even if the key went public, you could revoke support privileges for the key, issue the company a new one or slap them for breach of license agreements or contract. You can never eliminate that risk on a not communications-based scheme. If a key is out, all you can do is stop to support it as quickly as possible. Have a look at what MS did with the leaked WinXP keys.

Share on other sites
One thing you could do is make the key have some kind of hash of the hardware. This only works for high-provile single-use apps though, since the user will have to call you every time they change hardware.
You'd send them a program to run on the machine, they read/send off what it says, and you include some of that material in a new key for the latest version of the machine.

But really, even programs with hardware dongles get cracked, and that pretty much proves there is no secure way to make keys. Even if you made a dongle that actually did some processing required by the program, some warez groups would be making their own in a relatively short period of time.