Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Developing U++ » UppHub » Protect package - A starting copy protection system
Protect package - A starting copy protection system [message #28850] Sun, 19 September 2010 21:07 Go to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
I added a symple code copy protection / encryption package (Protect) with the encryptor itself (ProtectEncrypt) and a test application (ProtectTest).

Please read the help inside Protect package in order to setup the encryptor.
Once properly setup, the system is transparent to TheIde build system; code will be automatically encrypted upon build.

Please try it with the ProtectTest demo package:

1) Load and build ProtectEncrypt package; if possible put the resulting executable somewhere in your execution path (/usr/bin for Linux, system32 directory for windows). If you prefere, you can leave executable in upp/out folder, but you'll have to give the full executable path to custom build step, see below.

2) Open the demo project ProtectTest; choose the 'GUI PROTECT' build flags AND update the custom build step to match location of your ProtectEncrypt executable; please leave the demo KEY as it is.

3) Build and run the ProtectTest package. If all went OK, you'll see a couple of message boxes telling you that, OR possibly you didn't choose the 'GUI PROTECT' build flags, in which case the encryptor isn't operating.

4) When all above is working, try to change the key inside GetKey() function in ProtectTest package, making it different from the one inside the custom build step line.
Running the app will make it crash, as it'll be executing garbage code instead of un-encrypted one.

REMARKS :

-- if you don't choose the 'GUI PROTECT' build method, encryption will be disabled and your app will run unprotected.

-- if you don't put the right executable path on custom build step, the encryptor won't work, BUT the decryptor inside test app will... so you'r app will crash when run.

This one IS NOT a commercial grade copy protection system, but just a starting point for software locking/encryption; feel free to add suggestions/enhancements to it !

Ciao

Max

[Updated on: Sun, 19 September 2010 23:16]

Report message to a moderator

Re: Protect package - A starting copy protection system [message #28854 is a reply to message #28850] Mon, 20 September 2010 00:50 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

Hi Max!

This is a very interesting package. I couldn't resist and played with it for a while Smile My conclusions: It works very well and it would definitely stop me from stealing the app.

Few observations:

It works as well with flags "GUI .PROTECT" which cause less recompilation when switching between protected and unprotected mode. (If you want to have encrypted code in other packages than main and still use this trick, you can add PROTECT into 'Accepts' field in package manager.)

You can't declare variables inside the encrypted block, because 'jump to label __end crosses initialization of ...'. It is somewhat cryptic, so it should be probably mentioned in docs. Work around is to put another pair of '{}' between the calls to PROTECT_... macros to limit the scope of variables declared inside.

You can't have two encrypted blocks in one function, as it results into redeclaring variables. Even if the blocks are in different scopes, it fails on duplicate labels. This could be fixed easily, but it is probably not important for real-life usage.

The 'return' in PROTECT_END_FUNC prevents using the macro in functions returning a value. Omitting it causes runtime error, but ugly fix comes to my mind:
#define 
//only for posix here, for win it is similar
PROTECT_END_FUNC(RETURN) \
	RETURN; \
	__end: \
	asm volatile ( \
		"\t.ascii \""PROTECT_END_MARKER"\"\n" \
	)
//and calling it like this (stupid example):
int testfn1(void){
	int j=0;
	PROTECT_START_FUNC(Decrypt);
	PromptOK("testfn1 DECRYPTED SUCCESSFULLY!!!");
	return j; // <- returning in between wouldn't hurt 
	PROTECT_END_FUNC(return j);
}


One question at the end: Do I understand it right, that the decryption is performed only on first call of the function? So it modifies only the program loaded in memory? If so, I'll seriously consider calling it a voodoo Very Happy

Good job!
Honza
Re: Protect package - A starting copy protection system [message #28855 is a reply to message #28850] Mon, 20 September 2010 08:14 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3355
Registered: August 2008
Senior Veteran
Thank you Massimo

I will try to use it, sure!


Best regards
Iñaki
Re: Protect package - A starting copy protection system [message #28857 is a reply to message #28854] Mon, 20 September 2010 10:02 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
dolik.rce wrote on Mon, 20 September 2010 00:50

Hi Max!

This is a very interesting package. I couldn't resist and played with it for a while Smile My conclusions: It works very well and it would definitely stop me from stealing the app.


Ehehehe.... no, it's not too difficult to defeat, IF you've the key

Quote:


Few observations:
.........
You can't declare variables inside the encrypted block, because 'jump to label __end crosses initialization of ...'. It is somewhat cryptic, so it should be probably mentioned in docs.


mhhhh... I haven't tried it enough, but I guess it can be solved
somehow.... I couldn't just resist to put on bazaar for testing Smile
The main problem I found is that damned M$ inline assembler, I guess it was coded by some drunk people....

Quote:


Work around is to put another pair of '{}' between the calls to PROTECT_... macros to limit the scope of variables declared inside.


I'll look at this solution this night.... Maybe it's a good suggestion

Quote:


You can't have two encrypted blocks in one function, as it results into redeclaring variables. Even if the blocks are in different scopes, it fails on duplicate labels. This could be fixed easily, but it is probably not important for real-life usage.


Well, the macros are thought for single usage in every function. I guess they could be modified for multiple usages (maybe using the __LINE__ macro for labels, or something like that, but I guess it's better to use it just once per function.

Quote:


The 'return' in PROTECT_END_FUNC prevents using the macro in functions returning a value. Omitting it causes runtime error,


Well, that's a bigger problem.... I didn't think about it.
The ending return statement is just to avoid entering into data (garbage) part of the code.... But can be solved also with an assembler jmp, I guess. I'll try it this night too Smile

Quote:


One question at the end: Do I understand it right, that the decryption is performed only on first call of the function? So it modifies only the program loaded in memory? If so, I'll seriously consider calling it a voodoo Very Happy



Yep, it's decrypting on the fly on first function call.... and that's the biggest flaw of the approach. With a good placed breakpoint you can have the decrypted code in memory, and looking for the call to decrypt routine is quite easy with a good debugger. You must, indeed, have the key handy to do that, without key you can't do anything.
I was thinking about obfuscating a bit more the stuff, I've just to think a bit about it. The "big" problem is to keep the process simple and portable between GCC and MSC; to do a better think we should parse executable headers which isn't easy.

Anyways, as you can see from macro code, the whole process isn't a big voodoo Smile The macro just marks the executable with some known strings, easily found by encrypter code, which patch the executable on right places. The decrypter has just to open code memory for write access and reverse the process. It's easy if you use encrypt algorithm that doesn't change code size.
A better (and more secure) approach would be to encrypt/pack the code and to decrypt/unpack in memory allocated for the purpose.... But, I guess then ww would have do parse executables, object files and so on, which makes it a nightmare for portability sakes Smile

Quote:


Good job!
Honza


Thank you Smile

Ciao

Max
Re: Protect package - A starting copy protection system [message #28862 is a reply to message #28857] Mon, 20 September 2010 13:57 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
Uhmmmm... well, I guess the 2 most annoying points are solved now.

Now functions returning values are allowed and also declarations inside function body.

Ciao

Max

Edit: btw, if somebody just wonders why the

if(!__decrypted)
    goto __end;


Is needed (goto is never taken), that's because if not there the optimizing GCC would skip the end marker assembly code, thinking it never gets executed.

[Updated on: Mon, 20 September 2010 14:46]

Report message to a moderator

Re: Protect package - A starting copy protection system [message #28866 is a reply to message #28862] Mon, 20 September 2010 18:29 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

Wonderful!

I have one more idea Wink Unfortunately I am too lame to implement it Very Happy

Just letting it crash by executing garbage is not really nice (even if the cheating user deserves it Smile ). Might be even possibly dangerous. Would it be possible to somehow check if the decryption was successful and throw an exception? Then the programmer could use something like
bool TestLicense(){
    bool b;
    try{
        PROTECT_START_FUNC(decrFunc);
        b=true;
        PROTECT_END_FUNC;
    }catch (...) {
        Exclamation("Invalid license, get a new one!");
        b=false;
    }
    return b;
}


Now implementation idea: put one more data section similar to PROTECT_XY_MARKERs, but this time into the encrypted area. As this would be a known constant, it could be checked right after decrypting. If the decrypted data don't match, the inner function code could be skipped and exception thrown (or some flag raised, if you don't like exceptions). Do you think this would be possible?

Honza

PS: Sorry if it looks like I am never satisfied Smile I admire the code and just trying to give you a (possibly useful) feedback Wink

[Updated on: Mon, 20 September 2010 20:55]

Report message to a moderator

Re: Protect package - A starting copy protection system [message #28867 is a reply to message #28866] Mon, 20 September 2010 21:38 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
Well, the idea is to check the license correctness at program startup and abort if not valid.... You should never reach the encrypted functions if license is not valid.
The check could be quite simple, like that one :

main()
{
    String guard = "someencryptedtextofwhichyouknowthedecryptresult";
    String key = GetGey();
    Buffer<byte>buf(guard.GetCount());
    memcpy(buf, ~guard, guard.GetCount());
    RC4 rc4(key);
    rc4.Crypt(buf, buf, guard.GetCount());
    if(strncmp(buf, "yourknowndecryptedtext", guard.GetCount())
    {
        PromptOK("Invalid license key!!!");
        exit(1);
    }

    // here rest of your app

}


As you see, the user is warned that the key is invalid. If it
patches the app, for example removing the exit(), he deserves a good app crash Smile

Purpose of encryption is to (try to) avoid reverse engineering of application, not to signal the user of the correctness of license.

Ciao

Max

Re: Protect package - A starting copy protection system [message #28868 is a reply to message #28867] Mon, 20 September 2010 23:21 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

mdelfede wrote on Mon, 20 September 2010 21:38

As you see, the user is warned that the key is invalid. If it
patches the app, for example removing the exit(), he deserves a good app crash Smile

Point taken Smile I don't know why I always miss the simple solutions Confused

Honza
Re: Protect package - A starting copy protection system [message #28869 is a reply to message #28868] Mon, 20 September 2010 23:38 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
dolik.rce wrote on Mon, 20 September 2010 23:21

mdelfede wrote on Mon, 20 September 2010 21:38

As you see, the user is warned that the key is invalid. If it
patches the app, for example removing the exit(), he deserves a good app crash Smile

Point taken Smile I don't know why I always miss the simple solutions Confused

Honza



Well, I think I'll add some simple encrypt routines for strings and a macro to check the correctness of key... they should be simple too.
Btw, I'd like to add a simple web authentication scheme... do you have some skill in php/web programming ?
What I'd need would be a way to register by app dialog, get back an activation e-mail with a link and then have the key sent from web server to my app on each app run.
I mean :

APP NOT REGISTERED --> REGISTER DIALOG --> SEND TO SERVER
SERVER SENDS EMAIL --> USER CLICK ON EMAIL LINK -- USER ACTIVATED

On following app launches :

APP REGISTERED --> ASK SERVER FOR KEY (sending name-mail-pass) --> SERVER SEND BACK KEY

The best would of course be some obfuscation of key from server, but that one could be added later.

Ciao

Max
Re: Protect package - A starting copy protection system [message #28877 is a reply to message #28850] Wed, 22 September 2010 00:52 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
I added some more stuffs to package :

1) A macro to check key correctness on startup :

ON_PROTECT_BAD_KEY(Decrypt)
{
    PromptOK("Bad License !!!");
    exit(1);
}


And another protection method, OBFUSCATION, which is handy to make code hard to disassemble/debug even before you obtain the key, so useful to protect your key-obtaining code sections, for example.

Docs and example have also been updated.

Ciao

Max
Re: Protect package - A starting copy protection system [message #28888 is a reply to message #28877] Thu, 23 September 2010 17:05 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
Does somebody have the sources (C, possibly....) of the snow 2.0 cypher algorhitm ? I've looked at their website and is gone... Also googling around didn't give me hints.
The RC4 used by now is quite weak.

Ciao

Max
Re: Protect package - A starting copy protection system [message #28890 is a reply to message #28888] Thu, 23 September 2010 20:39 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3355
Registered: August 2008
Senior Veteran
mdelfede wrote on Thu, 23 September 2010 17:05

Does somebody have the sources (C, possibly....) of the snow 2.0 cypher algorhitm ? I've looked at their website and is gone... Also googling around didn't give me hints.
The RC4 used by now is quite weak.

Ciao

Max


Hello Massimo

In AESStream you have AES, that is rather safe.

It works very well.


Best regards
Iñaki
Re: Protect package - A starting copy protection system [message #28892 is a reply to message #28890] Fri, 24 September 2010 10:13 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
Hi Koldo,

I'll try it, maybe.
I would have liked a builtin solution, as I need to encrypt short pieces of code and I guess there is need to change somehow the key from one to another to keep it safe.
Having many small chunks encrypted with the same key (and same startpoint of key random generation) is the best way to have your key cracked Smile

Thank you for the hint !

Ciao

Max
Re: Protect package - A starting copy protection system [message #28904 is a reply to message #28892] Sat, 25 September 2010 13:36 Go to previous messageGo to next message
Zbych is currently offline  Zbych
Messages: 325
Registered: July 2009
Senior Member
AES is quite small. See attached files that implement AES256 encryption. I use them on small 8-bit uC like AVR.
  • Attachment: aes256.zip
    (Size: 2.79KB, Downloaded 410 times)
Re: Protect package - A starting copy protection system [message #28908 is a reply to message #28904] Sat, 25 September 2010 15:37 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
Zbych wrote on Sat, 25 September 2010 13:36

AES is quite small. See attached files that implement AES256 encryption. I use them on small 8-bit uC like AVR.



Hi Zbych,

thank you for the source Smile
As I see, AES is a block-encoder with a blocksize of 128 bits and a keysize of 128, 192 or 256 bits, right ?
If so, I'll have to adapt it to my routines, as they need to encode/decode variable sized buffers.
Just one question : if I encode 2 128 bit blocks, let's say block 1 and block 2, and I want to decode them in reverse order, like block 2 and then block 1, shall I care about something, like resetting the encoder between blocks ?

Ciao

Max
Re: Protect package - A starting copy protection system [message #28909 is a reply to message #28908] Sat, 25 September 2010 18:03 Go to previous messageGo to next message
Zbych is currently offline  Zbych
Messages: 325
Registered: July 2009
Senior Member
Those routines implement ECB (electronic codebook) mode. That means that every block of data is encoded separately. It is safer to use CBC mode with long data streams.

http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation

If you use ECB mode, you don't have to reset encoder, just initialize ctx at the begging. Since you want to encrypt blocks of code, you can tell compiler to align code to 16 bytes (in case of gcc you can add inline assembly with align directive).

Re: Protect package - A starting copy protection system [message #28910 is a reply to message #28909] Sat, 25 September 2010 18:59 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
Ah, ok, I got it Smile

Anyways, I need to cypher each code routine separately, as they are decyphered in random order (when they're used), so I guess I could do CBC restarting it on each encrypted routine... Or, maybe, use CBC plus some random data added at beginning of each routine, which should lead to different coding even for identical routines.
The most annoying problem is the need of padding to 128 bits buffer, which makes it impossible to code directly on place.

Thank you for your hints Smile

Ciao

Max
Re: Protect package - A starting copy protection system [message #28976 is a reply to message #28910] Wed, 29 September 2010 22:29 Go to previous messageGo to next message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
Well, I finally found Snow2 code, so I replaced the endoding method in Protect package from RC4 to Snow2.
This brings far more encryption security at the expense of a small increment of code footprint.
A small caveat : Snow2 requires a key of fixed length of 16 OR 32 bytes (128 or 256 bits); other keylengths are NOT supported.

The encryption code is removed from Protect package and added as a new (StreamCypher) package wich implements both RC4 and Snow2 encodings.

Ciao

Max
Re: Protect package - A starting copy protection system [message #28994 is a reply to message #28976] Thu, 30 September 2010 21:30 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi Max,

Great stuff. Can't wait to get the time to get to know it better.

BTW: Do you take suggestions? If you do, may I suggest adding detection of and protection against common cracking debuggers such as SoftICE and like? This kind of reverse engineering protection is commonly found on the commercial protection products such as former Aladdin HASP HL now Safenet Sentinel HASP HL and Matrix Software Protection.

Best regards,

Tom

Re: Protect package - A starting copy protection system [message #28998 is a reply to message #28994] Thu, 30 September 2010 22:59 Go to previous messageGo to previous message
mdelfede is currently offline  mdelfede
Messages: 1307
Registered: September 2007
Ultimate Contributor
Eh. Tom... SoftICE detecting is quite windows-specific, and I develop on Unix only Smile
I'd need some window system programmer to partecipate on the package.
BTW, I think that to make it a semi-professional copy protection package we should add much more hardening stuffs, which is quite difficult keeping it portable between both worlds (and maybe also to other platforms).

Anyways, dolik-rce and I we're preparing a web-authentication module to be used together with Protect, which will allow registering and auth through a web server, which, BTW, is a thing I need for my app Smile

Next I could try to give a look to some dongle auth stuff, I'm good enough on electronics, so I could develop a dongle hardware well suited to Protect package, and I've got also an electronic manufacturer that can prototype it even in small quantities for few money Smile
I've already some ideas on how to do it... Just no time by now ! Sad

Ciao

Max

Previous Topic: UPDATED PROTECT PACKAGE
Next Topic: OAuth2 package for U++
Goto Forum:
  


Current Time: Thu Mar 28 16:36:30 CET 2024

Total time taken to generate the page: 0.01899 seconds