windows C++:如何在编译时加密字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4102320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:33:29  来源:igfitidea点击:

C++: How to encrypt strings at compile time?

c++windowsvisual-studio-2008

提问by Newbie

I want to hide some strings in my .exe so people can't simply just open the .exe and look at all the strings there. I don't care about the strength of the encrypting method, so I will probably use XOR etc.

我想在我的 .exe 中隐藏一些字符串,这样人们就不能简单地打开 .exe 并查看那里的所有字符串。我不关心加密方法的强度,所以我可能会使用 XOR 等。

How can I do this at compile time? That way my strings won't be stored in the .exe but the encrypted versions would. Then, I would just use my decrypting function every time to display those strings on screen.

我怎样才能在编译时做到这一点?这样我的字符串就不会存储在 .exe 中,但加密版本会。然后,我每次都会使用我的解密功能在屏幕上显示这些字符串。

采纳答案by Yevhen

you can encrypt it using macros or write your own preprocessor

您可以使用宏对其进行加密或编写自己的预处理器

#define CRYPT8(str) { CRYPT8_(str "
#define XorString( String ) ( CXorString<ConstructIndexList<sizeof( String ) - 1>::Result>( String ).decrypt() )
printf(XorString( "this string is hidden!" ));
#pragma once

//-------------------------------------------------------------//
// "Malware related compile-time hacks with C++11" by LeFF   //
// You can use this code however you like, I just don't really //
// give a shit, but if you feel some respect for me, please //
// don't cut off this comment when copy-pasting... ;-)       //
//-------------------------------------------------------------//

////////////////////////////////////////////////////////////////////
template <int X> struct EnsureCompileTime {
    enum : int {
        Value = X
    };
};
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
//Use Compile-Time as seed
#define Seed ((__TIME__[7] - '0') * 1  + (__TIME__[6] - '0') * 10  + \
              (__TIME__[4] - '0') * 60   + (__TIME__[3] - '0') * 600 + \
              (__TIME__[1] - '0') * 3600 + (__TIME__[0] - '0') * 36000)
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
constexpr int LinearCongruentGenerator(int Rounds) {
    return 1013904223 + 1664525 * ((Rounds> 0) ? LinearCongruentGenerator(Rounds - 1) : Seed & 0xFFFFFFFF);
}
#define Random() EnsureCompileTime<LinearCongruentGenerator(10)>::Value //10 Rounds
#define RandomNumber(Min, Max) (Min + (Random() % (Max - Min + 1)))
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
template <int... Pack> struct IndexList {};
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
template <typename IndexList, int Right> struct Append;
template <int... Left, int Right> struct Append<IndexList<Left...>, Right> {
    typedef IndexList<Left..., Right> Result;
};
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
template <int N> struct ConstructIndexList {
    typedef typename Append<typename ConstructIndexList<N - 1>::Result, N - 1>::Result Result;
};
template <> struct ConstructIndexList<0> {
    typedef IndexList<> Result;
};
////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////
const char XORKEY = static_cast<char>(RandomNumber(0, 0xFF));
constexpr char EncryptCharacter(const char Character, int Index) {
    return Character ^ (XORKEY + Index);
}

template <typename IndexList> class CXorString;
template <int... Index> class CXorString<IndexList<Index...> > {
private:
    char Value[sizeof...(Index) + 1];
public:
    constexpr CXorString(const char* const String)
    : Value{ EncryptCharacter(String[Index], Index)... } {}

    char* decrypt() {
        for(int t = 0; t < sizeof...(Index); t++) {
            Value[t] = Value[t] ^ (XORKEY + t);
        }
        Value[sizeof...(Index)] = '
#include <array>
#include <string>

template<typename Char>
static const Char SECRET = 0x01;

template<typename Char,
         typename std::basic_string<Char>::size_type Length>
struct obfuscated_string
{
    using String = std::basic_string<Char>;

    const std::array<const Char, Length> storage;

    operator String() const
    {
        String s{storage.data(), Length};
        for (auto& c: s)
            c ^= SECRET<Char>;
        return s;
    }
};
'; return Value; } char* get() { return Value; } }; #define XorS(X, String) CXorString<ConstructIndexList<sizeof(String)-1>::Result> X(String) #define XorString( String ) ( CXorString<ConstructIndexList<sizeof( String ) - 1>::Result>( String ).decrypt() ) ////////////////////////////////////////////////////////////////////
template<typename ctype, ctype...STR>
constexpr obfuscated_string<ctype, sizeof... (STR)> operator ""_hidden()
{
    return { { (STR ^ SECRET<ctype>)... } };
}
#include <iostream>
int main()
{
    static const auto message = "squeamish ossifrage"_hidden;
    std::string plaintext = message;
    std::cout << plaintext << std::endl;
}
#include <iostream>

// =============================================================================
namespace crypt {
// =============================================================================

// convert __TIME__ == "hh:mm:ss" to a sum of seconds this gives us a compile-time seed
// Note: in some weird cases I've seen the seed being different from encryption
// to decryption so it's safer to not use time and set the seed manually
#if 0
#define TBX_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)
#else
#define TBX_XSTR_SEED (3600ull)
#endif

// -----------------------------------------------------------------------------

// @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) : (TBX_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] = '
char test[256] = { 0 };
w_sprintf_s(test, 256, XorStr("test test :D %d %+d\n"), 1, 1337);
'; 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; }
#pragma once
#include <string>
#include <array>
#include <cstdarg>

#define BEGIN_NAMESPACE( x ) namespace x {
#define END_NAMESPACE }

BEGIN_NAMESPACE(XorCompileTime)

constexpr auto time = __TIME__;
constexpr auto seed = static_cast< int >(time[7]) + static_cast< int >(time[6]) * 10 + static_cast< int >(time[4]) * 60 + static_cast< int >(time[3]) * 600 + static_cast< int >(time[1]) * 3600 + static_cast< int >(time[0]) * 36000;

// 1988, Stephen Park and Keith Miller
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
// with 32-bit math and without division

template < int N >
struct RandomGenerator
{
private:
    static constexpr unsigned a = 16807; // 7^5
    static constexpr unsigned m = 2147483647; // 2^31 - 1

    static constexpr unsigned s = RandomGenerator< N - 1 >::value;
    static constexpr unsigned lo = a * (s & 0xFFFF); // Multiply lower 16 bits by 16807
    static constexpr unsigned hi = a * (s >> 16); // Multiply higher 16 bits by 16807
    static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // Combine lower 15 bits of hi with lo's upper bits
    static constexpr unsigned hi2 = hi >> 15; // Discard lower 15 bits of hi
    static constexpr unsigned lo3 = lo2 + hi;

public:
    static constexpr unsigned max = m;
    static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
};

template <>
struct RandomGenerator< 0 >
{
    static constexpr unsigned value = seed;
};

template < int N, int M >
struct RandomInt
{
    static constexpr auto value = RandomGenerator< N + 1 >::value % M;
};

template < int N >
struct RandomChar
{
    static const char value = static_cast< char >(1 + RandomInt< N, 0x7F - 1 >::value);
};

template < size_t N, int K >
struct XorString
{
private:
    const char _key;
    std::array< char, N + 1 > _encrypted;

    constexpr char enc(char c) const
    {
        return c ^ _key;
    }

    char dec(char c) const
    {
        return c ^ _key;
    }

public:
    template < size_t... Is >
    constexpr __forceinline XorString(const char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... }
    {
    }

    __forceinline decltype(auto) decrypt(void)
    {
        for (size_t i = 0; i < N; ++i) {
            _encrypted[i] = dec(_encrypted[i]);
        }
        _encrypted[N] = '##代码##';
        return _encrypted.data();
    }
};

//--------------------------------------------------------------------------------
//-- Note: XorStr will __NOT__ work directly with functions like printf.
//         To work with them you need a wrapper function that takes a const char*
//         as parameter and passes it to printf and alike.
//
//         The Microsoft Compiler/Linker is not working correctly with variadic 
//         templates!
//  
//         Use the functions below or use std::cout (and similar)!
//--------------------------------------------------------------------------------

static auto w_printf = [](const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf_s(fmt, args);
    va_end(args);
};

static auto w_printf_s = [](const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf_s(fmt, args);
    va_end(args);
};

static auto w_sprintf = [](char* buf, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vsprintf(buf, fmt, args);
    va_end(args);
};

static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vsprintf_s(buf, buf_size, fmt, args);
    va_end(args);
};

#define XorStr( s ) ( XorCompileTime::XorString< sizeof( s ) - 1, __COUNTER__ >( s, std::make_index_sequence< sizeof( s ) - 1>() ).decrypt() )

END_NAMESPACE
##代码##") } #define CRYPT8_(str) (str)[0] + 1, (str)[1] + 2, (str)[2] + 3, (str)[3] + 4, (str)[4] + 5, (str)[5] + 6, (str)[6] + 7, (str)[7] + 8, '##代码##' // calling it const char str[] = CRYPT8("ntdll");

回答by SSpoke

I also thought this wasn't possible, even though it's very simple, people wrote solutions where you need a custom tool to scan the built file afterwards and scan for strings and encrypt the strings like that, which wasn't bad but I wanted a package that's compiled from Visual Studio, and it's possible now!

我也认为这是不可能的,尽管这很简单,但人们编写了解决方案,您需要一个自定义工具来扫描构建的文件,然后扫描字符串并像这样加密字符串,这还不错,但我想要一个从 Visual Studio 编译的包,现在可以了!

What you need is C++ 11(Visual Studio 2015 Update 1 out of the box)

你需要的是C++ 11(Visual Studio 2015 Update 1 开箱即用)

the magic happens with this new command constexpr

这个新命令神奇地发生了 constexpr

By magic happens in this #define

魔法发生在这个 #define

##代码##

It won't decrypt the XorString at compile-time, only at run-time, but it will encrypt the string only in compile-time, so the strings will not appear in the Executable file

它不会在编译时解密 XorString,只在运行时解密,但它只会在编译时加密字符串,因此字符串不会出现在可执行文件中

##代码##

It will print out "this string is hidden!"but you won't find it inside Executable file as strings!, check it yourself with Microsoft Sysinternals Stringsprogram download link: https://technet.microsoft.com/en-us/sysinternals/strings.aspx

它会打印出来,"this string is hidden!"但你不会在可执行文件中找到它作为字符串!,请使用Microsoft Sysinternals Strings程序下载链接自行检查:https: //technet.microsoft.com/en-us/sysinternals/strings.aspx

The full source code is quite large but could easily be included into one header file. But also quite random so the encrypted string outputs will always change every new compile, the seed is changed based on the time it took it compile, pretty much solid,perfect solution.

完整的源代码相当大,但可以很容易地包含在一个头文件中。但也很随机,所以加密的字符串输出总是会改变每次新编译,种子根据编译时间而改变,非常可靠,完美的解决方案。

Create a file called XorString.h

创建一个名为 XorString.h

##代码##

回答by Toby Speight

This probably doesn't apply to the ancient compiler of the question, but on more more modern C++ implementations, we can use a string literal operator templatethat's declared constexprto implement compile-time obfuscation. For this, I've used GCC 7.2.0 with -std=c++17(and a full set of warning options, of course).

这可能不适用于该问题的古老编译器,但在更现代的 C++ 实现中,我们可以使用声明为实现编译时混淆的字符串文字运算符模板constexpr。为此,我使用了 GCC 7.2.0 -std=c++17(当然还有全套警告选项)。

Firstly, we define a type to hold our obfuscated string data, with a conversion operator to produce a plaintext string on demand:

首先,我们定义一个类型来保存我们混淆的字符串数据,使用转换运算符来按需生成纯文本字符串:

##代码##

Now, the literal operator template to convert a source-code literal to an obfuscated string:

现在,将源代码文字转换为混淆字符串的文字运算符模板:

##代码##

To demonstrate:

展示:

##代码##

We can inspect the object code with the stringsprogram. The binary doesn't contain squeamish ossifrageanywhere; instead it has rptd`lhri!nrrhgs`fd. I've confirmed this with a range of optimisation levels to demonstrate that the conversion back to std::stringdoesn't get pre-computed, but I advise you conduct your own tests whenever you change compiler and/or settings.

我们可以用strings程序检查目标代码。二进制文件不包含squeamish ossifrage任何地方;相反,它有rptd`lhri!nrrhgs`fd. 我已经通过一系列优化级别确认了这一点,以证明std::string不会预先计算返回到的转换,但我建议您在更改编译器和/或设置时进行自己的测试。

(I'm deliberately ignoring whether this is an advisablething to do - merely presenting a technical working solution).

(我故意忽略这是否是一个可取的做法 - 只是提出一个技术可行的解决方案)。

回答by arkan

Building on SSPoke's answer here is a slightly simpler and more robust solution. Tested with MSVC 2017 and gcc 7.3 https://godbolt.org/z/7fc3Zi

以 SSPoke 的答案为基础,这里是一个稍微简单且更强大的解决方案。使用 MSVC 2017 和 gcc 7.3 https://godbolt.org/z/7fc3Zi 进行测试

Changes:

变化:

  • Fix integer overflow warning for long strings
  • Fix/Make sure MSVC evaluate encrypt_character() at compile timeeven for very long strings (in the original version some strings would not get encrypted at compile time)
  • Support for wide character strings
  • Simpler code templates
  • 修复长字符串的整数溢出警告
  • 修复/确保 MSVC 在编译时评估 encrypt_character()即使对于很长的字符串(在原始版本中,某些字符串在编译时不会被加密)
  • 支持宽字符串
  • 更简单的代码模板
##代码##

回答by Beta

About the only way to do exactlywhat you suggest is to write a truly horrible macro. But here are some alternatives.

关于完全按照您的建议执行的唯一方法是编写一个真正可怕的宏。但这里有一些替代方案。

  1. Store the encrypted strings in a data file.
  2. Collect the strings in a single source file, then in the build, before actually compiling, go over it with a tool that will encrypt them (e.g. sed). You can automate this step.
  3. Use a powerful editor so that you can encrypt/decrypt the strings effortlessly, while you work.
  1. 将加密的字符串存储在数据文件中。
  2. 收集单个源文件中的字符串,然后在构建中,在实际编译之前,使用将它们加密的工具(例如 sed)对其进行检查。您可以自动执行此步骤。
  3. 使用功能强大的编辑器,以便您可以在工作时毫不费力地加密/解密字符串。

回答by gwell

If you are only trying to hide the strings, then you could just try compressing your executable with something like UPX.

如果您只是想隐藏字符串,那么您可以尝试使用UPX 之类的东西压缩您的可执行文件。

回答by Mark Storer

Any crypto that is done at compile time must also be undoable in the raw EXE (unless you're doing something Really Strange). And your app is running on their hardware. Doomed... barring DRM, which is (in my mind) Evil.

在编译时完成的任何加密也必须在原始 EXE 中撤消(除非您正在做一些非常奇怪的事情)。您的应用程序正在他们的硬件上运行。注定......除非DRM,这(在我看来)是邪恶的。

回答by Abyx

You can't encrypt strings (string literals) by С++ compiler or preprocessor, but you can write a pre-build tool which will parse your source code, and encrypt strings.

您不能通过 С++ 编译器或预处理器加密字符串(字符串文字),但您可以编写一个预构建工具来解析您的源代码并加密字符串。

Or, you can try to use boost::mpl::string.

或者,您可以尝试使用 boost::mpl::string。

回答by Cheers and hth. - Alf

No matter the details of your solution it will involve encrypting the strings using some encryption program.

无论您的解决方案的细节如何,都将涉及使用某些加密程序对字符串进行加密。

You might write a script to encrypt literals in your source code.

您可以编写一个脚本来加密源代码中的文字。

Or for a Windows exe you might encrypt literals in an [.rc] file, embedding the strings as a string table resource in the exe.

或者对于 Windows exe,您可以加密 [.rc] 文件中的文字,将字符串作为字符串表资源嵌入 exe 中。

But probably the best solution is to not try any hiding.

但可能最好的解决方案是不要尝试任何隐藏。

When Microsoft tried the XOR hiding trick on the Windows code that arbitrarily warned about non-Microsoft DOS-es being unreliable and incompatible with this and that, it just backfired on them. Of course the idea of saying bad things about competitors and bundling that bad-saying with Windows was a Really Stupid Idea in the first place. But, trying to hide the code was what made it into a public embarrassment: nobody had really noticed the warnings the code produced, but when people discovered "encrypted" code, naturally their curiosity was engaged, they just had to find out what it was, and write articles about it.

当 Microsoft 在 Windows 代码上尝试 XOR 隐藏技巧时,该技巧任意警告非 Microsoft DOS-es 不可靠且与此不兼容,结果适得其反。当然,说竞争对手的坏话并将这些坏话与 Windows 捆绑在一起的想法首先是一个非常愚蠢的想法。但是,试图隐藏代码使其成为公开的尴尬:没有人真正注意到代码产生的警告,但是当人们发现“加密”代码时,自然会引起他们的好奇心,他们只需要找出它是什么,并撰写有关它的文章。

Cheers & hth.,

干杯 & hth.,

回答by SSpoke

Here is what I currently use it has hacks to support sprintf functions which spilled plain-text in compiled binary file. You could now use w_sprintf_s instead of sprintf, like so

这是我目前使用的东西,它有一些技巧来支持 sprintf 函数,这些函数在编译的二进制文件中溢出纯文本。您现在可以使用 w_sprintf_s 而不是 sprintf,就像这样

##代码##


May add support for wchar_t wide strings like arkan did.. but I have no use for them right now as I don't write anything in symbols / unicode.


可能会像 arkan 那样添加对 wchar_t 宽字符串的支持..但我现在没有用它们,因为我没有用符号/unicode 写任何东西。

##代码##