C++ 编译时字符串加密
C++源代码虽然被反编译不太可能,但写在源代码里的常量字符串却在有些情况下会泄漏一些重要信息。比如 sql 语句、数据库连接字符串、密码、密钥等等。
用户通过PEEdit之类的软件不但可以看到,还可以修改以后将文件另存为一个新的PE文件,并且程序也会按照修改后的预期运行。如果在对程序安全性要求比较高的场景下,这个也是需要考虑的。按照一般人第一思路,想到的应该是写一个对称加密算法,在代码里写密文,调用算法解密,PE文件里就看不到了,这样当然可以。可是有一个缺陷,它的可读性很差,密文过得时间长了,可能连自己都忘记原文是什么了。
国外网站上有人推荐了一个办法,经试验是没有问题的。据说C++11以后的代码都可以使用。
#include <iostream> // ============================================================================= namespace crypt { // ============================================================================= // compile-time seed #define XSTR_SEED ((__TIME__[7] - '0') * 1ull + (__TIME__[6] - '0') * 10ull + \ (__TIME__[4] - '0') * 60ull + (__TIME__[3] - '0') * 600ull + \ (__TIME__[1] - '0') * 3600ull + (__TIME__[0] - '0') * 36000ull) // ----------------------------------------------------------------------------- // @return a pseudo random number clamped at 0xFFFFFFFF constexpr unsigned long long linear_congruent_generator(unsigned rounds) { return 1013904223ull + (1664525ull * ((rounds> 0) ? linear_congruent_generator(rounds - 1) : (XSTR_SEED) )) % 0xFFFFFFFF; } // ----------------------------------------------------------------------------- #define Random() linear_congruent_generator(10) #define XSTR_RANDOM_NUMBER(Min, Max) (Min + (Random() % (Max - Min + 1))) // ----------------------------------------------------------------------------- constexpr const unsigned long long XORKEY = XSTR_RANDOM_NUMBER(0, 0xFF); // ----------------------------------------------------------------------------- template<typename Char > constexpr Char encrypt_character(const Char character, int index) { return character ^ (static_cast<Char>(XORKEY) + index); } // ----------------------------------------------------------------------------- template <unsigned size, typename Char> class Xor_string { public: const unsigned _nb_chars = (size - 1); Char _string[size]; // if every goes alright this constructor should be executed at compile time inline constexpr Xor_string(const Char* string) : _string{} { for(unsigned i = 0u; i < size; ++i) _string[i] = encrypt_character<Char>(string[i], i); } // This is executed at runtime. // HACK: although decrypt() is const we modify '_string' in place const Char* decrypt() const { Char* string = const_cast<Char*>(_string); for(unsigned t = 0; t < _nb_chars; t++) { string[t] = string[t] ^ (static_cast<Char>(XORKEY) + t); } string[_nb_chars] = '\0'; return string; } }; }// END crypt NAMESPACE ======================================================== #define XorS(name, my_string) constexpr crypt::Xor_string<(sizeof(my_string)/sizeof(char)), char> name(my_string) // Because of a limitation/bug in msvc 2017 we need to declare crypt::Xor_string() as a constexpr // otherwise the constructor is not evaluated at compile time. The lambda function is here to allow this declaration inside the macro // because there is no such thing as casting to 'constexpr' (and casting to const does not solve this bug). #define XorString(my_string) []{ constexpr crypt::Xor_string<(sizeof(my_string)/sizeof(char)), char> expr(my_string); return expr; }().decrypt() // Crypt normal string char* #define _c( string ) XorString( string ) #define XorWS(name, my_string) constexpr crypt::Xor_string<(sizeof(my_string)/sizeof(wchar_t)), wchar_t> name(my_string) #define XorWideString(my_string) []{ constexpr crypt::Xor_string<(sizeof(my_string)/sizeof(wchar_t)), wchar_t> expr(my_string); return expr; }().decrypt() // crypt wide characters #define _cw( string ) XorWideString( string ) int main(void ) { std::cout << _c("0obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze0\n" "1obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze1\n" "2obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze2\n" "3obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze3\n" "4obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze4\n" "5obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze5\n" "6obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze6\n" "7obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze7\n" "8obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze8\n" "9obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze9\n" ) << std::endl; std::cout << "Wide strings" << std::endl; std::wcout << _cw(L"0obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze0\n" "1obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze1\n" "2obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze2\n" "3obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze3\n" "4obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze4\n" "5obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze5\n" "6obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze6\n" "7obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze7\n" "8obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze8\n" "9obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzze obfuscate me pleazzzzzzeobfuscate me pleazzzzzze obfuscate me pleazzzzzze9\n") << std::endl; return 0; }
桂棹兮兰桨,击空明兮溯流光。