C++字串常見混淆方案

倚剑问天發表於2024-04-19

正文

將字串轉換成等效int陣列

std::vector<uint32_t> convert_wstring_to_int_array(const wchar_t *str) {
  std::vector<uint32_t> vec;

  for (size_t i = 0; i < wcslen(str); i += 2) {
    uint32_t val = (uint32_t)str[i] << 16 & 0xff0000;
    if (i < wcslen(str) - 1) {
      val |= (uint32_t)str[i + 1] & 0xff;
    }
    vec.push_back(val);
  }

  if (vec.back() & 0xffff) {
    vec.push_back(0);
  }

  return vec;
}

std::vector<uint32_t> convert_string_to_int_array(const char *str) {
  std::vector<uint32_t> vec;
  for (int i = 0; i < int(strlen(str)); i += 4) {
    uint32_t val = (uint32_t)str[i] << 24 & 0xff000000;
    if (i < int(strlen(str)) - 1) {
      val |= (uint32_t)str[i + 1] << 16 & 0xff0000;
    }
    if (i < int(strlen(str)) - 2) {
      val |= (uint32_t)str[i + 2] << 8 & 0xff00;
    }
    if (i < int(strlen(str)) - 3) {
      val |= (uint32_t)str[i + 3] & 0xff;
    }
    vec.push_back(val);
  }

  return vec;
}

編譯時xor混淆字串

#pragma once

namespace zzz {

#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)

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)))

// FIXME: Why use XSTR_RANDOM_NUMBER(0, 0xFF) will cause undefined behavior??
constexpr const unsigned long long XORKEY = 0x56; // 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] ^= (static_cast<Char>(XORKEY) + t);
        }
        string[_nb_chars] = '\0';
        return string;
    }
};

}  // namespace zzz

#define XorS(name, my_string) \
    constexpr zzz::Xor_string<(sizeof(my_string) / sizeof(char)), char> name(my_string)
// Because of a limitation/bug in msvc 2017 we need to declare zzz::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 zzz::Xor_string<(sizeof(my_string) / sizeof(char)), char> expr(my_string); \
        return expr;                                                                                 \
    }()                                                                                              \
        .decrypt()

#define XorWS(name, my_string) \
    constexpr zzz::Xor_string<(sizeof(my_string) / sizeof(wchar_t)), wchar_t> name(my_string)
#define XorWideString(my_string)                                                                           \
    [] {                                                                                                   \
        constexpr zzz::Xor_string<(sizeof(my_string) / sizeof(wchar_t)), wchar_t> expr(my_string); \
        return expr;                                                                                       \
    }()                                                                                                    \
        .decrypt()

// Crypt normal string char*
#define xorstr(string) XorString(string)

// crypt wide characters
#define xorstrw(string) XorWideString(string)

相關文章