mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Bazaar/Protect : added Obfuscation, key check and updated docs
git-svn-id: svn://ultimatepp.org/upp/trunk@2717 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
7eb3190381
commit
8a462f4233
6 changed files with 412 additions and 158 deletions
|
|
@ -1,38 +1,47 @@
|
|||
#include "Protect.h"
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static bool PROTECT_WRITE_ACCESS(byte *start, size_t size, bool access)
|
||||
{
|
||||
// round start and size to page size -- needed for mprotect
|
||||
long pSize = sysconf(_SC_PAGESIZE );
|
||||
long delta = (long)start % pSize;
|
||||
if(delta)
|
||||
{
|
||||
start -= delta;
|
||||
size += delta;
|
||||
}
|
||||
return mprotect(start, size, access ? PROT_READ | PROT_WRITE | PROT_EXEC : PROT_READ | PROT_EXEC) == 0;
|
||||
}
|
||||
#else
|
||||
|
||||
static bool PROTECT_WRITE_ACCESS(byte *start, size_t size, bool access)
|
||||
{
|
||||
dword oldProt;
|
||||
bool res = VirtualProtect(start, size, access ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ, &oldProt);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool PROTECT_DECRYPT(byte *start, size_t size, String const &key)
|
||||
{
|
||||
RC4 rc4(key);
|
||||
|
||||
if(!PROTECT_WRITE_ACCESS(start, size, true))
|
||||
return false;
|
||||
rc4.Crypt(start, start, size);
|
||||
return PROTECT_WRITE_ACCESS(start, size, false);
|
||||
}
|
||||
#include "Protect.h"
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
bool PROTECT_WRITE_ACCESS(byte *start, size_t size, bool access)
|
||||
{
|
||||
// round start and size to page size -- needed for mprotect
|
||||
long pSize = sysconf(_SC_PAGESIZE );
|
||||
long delta = (long)start % pSize;
|
||||
if(delta)
|
||||
{
|
||||
start -= delta;
|
||||
size += delta;
|
||||
}
|
||||
return mprotect(start, size, access ? PROT_READ | PROT_WRITE | PROT_EXEC : PROT_READ | PROT_EXEC) == 0;
|
||||
}
|
||||
#else
|
||||
|
||||
static bool PROTECT_WRITE_ACCESS(byte *start, size_t size, bool access)
|
||||
{
|
||||
dword oldProt;
|
||||
bool res = VirtualProtect(start, size, access ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ, &oldProt);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
void PROTECT_DECRYPT(byte *start, size_t size, String const &key)
|
||||
{
|
||||
RC4 rc4(key);
|
||||
|
||||
rc4.Crypt(start, start, size);
|
||||
}
|
||||
|
||||
void PROTECT_OBFUSCATE(byte *start, size_t len, byte *key, size_t keyLen)
|
||||
{
|
||||
String k;
|
||||
for(unsigned i = 0; i < keyLen; i++)
|
||||
k += *key++;
|
||||
if(!PROTECT_WRITE_ACCESS(start, len, true))
|
||||
return;
|
||||
RC4 rc4(k);
|
||||
rc4.Crypt(start, start, len);
|
||||
PROTECT_WRITE_ACCESS(start, len, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,118 +1,218 @@
|
|||
#ifndef _Protect_h_
|
||||
#define _Protect_h_
|
||||
|
||||
#include <Core/Core.h>
|
||||
#include "RC4.h"
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
#define PROTECT_START_MARKER "\xba\xad\xde\xad\xfa\xce"
|
||||
#define PROTECT_END_MARKER "\xc0\xde\xde\xad\xfe\xed"
|
||||
|
||||
#ifdef flagPROTECT
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
|
||||
#define PROTECT_START_FUNC(decrFunc) \
|
||||
static bool __decrypted = false; \
|
||||
void (*ptr)(void); \
|
||||
dword size; \
|
||||
if(!__decrypted) \
|
||||
{ \
|
||||
decrFunc((byte *)&&__start, (byte *)&&__end - (byte *)&&__start); \
|
||||
__decrypted = true; \
|
||||
asm volatile ( \
|
||||
"\txor %%eax, %%eax\n" \
|
||||
"\tcpuid\n" \
|
||||
: \
|
||||
: \
|
||||
: "eax", "ebx", "ecx", "edx" \
|
||||
); \
|
||||
} \
|
||||
if(!__decrypted) \
|
||||
goto __end; \
|
||||
asm volatile( \
|
||||
"\tjmp 1f\n" \
|
||||
"\t.ascii \""PROTECT_START_MARKER"\"\n" \
|
||||
"1:\n" \
|
||||
); \
|
||||
__start: \
|
||||
{ \
|
||||
|
||||
#define PROTECT_END_FUNC \
|
||||
} \
|
||||
__end: \
|
||||
asm volatile ( \
|
||||
"\tjmp 2f\n" \
|
||||
"\t.ascii \""PROTECT_END_MARKER"\"\n" \
|
||||
"2:\n" \
|
||||
);
|
||||
|
||||
#else
|
||||
|
||||
#define _PROTECT_START_MARKER __asm _emit 0xba __asm _emit 0xad __asm _emit 0xde __asm _emit 0xad __asm _emit 0xfa __asm _emit 0xce
|
||||
#define _PROTECT_END_MARKER __asm _emit 0xc0 __asm _emit 0xde __asm _emit 0xde __asm _emit 0xad __asm _emit 0xfe __asm _emit 0xed
|
||||
|
||||
#define PROTECT_START_FUNC(decrFunc) \
|
||||
static bool __decrypted = false; \
|
||||
byte *start, *end; \
|
||||
if(!__decrypted) \
|
||||
{ \
|
||||
__asm \
|
||||
{ \
|
||||
__asm lea eax, __start \
|
||||
__asm mov start, eax \
|
||||
__asm lea eax, __end \
|
||||
__asm mov end, eax \
|
||||
}; \
|
||||
decrFunc(start, end - start); \
|
||||
__decrypted = true; \
|
||||
__asm \
|
||||
{ \
|
||||
__asm push eax \
|
||||
__asm push ebx \
|
||||
__asm push ecx \
|
||||
__asm push edx \
|
||||
__asm xor eax, eax \
|
||||
__asm cpuid \
|
||||
__asm pop edx \
|
||||
__asm pop ecx \
|
||||
__asm pop ebx \
|
||||
__asm pop eax \
|
||||
__asm lea eax, __start \
|
||||
__asm mov start, eax \
|
||||
__asm lea eax, __end \
|
||||
__asm mov end, eax \
|
||||
}; \
|
||||
} \
|
||||
if(!__decrypted) \
|
||||
goto __end; \
|
||||
__asm { \
|
||||
__asm jmp next \
|
||||
_PROTECT_START_MARKER \
|
||||
__asm next: \
|
||||
} \
|
||||
__start: \
|
||||
{ \
|
||||
|
||||
#define PROTECT_END_FUNC \
|
||||
} \
|
||||
__end: \
|
||||
__asm { \
|
||||
__asm jmp next2 \
|
||||
_PROTECT_END_MARKER \
|
||||
__asm next2: \
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define PROTECT_START_FUNC(decrFunc)
|
||||
#define PROTECT_END_FUNC
|
||||
|
||||
#endif
|
||||
|
||||
bool PROTECT_DECRYPT(byte *start, size_t size, String const &key);
|
||||
|
||||
#endif
|
||||
#ifndef _Protect_h_
|
||||
#define _Protect_h_
|
||||
|
||||
#include <Core/Core.h>
|
||||
#include "RC4.h"
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
#define PROTECT_START_MARKER "\xba\xad\xde\xad\xfa\xce"
|
||||
#define PROTECT_END_MARKER "\xc0\xde\xde\xad\xfe\xed"
|
||||
|
||||
#define OBFUSCATE_START_MARKER "\xba\xad\xde\xad\xfa\xde"
|
||||
#define OBFUSCATE_END_MARKER "\xc0\xde\xde\xad\xfe\xde"
|
||||
|
||||
#ifdef flagPROTECT
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
|
||||
#define PROTECT_START_FUNC(decrFunc) \
|
||||
static bool __decrypted = false; \
|
||||
if(!__decrypted) \
|
||||
{ \
|
||||
PROTECT_WRITE_ACCESS((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, true); \
|
||||
decrFunc((byte *)&&__start, (byte *)&&__end - (byte *)&&__start); \
|
||||
PROTECT_WRITE_ACCESS((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, false); \
|
||||
__decrypted = true; \
|
||||
asm volatile ( \
|
||||
"\txor %%eax, %%eax\n" \
|
||||
"\tcpuid\n" \
|
||||
: \
|
||||
: \
|
||||
: "eax", "ebx", "ecx", "edx" \
|
||||
); \
|
||||
} \
|
||||
if(!__decrypted) \
|
||||
goto __end; \
|
||||
asm volatile( \
|
||||
"\tjmp 1f\n" \
|
||||
"\t.ascii \""PROTECT_START_MARKER"\"\n" \
|
||||
"1:\n" \
|
||||
); \
|
||||
__start: \
|
||||
{ \
|
||||
|
||||
#define PROTECT_END_FUNC \
|
||||
} \
|
||||
__end: \
|
||||
asm volatile ( \
|
||||
"\tjmp 2f\n" \
|
||||
"\t.ascii \""PROTECT_END_MARKER"\"\n" \
|
||||
"2:\n" \
|
||||
);
|
||||
|
||||
#define OBFUSCATE_START_FUNC \
|
||||
PROTECT_OBFUSCATE((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, (byte *)&&__init + 2, 16 /* sizeof(OBFUSCATE_START_MARKER) + sizeof("0123456789") */); \
|
||||
asm volatile ( \
|
||||
"\txor %%eax, %%eax\n" \
|
||||
"\tcpuid\n" \
|
||||
: \
|
||||
: \
|
||||
: "eax", "ebx", "ecx", "edx" \
|
||||
); \
|
||||
__init: \
|
||||
asm volatile( \
|
||||
"\tjmp 1f\n" \
|
||||
"\t.ascii \""OBFUSCATE_START_MARKER"\"\n" \
|
||||
"\t.ascii \"0123456789\"\n" \
|
||||
"1:\n" \
|
||||
); \
|
||||
__start:
|
||||
|
||||
#define OBFUSCATE_END_FUNC \
|
||||
asm volatile( \
|
||||
"\tjmp 1f\n" \
|
||||
"\t.ascii \""OBFUSCATE_END_MARKER"\"\n" \
|
||||
"1:\n" \
|
||||
); \
|
||||
__end: \
|
||||
PROTECT_OBFUSCATE((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, (byte *)&&__init + 2, 16 /* sizeof(OBFUSCATE_START_MARKER) + sizeof("0123456789") */)
|
||||
|
||||
#else
|
||||
|
||||
#define _PROTECT_START_MARKER __asm _emit 0xba __asm _emit 0xad __asm _emit 0xde __asm _emit 0xad __asm _emit 0xfa __asm _emit 0xce
|
||||
#define _PROTECT_END_MARKER __asm _emit 0xc0 __asm _emit 0xde __asm _emit 0xde __asm _emit 0xad __asm _emit 0xfe __asm _emit 0xed
|
||||
|
||||
#define _OBFUSCATE_START_MARKER __asm _emit 0xba __asm _emit 0xad __asm _emit 0xde __asm _emit 0xad __asm _emit 0xfa __asm _emit 0xde
|
||||
#define _OBFUSCATE_END_MARKER __asm _emit 0xc0 __asm _emit 0xde __asm _emit 0xde __asm _emit 0xad __asm _emit 0xfe __asm _emit 0xde
|
||||
#define _OBFUSCATE_KEYPLACER __asm _emit 0x00 __asm _emit 0x01 __asm _emit 0x02 __asm _emit 0x03 __asm _emit 0x04 __asm _emit 0x05 __asm _emit 0x06 __asm _emit 0x07 __asm _emit 0x08 __asm _emit 0x09
|
||||
|
||||
#define PROTECT_START_FUNC(decrFunc) \
|
||||
static bool __decrypted = false; \
|
||||
byte *__startPtr, *__endPtr; \
|
||||
if(!__decrypted) \
|
||||
{ \
|
||||
__asm \
|
||||
{ \
|
||||
__asm push eax \
|
||||
__asm lea eax, __start \
|
||||
__asm mov __startPtr, eax \
|
||||
__asm lea eax, __end \
|
||||
__asm mov __endPtr, eax \
|
||||
__asm pop eax \
|
||||
}; \
|
||||
PROTECT_WRITE_ACCESS(__startPtr, __endPtr - __startPtr, true); \
|
||||
decrFunc(__startPtr, __endPtr - __startPtr); \
|
||||
PROTECT_WRITE_ACCESS(__startPtr, __endPtr - __startPtr, false); \
|
||||
__decrypted = true; \
|
||||
__asm \
|
||||
{ \
|
||||
__asm push eax \
|
||||
__asm push ebx \
|
||||
__asm push ecx \
|
||||
__asm push edx \
|
||||
__asm xor eax, eax \
|
||||
__asm cpuid \
|
||||
__asm pop edx \
|
||||
__asm pop ecx \
|
||||
__asm pop ebx \
|
||||
__asm pop eax \
|
||||
}; \
|
||||
} \
|
||||
if(!__decrypted) \
|
||||
goto __end; \
|
||||
__asm { \
|
||||
__asm jmp __next \
|
||||
_PROTECT_START_MARKER \
|
||||
__asm __next: \
|
||||
} \
|
||||
__start: \
|
||||
{ \
|
||||
|
||||
#define PROTECT_END_FUNC \
|
||||
} \
|
||||
__end: \
|
||||
__asm { \
|
||||
__asm jmp __next2 \
|
||||
_PROTECT_END_MARKER \
|
||||
__asm __next2: \
|
||||
};
|
||||
|
||||
#define OBFUSCATE_START_FUNC \
|
||||
byte *__startPtr, *__endPtr, *__keyPtr; \
|
||||
__asm \
|
||||
{ \
|
||||
__asm push eax \
|
||||
__asm lea eax, __start \
|
||||
__asm mov __startPtr, eax \
|
||||
__asm lea eax, __end \
|
||||
__asm mov __endPtr, eax \
|
||||
__asm lea eax, __init \
|
||||
__asm inc eax \
|
||||
__asm inc eax \
|
||||
__asm mov __keyPtr, eax \
|
||||
__asm pop eax \
|
||||
}; \
|
||||
PROTECT_OBFUSCATE(__startPtr, __endPtr - __startPtr, __keyPtr, 16); \
|
||||
__asm \
|
||||
{ \
|
||||
__asm push eax \
|
||||
__asm push ebx \
|
||||
__asm push ecx \
|
||||
__asm push edx \
|
||||
__asm xor eax, eax \
|
||||
__asm cpuid \
|
||||
__asm pop edx \
|
||||
__asm pop ecx \
|
||||
__asm pop ebx \
|
||||
__asm pop eax \
|
||||
}; \
|
||||
__init: \
|
||||
__asm { \
|
||||
__asm jmp __next \
|
||||
_OBFUSCATE_START_MARKER \
|
||||
_OBFUSCATE_KEYPLACER \
|
||||
__asm __next: \
|
||||
} \
|
||||
__start: \
|
||||
|
||||
#define OBFUSCATE_END_FUNC \
|
||||
__asm { \
|
||||
__asm jmp __next2 \
|
||||
_OBFUSCATE_END_MARKER \
|
||||
__asm __next2: \
|
||||
}; \
|
||||
__end: \
|
||||
PROTECT_OBFUSCATE(__startPtr, __endPtr - __startPtr, __keyPtr, 16)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// Check macro for program startup -- executes next statement if invalid key
|
||||
#define ON_PROTECT_BAD_KEY(decrFunc) \
|
||||
bool __keyOk; \
|
||||
{ \
|
||||
const char *crypted = PROTECT_START_MARKER "abracadabra" PROTECT_END_MARKER; \
|
||||
const int len = strlen("abracadabra"); \
|
||||
Buffer<byte>buf(len); \
|
||||
memcpy(buf, crypted + 6 /* sizeof(PROTECT_START_MARKER)*/, len); \
|
||||
decrFunc(buf, len); \
|
||||
__keyOk = !memcmp(buf, "abracadabra", len); \
|
||||
} \
|
||||
if(!__keyOk)
|
||||
|
||||
#else
|
||||
|
||||
#define PROTECT_START_FUNC(decrFunc)
|
||||
#define PROTECT_END_FUNC
|
||||
#define OBFUSCATE_START_FUNC
|
||||
#define OBFUSCATE_END_FUNC
|
||||
#define ON_PROTECT_BAD_KEY(decrFunc) if(false)
|
||||
|
||||
#endif
|
||||
|
||||
bool PROTECT_WRITE_ACCESS(byte *start, size_t size, bool access);
|
||||
void PROTECT_DECRYPT(byte *start, size_t size, String const &key);
|
||||
void PROTECT_OBFUSCATE(byte *start, size_t len, byte *key, size_t keyLen);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -49,3 +49,22 @@ void RC4::Crypt(byte *src, byte *dst, size_t len)
|
|||
*dst++ = *src++ ^ sbox[swap];
|
||||
}
|
||||
}
|
||||
|
||||
String RC4::Crypt(String const &s)
|
||||
{
|
||||
unsigned char swap;
|
||||
int i = 0;
|
||||
int len = s.GetCount();
|
||||
String res;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
sj += sbox[++si];
|
||||
swap = sbox[si];
|
||||
sbox[si] = sbox[sj];
|
||||
sbox[sj] = swap;
|
||||
swap = sbox[si] + sbox[sj];
|
||||
res += s[i++] ^ sbox[swap];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class RC4
|
|||
RC4(String const &key);
|
||||
void SetKey(String const &key);
|
||||
void Crypt(byte *src, byte *dst, size_t len);
|
||||
String Crypt(String const &s);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -941,10 +941,54 @@ FF`" );]&]
|
|||
file, from internet or generated by a combination of machine
|
||||
identification number and a license key.&]
|
||||
[s0; &]
|
||||
[s0; You can also check for key correctness on app startup, and abort
|
||||
the app if key is incorrect; the macro [* ON`_PROTECT`_BAD`_KEY(decrFunc)]
|
||||
executes a block of code only if the key isn`'t correct. Here
|
||||
an example usage :&]
|
||||
[s0; &]
|
||||
[s0;l128; [*/ ON`_PROTECT`_BAD`_KEY(decrFunc)]&]
|
||||
[s0;l128; [/ `{]&]
|
||||
[s0;l128; [/ -|PromptOK(`"License error`");]&]
|
||||
[s0;l128; [/ -|exit(1);]&]
|
||||
[s0;l128; [/ `}]&]
|
||||
[s0;l128; &]
|
||||
[s0; That`'s all ! If you build your application with TheIde, selecting
|
||||
the [* GUI PROTECT ]main configuration, it`'ll be automatically
|
||||
built and encrypted with the key you`'ve chosen.&]
|
||||
[s0; You can see all that working in ProtectTest demo application;
|
||||
if you change the key in its [* GetKey()] function your app will
|
||||
crash upon run; if the key is correct, it`'ll run normally.&]
|
||||
[s0; ]
|
||||
signal the license error upon run, giving the user the choice
|
||||
of exiting the app or continue anyways. Of course, if you choose
|
||||
to continue, the app will crash.&]
|
||||
[s0; If the key is correct, no alert is shown and the app runs normally.&]
|
||||
[s0; &]
|
||||
[s0; A note : the macros [* PROTECT`_START`_FUNC()] and [* PROTECT`_END`_FUNC]
|
||||
creates an internal block of code enclosed by a couple of `{`},
|
||||
for technical reasons. The caveat is that [*/ any][* ]variable defined
|
||||
[*/ inside ]the macro couple will not be visible from the outside.
|
||||
So :&]
|
||||
[s0; &]
|
||||
[s0;l160; [/ -|][*/ PROTECT`_START`_FUNC(Decrypt);]&]
|
||||
[s0;l160; [/ -|int i `= 10;]&]
|
||||
[s0;l160; [/ -|][*/ PROTECT`_END`_FUNC;]&]
|
||||
[s0;l160; [*/ -|][/ return i;]&]
|
||||
[s0; &]
|
||||
[s0; Will give an error because of undefined variable i; the solution
|
||||
is to put variable definition [/ before ][* PROTECT`_START`_FUNC]
|
||||
or the return statement [/ inside ]the macro couple :&]
|
||||
[s0; &]
|
||||
[s0; &]
|
||||
[s0;l160; [/ -|int i `= 10;]&]
|
||||
[s0;l160; [/ -|][*/ PROTECT`_START`_FUNC(Decrypt);]&]
|
||||
[s0;l160; [/ -|][*/ PROTECT`_END`_FUNC;]&]
|
||||
[s0;l160; [*/ -|][/ return i;]&]
|
||||
[s0; &]
|
||||
[s0; or&]
|
||||
[s0; &]
|
||||
[s0;l160; [/ -|][*/ PROTECT`_START`_FUNC(Decrypt);]&]
|
||||
[s0;l160; [/ -|int i `= 10;]&]
|
||||
[s0;l160; [*/ -|][/ return i;]&]
|
||||
[s0;l160; [/ -|][*/ PROTECT`_END`_FUNC;]&]
|
||||
[s0; &]
|
||||
[s0; On next chapter we`'ll introduce another kind of copy protection
|
||||
tool named [^topic`:`/`/Protect`/srcdoc`/Obfuscation`$en`-us^ obfuscation].]
|
||||
81
bazaar/Protect/srcdoc.tpp/Obfuscation$en-us.tpp
Normal file
81
bazaar/Protect/srcdoc.tpp/Obfuscation$en-us.tpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
topic "Code Obfuscation";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[{_}%EN-US
|
||||
[s0;%- [*R6 Code Obfuscation]&]
|
||||
[s0;/%- &]
|
||||
[s0; As you can easily understand, the [^topic`:`/`/Protect`/srcdoc`/HowItWorks`$en`-us^ e
|
||||
ncryption method proposed earlier] has 2 flaws :&]
|
||||
[s0; &]
|
||||
[s0;i150;O0; The decrypting code is visible and traceable&]
|
||||
[s0; &]
|
||||
[s0;i150;O0; You must obtain the key [*/ before ]the decryption phase&]
|
||||
[s0; &]
|
||||
[s0; The first point is not so important: even if that`'s true that
|
||||
user can step the decryptor and get the real code, he must do
|
||||
it for every function you did protect, record the code, repatch
|
||||
the executable in many places (they can be hundreds, if needed),
|
||||
disable the decryption parts, and so on.... an huge work, often
|
||||
not worth the time spent. And, of course, if your app is so valuable
|
||||
you can resort to a commercial tool !&]
|
||||
[s0; &]
|
||||
[s0; Second point is somehow more sensitive : if the cracker gets
|
||||
the key, he can write a tool that automatically decrypts and
|
||||
patch your application in short time, even if it contains hundred
|
||||
of protected functions. Is not so easy, but can be done in a
|
||||
reasonable time.&]
|
||||
[s0; A perfect solution for that doesn`'t exist... of course. But,
|
||||
we can make cracker`'s live a bit more difficult if we encrypt
|
||||
somehow also sensitive parts of code with a random key.&]
|
||||
[s0; This is done by another couple of macros :&]
|
||||
[s0; &]
|
||||
[s0;l160; [/ void MyObfuscatedFunction(void)]&]
|
||||
[s0;l160; [/ `{]&]
|
||||
[s0;l160; [/ -|][*/ OBFUSCATE`_START`_FUNC;]&]
|
||||
[s0;l160;/ &]
|
||||
[s0;l160; [/ -|<here my function code>]&]
|
||||
[s0;l160;/ &]
|
||||
[s0;l160; [/ -|][*/ OBFUSCATE`_END`_FUNC;]&]
|
||||
[s0;l160;/ &]
|
||||
[s0;l160; [/ `}]&]
|
||||
[s0; &]
|
||||
[s0; You can notice that the [* decrFunc ]parameter is gone. The macro
|
||||
generates a random, 16 byte long key, different for each obfuscated
|
||||
function. The key is stored into the executable and automatically
|
||||
used to decrypt the code on the fly when needed [*/ and ]to reencrypt
|
||||
it at function exit.&]
|
||||
[s0; The code will run anyways, it won`'t check any key, so what`'s
|
||||
the purpose ?&]
|
||||
[s0; Is simply to defeat disassemblers and to make function tracing
|
||||
quite hard.&]
|
||||
[s0; The disassembler would see just garbage bytes, as the function
|
||||
is stored in encrypted form. If you try to trace it step by step
|
||||
with a debugger, the function will be unencrypted just when needed,
|
||||
and re`-encrypted on exit, which confuses many debuggers (TheIde
|
||||
GDB frontend is `*very`* confused about it :`-) )&]
|
||||
[s0; You`'d normally use [* Obfuscation ]when obtaining your key used
|
||||
to decrypt the [* Protected ]parts, mostly on code startup and
|
||||
on some sensitive parts which needs to be executed [/ before ]the
|
||||
key is available.&]
|
||||
[s0; &]
|
||||
[s0; A note : as opposite as [* PROTECT`_xxx`_FUNC()] macro block, the
|
||||
[* OBFUSCATE`_xxx`_FUNC] one [/ doesn`'t] create an enclosed code
|
||||
block, so the visibility of variable is [/ global ]to function;
|
||||
more important, the code [*/ MUST ]reach the end macro in order
|
||||
to [*/ re`-obfuscate] itself. That means that you [*/ can`'t] put
|
||||
[*/ any] return statement inside the obfuscation block. If you
|
||||
do, your app will crash if the obfuscated function is executed
|
||||
twice. So :&]
|
||||
[s0; &]
|
||||
[s0;l160; [/ -|][*/ OBFUSCATE`_START`_FUNC;]&]
|
||||
[s0;l160; [*/ -|][/ <some code here>]&]
|
||||
[s0;l160; [/ -|return;]&]
|
||||
[s0;l160; [/ -|][*/ OBFUSCATE`_END`_FUNC;]&]
|
||||
[s0; &]
|
||||
[s0; Is [*/ WRONG ]and will make your app crash on second function
|
||||
invocation; the right approach is :&]
|
||||
[s0; &]
|
||||
[s0;l160; [/ -|][*/ OBFUSCATE`_START`_FUNC;]&]
|
||||
[s0;l160; [*/ -|][/ <some code here>]&]
|
||||
[s0;l160; [/ -|][*/ OBFUSCATE`_END`_FUNC;]&]
|
||||
[s0;l160; [/ -|return;]&]
|
||||
[s0; ]
|
||||
Loading…
Add table
Add a link
Reference in a new issue