Created
September 10, 2017 22:24
-
-
Save therealdreg/3b8d073368385aa04692afd0dd88b556 to your computer and use it in GitHub Desktop.
ADVobfuscator addaptation for easy use
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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