|
|
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 |
mdelfede
Messages: 1308 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 |
|
Hi Max!
This is a very interesting package. I couldn't resist and played with it for a while 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
Good job!
Honza
|
|
|
|
Re: Protect package - A starting copy protection system [message #28857 is a reply to message #28854] |
Mon, 20 September 2010 10:02 |
mdelfede
Messages: 1308 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 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
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
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
|
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 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
Thank you
Ciao
Max
|
|
|
Re: Protect package - A starting copy protection system [message #28862 is a reply to message #28857] |
Mon, 20 September 2010 13:57 |
mdelfede
Messages: 1308 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 #28867 is a reply to message #28866] |
Mon, 20 September 2010 21:38 |
mdelfede
Messages: 1308 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
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 #28869 is a reply to message #28868] |
Mon, 20 September 2010 23:38 |
mdelfede
Messages: 1308 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
|
Point taken I don't know why I always miss the simple solutions
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 #28908 is a reply to message #28904] |
Sat, 25 September 2010 15:37 |
mdelfede
Messages: 1308 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
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 #28910 is a reply to message #28909] |
Sat, 25 September 2010 18:59 |
mdelfede
Messages: 1308 Registered: September 2007
|
Ultimate Contributor |
|
|
Ah, ok, I got it
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
Ciao
Max
|
|
|
|
Re: Protect package - A starting copy protection system [message #28994 is a reply to message #28976] |
Thu, 30 September 2010 21:30 |
Tom1
Messages: 1253 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 |
mdelfede
Messages: 1308 Registered: September 2007
|
Ultimate Contributor |
|
|
Eh. Tom... SoftICE detecting is quite windows-specific, and I develop on Unix only
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
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
I've already some ideas on how to do it... Just no time by now !
Ciao
Max
|
|
|
Goto Forum:
Current Time: Sun Nov 10 20:47:12 CET 2024
Total time taken to generate the page: 0.03771 seconds
|
|
|