#ifndef _Protect_h_ #define _Protect_h_ #include #include 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 #ifdef flagMT #define PROTECT_START_FUNC1(decrFunc) \ static volatile bool __decrypted = false; \ INTERLOCKED \ { \ if(!__decrypted) \ { \ PROTECT_WRITE_ACCESS((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, true); \ decrFunc((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, (byte *)&&__init + 2, 6 /* sizeof(PROTECT_START_MARK) */); \ PROTECT_WRITE_ACCESS((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, false); \ __decrypted = true; \ asm volatile ( \ "\txor %%eax, %%eax\n" \ "\tcpuid\n" \ : \ : \ : "eax", "ebx", "ecx", "edx" \ ); \ } \ } /* THIS BECAUSE THEIDE HANGS... */ #define PROTECT_START_FUNC2 \ if(__decrypted) \ { \ if(!__decrypted) \ { \ __init: \ asm volatile( \ "\tjmp 1f\n" \ "\t.ascii \""PROTECT_START_MARKER"\"\n" \ "1:\n" \ ); \ } \ __start: #define PROTECT_START_FUNC(DecrFunc) PROTECT_START_FUNC1(DecrFunc) PROTECT_START_FUNC2 #else #define PROTECT_START_FUNC1(decrFunc) \ static volatile bool __decrypted = false; \ if(!__decrypted) \ { \ PROTECT_WRITE_ACCESS((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, true); \ decrFunc((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, (byte *)&&__init + 2, 6 /* sizeof(PROTECT_START_MARK) */); \ PROTECT_WRITE_ACCESS((byte *)&&__start, (byte *)&&__end - (byte *)&&__start, false); \ __decrypted = true; \ asm volatile ( \ "\txor %%eax, %%eax\n" \ "\tcpuid\n" \ : \ : \ : "eax", "ebx", "ecx", "edx" \ ); \ } /* THIS BECAUSE THEIDE HANGS... */ #define PROTECT_START_FUNC2 \ if(__decrypted) \ { \ if(!__decrypted) \ { \ __init: \ asm volatile( \ "\tjmp 1f\n" \ "\t.ascii \""PROTECT_START_MARKER"\"\n" \ "1:\n" \ ); \ } \ __start: #define PROTECT_START_FUNC(DecrFunc) PROTECT_START_FUNC1(DecrFunc) PROTECT_START_FUNC2 #endif #define PROTECT_END_FUNC \ } \ else \ { \ __end: \ asm volatile ( \ "\tjmp 2f\n" \ "\t.ascii \""PROTECT_END_MARKER"\"\n" \ "2:\n" \ ::: \ ); \ goto __start; \ } #define OBFUSCATE_START_FUNC \ static volatile bool __xxx = false; \ PROTECT_OBFUSCATE((byte *)&&__start, (byte *)&&__end - (byte *)&&__start + 2, (byte *)&&__init + 2, 16 /* sizeof(OBFUSCATE_START_MARKER) + sizeof("0123456789") */); \ asm volatile ( \ "\txor %%eax, %%eax\n" \ "\tcpuid\n" \ : \ : \ : "eax", "ebx", "ecx", "edx" \ ); \ __xxx = true; \ if(__xxx) \ { \ __init: \ asm __volatile__( \ "\tjmp 1f\n" \ "\t.ascii \""OBFUSCATE_START_MARKER"\"\n" \ "\t.ascii \"0123456789\"\n" \ "1:\n" \ ); \ } \ __start: \ if(__xxx) \ __xxx++; #define OBFUSCATE_END_FUNC \ if(__xxx) \ __xxx++; \ __end: \ asm __volatile__( \ "\tjmp 1f\n" \ "\t.ascii \""OBFUSCATE_END_MARKER"\"\n" \ "1:\n" \ ); \ PROTECT_OBFUSCATE((byte *)&&__start, (byte *)&&__end - (byte *)&&__start + 2, (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 #ifdef flagMT #define PROTECT_START_FUNC(decrFunc) \ static volatile bool __decrypted = false; \ INTERLOCKED \ { \ byte *__startPtr, *__endPtr, *__noncePtr; \ if(!__decrypted) \ { \ __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 __noncePtr, eax \ __asm pop eax \ }; \ PROTECT_WRITE_ACCESS(__startPtr, __endPtr - __startPtr, true); \ decrFunc(__startPtr, __endPtr - __startPtr, __noncePtr, 6); \ 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; \ __init: \ __asm { \ __asm jmp __next \ _PROTECT_START_MARKER \ __asm __next: \ } \ __start: \ { #else #define PROTECT_START_FUNC(decrFunc) \ static bool __decrypted = false; \ byte *__startPtr, *__endPtr, *__noncePtr; \ if(!__decrypted) \ { \ __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 __noncePtr, eax \ __asm pop eax \ }; \ PROTECT_WRITE_ACCESS(__startPtr, __endPtr - __startPtr, true); \ decrFunc(__startPtr, __endPtr - __startPtr, __noncePtr, 6); \ 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; \ __init: \ __asm { \ __asm jmp __next \ _PROTECT_START_MARKER \ __asm __next: \ } \ __start: \ { #endif #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"); \ Bufferbuf(len); \ Buffernonce(6); \ /* can't use memcpy, it gets optimized out */ \ for(int i = 0; i < len; i++) buf[i] = crypted[i + 6 /* sizeof(PROTECT_START_MARKER)*/]; \ for(int i = 0; i < 6 /* sizeof(PROTECT_START_MARKER)*/; i++) nonce[i] = crypted[i]; \ decrFunc(buf, len, nonce, 6); \ __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, byte const *nonce, size_t nonceLen); void PROTECT_OBFUSCATE(byte *start, size_t len, byte *key, size_t keyLen); #endif