Skip to content

Instantly share code, notes, and snippets.

@therealdreg
Created September 10, 2017 22:24
Show Gist options
  • Save therealdreg/3b8d073368385aa04692afd0dd88b556 to your computer and use it in GitHub Desktop.
Save therealdreg/3b8d073368385aa04692afd0dd88b556 to your computer and use it in GitHub Desktop.
ADVobfuscator addaptation for easy use
// https://github.com/andrivet/ADVobfuscator dreg's addaptation for easy use
#include <random>
#if defined(_MSC_VER)
#define ALWAYS_INLINE __forceinline
#else
#define ALWAYS_INLINE __attribute__((always_inline))
#endif
namespace andrivet { namespace ADVobfuscator {
namespace
{
// I use current (compile time) as a seed
constexpr char time[] = __TIME__; // __TIME__ has the following format: hh:mm:ss in 24-hour time
// Convert time string (hh:mm:ss) into a number
constexpr int DigitToInt(char c) { return c - '0'; }
const int seed = DigitToInt(time[7]) +
DigitToInt(time[6]) * 10 +
DigitToInt(time[4]) * 60 +
DigitToInt(time[3]) * 600 +
DigitToInt(time[1]) * 3600 +
DigitToInt(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 MetaRandomGenerator
{
private:
static constexpr unsigned a = 16807; // 7^5
static constexpr unsigned m = 2147483647; // 2^31 - 1
static constexpr unsigned s = MetaRandomGenerator<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 MetaRandomGenerator<0>
{
static constexpr unsigned value = seed;
};
// Note: A bias is introduced by the modulo operation.
// However, I do belive it is neglictable in this case (M is far lower than 2^31 - 1)
template<int N, int M>
struct MetaRandom
{
static const int value = MetaRandomGenerator<N + 1>::value % M;
};
// std::index_sequence will be available with C++14 (C++1y). For the moment, implement a (very) simplified and partial version. You can find more complete versions on the Internet
// MakeIndex<N>::type generates Indexes<0, 1, 2, 3, ..., N>
template<int... I>
struct Indexes { using type = Indexes<I..., sizeof...(I)>; };
template<int N>
struct Make_Indexes { using type = typename Make_Indexes<N-1>::type::type; };
template<>
struct Make_Indexes<0> { using type = Indexes<>; };
// Represents an obfuscated string, parametrized with an alrorithm number N, a list of indexes Indexes and a key Key
template<int N, int Key, typename Indexes>
struct MetaString4;
// Partial specialization with a list of indexes I, a key K and algorithm N = 0
// Each character is encrypted (XOR) with the same key, stored at the beginning of the buffer
template<int K, int... I>
struct MetaString4<0, K, Indexes<I...>>
{
// Constructor. Evaluated at compile time. Key is stored as the first element of the buffer
constexpr ALWAYS_INLINE MetaString4(const char* str)
: buffer_ {static_cast<char>(K), encrypt(str[I])...} { }
// Runtime decryption. Most of the time, inlined
inline const char* decrypt()
{
for(int i = 0; i < sizeof...(I); ++i)
buffer_[i + 1] = decrypt(buffer_[i + 1]);
buffer_[sizeof...(I) + 1] = 0;
return buffer_ + 1;
}
private:
// Encrypt / decrypt a character of the original string with the key
constexpr char key() const { return buffer_[0]; }
constexpr char encrypt(char c) const { return c ^ key(); }
constexpr char decrypt(char c) const { return encrypt(c); }
// Buffer to store the encrypted string + terminating null byte + key
char buffer_[sizeof...(I) + 2];
};
// Partial specialization with a list of indexes I, a key K and algorithm N = 1
// Each character is encrypted (XOR) with an incremented key. The first key is stored at the beginning of the buffer
template<int K, int... I>
struct MetaString4<1, K, Indexes<I...>>
{
// Constructor. Evaluated at compile time. Key is stored as the first element of the buffer
constexpr ALWAYS_INLINE MetaString4(const char* str)
: buffer_ {static_cast<char>(K), encrypt(str[I], I)...} { }
// Runtime decryption. Most of the time, inlined
inline const char* decrypt()
{
for(int i = 0; i < sizeof...(I); ++i)
buffer_[i + 1] = decrypt(buffer_[i + 1], i);
buffer_[sizeof...(I) + 1] = 0;
return buffer_ + 1;
}
private:
// Encrypt / decrypt a character of the original string with the key
constexpr char key(int position) const { return buffer_[0] + position; }
constexpr char encrypt(char c, int position) const { return c ^ key(position); }
constexpr char decrypt(char c, int position) const { return encrypt(c, position); }
// Buffer to store the encrypted string + terminating null byte + key
char buffer_[sizeof...(I) + 2];
};
// Partial specialization with a list of indexes I, a key K and algorithm N = 2
// Shift the value of each character and does not store the key. It is only used at compile-time.
template<int K, int... I>
struct MetaString4<2, K, Indexes<I...>>
{
// Constructor. Evaluated at compile time. Key is *not* stored
constexpr ALWAYS_INLINE MetaString4(const char* str)
: buffer_ {encrypt(str[I])..., 0} { }
// Runtime decryption. Most of the time, inlined
inline const char* decrypt()
{
for(int i = 0; i < sizeof...(I); ++i)
buffer_[i] = decrypt(buffer_[i]);
return buffer_;
}
private:
// Encrypt / decrypt a character of the original string with the key
constexpr char key(int key) const { return key % 13; }
constexpr char encrypt(char c) const { return c + key(K); }
constexpr char decrypt(char c) const { return c - key(K); }
// Buffer to store the encrypted string + terminating null byte. Key is not stored
char buffer_[sizeof...(I) + 1];
};
// Helper to generate a key
template<int N>
struct MetaRandomChar4
{
// Use 0x7F as maximum value since most of the time, char is signed (we have however 1 bit less of randomness)
static const char value = static_cast<char>(1 + MetaRandom<N, 0x7F - 1>::value);
};
}}
// Prefix notation
#define DEF_OBFUSCATED4(str) MetaString4<andrivet::ADVobfuscator::MetaRandom<__COUNTER__, 3>::value, andrivet::ADVobfuscator::MetaRandomChar4<__COUNTER__>::value, Make_Indexes<sizeof(str) - 1>::type>(str)
#define OBFUSCATED4(str) (DEF_OBFUSCATED4(str).decrypt())
// To remove Boost assert messages
#if !defined(DEBUG) || DEBUG == 0
#define BOOST_DISABLE_ASSERTS
#endif
#if defined(__GNUC__)
// GCC O3 is doing very strange things that are sometimes wrong or that remove the obfuscation. So use O2.
#pragma GCC push_options
#pragma GCC optimize("O2")
#endif
#include <iostream>
using namespace std;
using namespace andrivet::ADVobfuscator;
// Fourth implementation of obfuscated string
// Declaration and usage are separated
void SampleEncryped4_differed()
{
cout << "--------------------" << endl;
cout << "Encryption of string literals - version 4 - Separated declaration and usage" << endl;
auto miley = DEF_OBFUSCATED4("Miley Cyrus");
auto britney = DEF_OBFUSCATED4("Britney Spears");
auto katy = DEF_OBFUSCATED4("Katy Perry");
cout << britney.decrypt() << endl;
cout << katy.decrypt() << endl;
cout << miley.decrypt() << endl;
}
// Entry point
int main(int argc, const char * argv[])
{
SampleEncryped4_differed();
return 0;
}
#if defined(__GNUC__)
#pragma GCC pop_options
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment