Here's a proof of concept.
This will "encrypt" (scramble, rather) the strings at compile time and decrypt at runtime.
#ifndef SCRAMBLEH<br />
#define SCRAMBLEH<br />
<br />
<br />
<br />
<br />
#define STRING_SCRAMBLE(s00, s01, s02, s03, s04, s05, s06, s07, s08, s09, \<br />
s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, \<br />
s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, \<br />
s30, s31) \<br />
{ \<br />
char(s00 ^ 0xa3), \<br />
char(s01 ^ 0x54), \<br />
char(s02 ^ 0xff), \<br />
char(s03 ^ 0x75), \<br />
char(s04 ^ 0xe7), \<br />
char(s05 ^ 0x44), \<br />
char(s06 ^ 0x4b), \<br />
char(s07 ^ 0x23), \<br />
char(s08 ^ 0xbf), \<br />
char(s09 ^ 0x45), \<br />
char(s10 ^ 0x3b), \<br />
char(s11 ^ 0x56), \<br />
char(s12 ^ 0xf8), \<br />
char(s13 ^ 0x98), \<br />
char(s14 ^ 0x5b), \<br />
char(s15 ^ 0xf4), \<br />
char(s16 ^ 0xb5), \<br />
char(s17 ^ 0x87), \<br />
char(s18 ^ 0x7b), \<br />
char(s19 ^ 0x0f), \<br />
char(s20 ^ 0xf4), \<br />
char(s21 ^ 0x76), \<br />
char(s22 ^ 0xb9), \<br />
char(s23 ^ 0x34), \<br />
char(s24 ^ 0xbf), \<br />
char(s25 ^ 0x1e), \<br />
char(s26 ^ 0xe7), \<br />
char(s27 ^ 0x78), \<br />
char(s28 ^ 0x98), \<br />
char(s29 ^ 0xe9), \<br />
char(s30 ^ 0x6f), \<br />
char(s31 ^ 0xb4), \<br />
'\0' \<br />
} <br />
<br />
#define LICENSE_STRING_CHECKSUM(s) \<br />
(s[ 0] << 0) ^ \<br />
(s[ 1] << 8) ^ \<br />
(s[ 2] << 16) ^ \<br />
(s[ 3] << 0) ^ \<br />
(s[ 4] << 8) ^ \<br />
(s[ 5] << 16) ^ \<br />
(s[ 6] << 24) ^ \<br />
(s[ 7] << 8) ^ \<br />
(s[ 8] << 0) ^ \<br />
(s[ 9] << 8) ^ \<br />
(s[10] << 16) ^ \<br />
(s[11] << 24) ^ \<br />
(s[12] << 0) ^ \<br />
(s[13] << 8) ^ \<br />
(s[14] << 16) ^ \<br />
(s[15] << 24) ^ \<br />
(s[16] << 0) ^ \<br />
(s[17] << 8) ^ \<br />
(s[18] << 16) ^ \<br />
(s[19] << 24) ^ \<br />
(s[20] << 0) ^ \<br />
(s[21] << 8) ^ \<br />
(s[22] << 16) ^ \<br />
(s[23] << 24) ^ \<br />
(s[24] << 0) ^ \<br />
(s[25] << 8) ^ \<br />
(s[26] << 16) ^ \<br />
(s[27] << 24) ^ \<br />
(s[28] << 0) ^ \<br />
(s[29] << 8) ^ \<br />
(s[30] << 16) ^ \<br />
(s[31] << 24)<br />
<br />
<br />
extern "C" void __cdecl exit(int);<br />
<br />
inline char* __STRING_UNSCRAMBLE(const char s[], char clear[32], <br />
unsigned compileTimeChksum) <br />
{ <br />
unsigned curChksum = STRING_CHECKSUM(s);<br />
<br />
if (compileTimeChksum != curChksum) <br />
exit(0);<br />
<br />
char temp[] =<br />
STRING_SCRAMBLE(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], <br />
s[10], s[11], s[12], s[13], s[14], s[15], s[16], s[17], s[18], s[19], <br />
s[20], s[21], s[22], s[23], s[24], s[25], s[26], s[27], s[28], s[29],<br />
s[30], s[31]);<br />
<br />
for (unsigned i = 0; i < 32; i++)<br />
clear[i] = temp[i];<br />
<br />
return (char*)clear; <br />
};<br />
<br />
<br />
#define STRING_DECL(NAME) \<br />
extern const char NAME ## _Scrambled[]; \<br />
extern char NAME ## _Clear[32]; \<br />
extern const unsigned NAME ## _CheckSum;<br />
<br />
#define STRING_UNSCRAMBLE(NAME) \<br />
__STRING_UNSCRAMBLE(NAME ## _Scrambled, NAME ## _Clear, NAME ## _CheckSum)<br />
<br />
#define STRING_DEF(NAME, VALUE) \<br />
const char NAME ## _Scrambled[] = STRING_SCRAMBLE VALUE; \<br />
char NAME ## _Clear[32]; \<br />
const unsigned NAME ## _CheckSum = STRING_CHECKSUM(NAME ## _Scrambled);<br />
<br />
<br />
#endif
(Obviously, change the encryption key...)
Downside: hardcoded 32-character length for strings (could perhaps be expanded), and all the downsides CXR has. Benefits: does not require extra build step.
|