More copy protection...

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Hello everyone,

First off, I'd like to thank everyone for sharing their wealth of knowledge and insight here. It's been extremely helpful for a newcomer like me.

I've read all of the copy protection discussions here and it helped me come up with some sort of ***reasonable*** plan for my upcoming plugin. It goes something like this:

- When the user purchases a license, Fastspring calls a php script on my server that encodes the user's name & email using a private key into a license code that's emailed to the user.
- The user enters that license into my plugin.
- My plugin decodes that license using a public key that I've obfuscated inside the plugin.
- If everything is proper, I should save some kind of encoded file that contains a form of a machineID on the user's drive that says the license is proper for future startups.

And that's where I'm a bit confused.

I understand that the reason to keep the private key only on my server and obfuscating the public key in my plugin is to help prevent from a cracker creating a keygen. But I have to save that encoded license info on the user's drive and to do that would mean that my plugin would have to contain another private and public key to write and then later read that license during future startups. But wouldn't I be risking a cracker creating a keygen for the license file that's in plain sight on the user's drive?

I notice that many manufacturers save some sort of license file in Application Support, so I'm guessing that I'm going in the right direction, but I seem to be missing something.

I know this is an ongoing battle that's almost always doomed to failure, but I feel like I need to do at least some due diligence here. Any thoughts would be greatly appreciated. Feel free to message me privately if you prefer.

Thanks again.

Post

Ilok is the way to go. Don't bother with other schemes, it's a waste of time... :hihi:

Post

Afaik everything that uses encryption/decryption will be cracked quickly. They usually just swap the public key for their own out of the binary and write a keygen for it.

Encryption is useful to do "casual" obfuscation, but the payload should contain something that you can verify later on.

You could for instance add secret number, a hash of the licensee's name and the licensee's name itself into the payload. Your software unlocks when there's a plausible user name and if the secret number checks out.

Then, on a delayed check that's hidden in your app you can verify if the hash matches taking the hash from the user name. This way, even if the crackers can swap the public key to create the payload, they still can't create the hash of the user name, unless they find the place where you check it.

Obfuscating checks, i.e. doing checks much later than on app start, maybe weeks or months later, has been my most successful strategy against cracks. We have about 10 different checks in our stuff.

Oh, and once it's cracked, don't despair. Find out how they did it and add a delayed check that tests the vulnerability. Then release and update with better features (they'll crack it straight away, but the crack won't last long, due to your new check). Writing strong copy protection is also an iterative process, where the protection becomes gradually stronger, with the free help from crackers themselves.

- U

Post

Urs wrote: Encryption is useful to do "casual" obfuscation, but the payload should contain something that you can verify later on.

You could for instance add secret number, a hash of the licensee's name and the licensee's name itself into the payload. Your software unlocks when there's a plausible user name and if the secret number checks out.
Are you suggesting that to compile a specific binary to send to each user with some user info contained inside?

Post

joshb wrote:
Urs wrote: Encryption is useful to do "casual" obfuscation, but the payload should contain something that you can verify later on.

You could for instance add secret number, a hash of the licensee's name and the licensee's name itself into the payload. Your software unlocks when there's a plausible user name and if the secret number checks out.
Are you suggesting that to compile a specific binary to send to each user with some user info contained inside?
Could be, I know some developers that also work with distributing "watermarked" personal binaries , but I think in this case Urs means that the universal binary changes from the point where a user has entered his/her serial number registration info (?)
No band limits, aliasing is the noise of freedom!

Post

Urs wrote:Oh, and once it's cracked, don't despair. Find out how they did it and add a delayed check that tests the vulnerability. Then release and update with better features (they'll crack it straight away, but the crack won't last long, due to your new check). Writing strong copy protection is also an iterative process, where the protection becomes gradually stronger, with the free help from crackers themselves.
Regular updates and a relaxed demo policy are probably the most effective measures.

In our specific case, the whole business model is designed to demotivate these activities to the max. Our products, when cracked (or rather simply uploaded with an .nfo), typically tend to provoke long ethical (!) debates in warez forums. I think that's a good sign. :)

In 2016, it's rather silly to ignore piracy in the business model/marketing. You simply can't sell plugins like luxury goods. You need a more organic product structure that's immune to regular copy and paste fraud.
Fabien from Tokyo Dawn Records

Check out my audio processors over at the Tokyo Dawn Labs!

Post

No ethical forum discussion would stop someone anonymous from using a cracked plugin. Particularly if he/she uses illegal software all the time. This is some kind of wishful thinking.

Nonetheless conditions for buying a product are a good & stable plugin for a fair(!) price, a somewhat limited demo version, a developer/support who doesn't lack in communication, fast bugfixing and a userfriendly copy protection.

Post

Nielzie wrote:
joshb wrote:
Urs wrote: Encryption is useful to do "casual" obfuscation, but the payload should contain something that you can verify later on.

You could for instance add secret number, a hash of the licensee's name and the licensee's name itself into the payload. Your software unlocks when there's a plausible user name and if the secret number checks out.
Are you suggesting that to compile a specific binary to send to each user with some user info contained inside?
Could be, I know some developers that also work with distributing "watermarked" personal binaries , but I think in this case Urs means that the universal binary changes from the point where a user has entered his/her serial number registration info (?)
Watermarking binaries is pretty much yesterday sicne operating systems prefer signed binaries installed with signed installers. You can't just quickly do this on the server anymore, unless you build hundreds or thousands of binaries "on store". It's doable, but it isn't elegant anymore.

What I mean is, don't waste your time in encrypting/decrypting protection data with elaborate 2048 bit RSA whatsoever. As soon as there's a public key in your binary, they'll find it, lift it and put their own in.

I recommend something like this:

Username : John Smith
Serial : XGHZ-HJKI-KJFT-JHPT

where

XGHZ-HJKI = Whirlpool(John Smith) & 0xFFFFFF

and

KJFT-JHPT = SHA512(XGHZ-HJKI) & 0xFFFFFF

So half the serial is based on a hash (Whirlpool) of the user name, the other half is based on the hash (SHA) of the first half. That's an example. You can use other combinations.

Here, you get two possible checks:

1. Check if hashing the user name yields the same number as the first half of the serial.

2. Chech if hashing the first half of the serial yields the second half of it.

In the app then, unlock the demo if *one* (and only one!) of the two conditions is true.

In a delayed check, impose a new demo restriction if the other of the two conditions is wrong.

#----

Once understood, make it 4 or 5 such things. Find clever ways to hide the checks, let them go off rarely.

Most importantly: Keep it simple. Don't make mistakes. You don't want false positives. Add a checksum maybe.

There you go. In order to keygen this they need to find all the occasions of delayed checks, because it doesn't happen on first occasion. Tedious. There's also a way to make it impossible to keygen at all, but that's a whole different story.

- U

Post

Thank you so much. This really opened my eyes to looking at this in a whole new way. Seriously, thank you.
Urs wrote: There's also a way to make it impossible to keygen at all, but that's a whole different story.
And feel free to elaborate on your "whole different story"... :wink:

Post

I suspect Urs means making a network request to a server to verify the key is one you've issued and the whole different story is the complexity it introduces to your code and the wonderful ways it be circumvented.

Post

joshb wrote:Thank you so much. This really opened my eyes to looking at this in a whole new way. Seriously, thank you.
Urs wrote: There's also a way to make it impossible to keygen at all, but that's a whole different story.
And feel free to elaborate on your "whole different story"... :wink:
Ok, quick one...

Create, say, 100 (or 2000, or 65536, don't matter) absolutely random pieces of your serial, like DIHE, S3TH, XXVR and so on and so on. If you use a keyfile instead of serial, you can lush out and make it 64 bytes long.

Take a 512-bit cryprographic hash function (I love Whirlpool, what a great name) and hash each of those. Now you got a hash of 64 bytes for each secret part. Out of these 64 bytes, choose 5 pairs of two and "hide" them in you binary, for example bytes 5 & 7,19 & 34, 45 &... of each hash . So you have 5 new sections in your code where you have 100 pairs of bytes selected from those hashes of your secret list of pre-computed random serial extensions. These are part of your new extra check points.

As these are cryptographic hashes it's utterly difficult to recover the original random stuff from just those 10 or so bytes stored in your binary, even if they find all occurrences :idea:

Now. You're hashing the user name, aren't you? - Take the hash of the user name, take it % 100. So each user is assigned one of the random serial bits. On your keygen at home, add that secret serial bit to their serial number. (yes, some users share the same secret bit. Do you care? - I don't)

In the main check of your app, take the hash from the user and take the hash from the secret random bit of the serial. With whatever you check there, also check the hash of the secret bit against the first two corresponding bytes stored in your binary.

When unlocking your app, make a few dozen copies of the hash of the user name % 100 and the 64 bytes of the hash of the secret part. Distribute it all over the app. Make it a member of some important classes. Just splatter it all over the place. Still, keep it simple no mistakes allowed.

On rare occasions, possibly not even based on user interaction, in one of your important classes that stores those hashes: Based on the user name hash % 100, pick the right pair of bytes stored in that table of 100 pairs. Check it against the corresponding 2 bytes in the hash of the secret random part of your serial. On fail, impose new demo restriction.

Every once in a while, when you update you app, swap one or two tables of the 100 pairs of hashes of the secret part of the serial against another. Instead of, say, 100 pairs made of bytes 19 and 34, store 100 pairs made of bytes 7 and 51. So in an update you're storing new information in the binary that was not present before.

This way, even if they're lucky enough to write a keygen that unlocks your current set of hashes, they have to do it all over again.

#----

More tips.

Don't use the same code for each check. Write each check as if you're trying to find a different way to do it. Their tools allow for pattern matching in the executable code. (definitely don't store the % operator with each section)

Use functions and methods in your CP that your app needs anyway. For example, make an abstraction fo file loading. Let the code that opens the key/serial file be the same code that loads presets of documents. The more overlap, the better debugged, the more stable, the less vulnerable against cracks.

A classy delayed check: Run a bogus user name and serial by your registration method. One that you know fails. If it still unlocks, you're cracked. Then impose new demo restriction.

Find ways to hide your executable flow from IDA Pro. One good method is to write a "service object" that does file handling, message boxes, hashes, preset loading, a few uncritical sample calculations and so on. Make it have a dispatcher call that doesn't inline ever. So that, no matter if you load a file, calculate some waveform tables, calculate the RMS for a set of samples or hash something, it's a call to the same dispatcher method, with just some opcode and a pointer to whatever data. Use it a lot throughout your code. (this moves cracking from the realm of code flow to the realm of data manipulation, of which the tools are lesser)

Keep it simple. Keep each check, it's trigger, it's evaluation and the demorestriction it imposes in the vicinity of 10 lines of code each. With some experience, ten checks, 300 lines keep your binary pretty safe.

Ok, maybe that wasn't so quick after all. And yep, not helping them, just helping you.

- U
Last edited by Urs on Mon Nov 07, 2016 8:01 am, edited 1 time in total.

Post

keithwood wrote:making a network request to a server
Web access is among the first things they find. Anything that requires calling OS routines and services. One can put it into the dispatcher I mentioned, but unless you also have an online preset database or something, I wouldn't bet my life on it.

Post

So awesome. Urs, you're a wicked gentleman. The next time you're in LA, beers on me.

Post

Hey Urs,

Do you any thoughts on using some form of a machineID in the serial?

I was thinking about doing something similar to what you suggested above with hashing the name of the user, and when he registers the plugin, get a machineID and make a new license code out of that and the hash of the user, and that's what get's saved to disk. The idea being that a user couldn't then just share the license file with others because the machineID wouldn't match.

Thoughts?

Post

joshb wrote:Hello everyone,

First off, I'd like to thank everyone for sharing their wealth of knowledge and insight here. It's been extremely helpful for a newcomer like me.

I've read all of the copy protection discussions here and it helped me come up with some sort of ***reasonable*** plan for my upcoming plugin. It goes something like this:

- When the user purchases a license, Fastspring calls a php script on my server that encodes the user's name & email using a private key into a license code that's emailed to the user.
- The user enters that license into my plugin.
- My plugin decodes that license using a public key that I've obfuscated inside the plugin.
- If everything is proper, I should save some kind of encoded file that contains a form of a machineID on the user's drive that says the license is proper for future startups.

And that's where I'm a bit confused.

I understand that the reason to keep the private key only on my server and obfuscating the public key in my plugin is to help prevent from a cracker creating a keygen. But I have to save that encoded license info on the user's drive and to do that would mean that my plugin would have to contain another private and public key to write and then later read that license during future startups. But wouldn't I be risking a cracker creating a keygen for the license file that's in plain sight on the user's drive?

I notice that many manufacturers save some sort of license file in Application Support, so I'm guessing that I'm going in the right direction, but I seem to be missing something.

I know this is an ongoing battle that's almost always doomed to failure, but I feel like I need to do at least some due diligence here. Any thoughts would be greatly appreciated. Feel free to message me privately if you prefer.

Thanks again.
Copy protection is token resistance, merely a symbol to support the developer. I highly recommend you focus on the product features instead... because I can most definitely tell you there are people with the same level of knowledge as myself and beyond that can break pretty much anything you can throw. Although I personally refrain from cracking, I grew up on ASM, and I've had to do plenty of legitimate reverse engineering in the past. If you want to keep it real simple, keep a list of strings to yourself and then hash them all, keep the hashed list in your program. Unless you are planning on selling massive numbers of copies.. this should be good to get it out of the way real quick and only a couple lines of code. This is the same idea as a basic password database.

If you want to get into serious copy protection, of course the product would have to be run on a dedicated server under your control (no code access), but that wouldn't sell at all. Or you could create unique compiles for every download (a form of polymorphism), but that's easy to bypass by simply copying the file after cracking, wherever. As long as actual valued code is run in some form on the customer's system, it can be cracked. You could go so far as to exclude the code until run-time, require an online connection, and download obfuscated polymorphic code into encrypted memory, except that code can be unspun pretty quickly too.. so then you can try to integrate into the system to try to further prevent this going as far as drivers and beyond.. but of course there are virtual machines, and other 'tools'... it's inescapable as long as the code is in the hands of the user, in any form.

Although I'm a developer, I also am a picky customer and very strict about software that I buy and allow on my system. If it's too much of a hassle and the product is too obsessed with copy protection to be a convenience, and even begins to drain my resources, it's scratched off the list. I have too much software, way too many plugins, and I don't need a mini nuisance product to waste my time and resources. If it's truly a gem, it will act that way. That's why I love audio damage, you can truly buy it 'ready-to-go'.... simply does what you need it for. I'm definitely not the only guy in this boat either.
SLH - Yes, I am a woman, deal with it.

Post Reply

Return to “DSP and Plugin Development”