Jump to content
Sign in to follow this  
Fenrisus

String Obfuscation Tutorial

Recommended Posts

Hi guys, today I will tell you how you can protect C ++ code from reverse engineering. Just little trick based on const expr compile-time obfuscation.

Everything in comments 😉

 

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>


#include <array>
#include <iostream>
#include <string>

#pragma region Learning



typedef uint32_t u32;
typedef uint64_t u64;
typedef unsigned char uchar;

template<u32 S, u32 A = 16807UL, u32 C = 0UL, u32 M = (1UL << 31) - 1>
struct LinearGenerator {
	static const u32 state = ((u64)S * A + C) % M;
	static const u32 value = state;
	typedef LinearGenerator<state> next;
	struct Split { // Leapfrog
		typedef LinearGenerator< state, A*A, 0, M> Gen1;
		typedef LinearGenerator<next::state, A*A, 0, M> Gen2;
	};
};

// Metafunction to get a particular index from generator
template<u32 S, std::size_t index>
struct Generate {
	static const uchar value = Generate<LinearGenerator<S>::state, index - 1>::value;
};

template<u32 S>
struct Generate<S, 0> {
	static const uchar value = static_cast<uchar> (LinearGenerator<S>::value);
};

// List of indices
template<std::size_t...>
struct StList {};

// Concatenate
template<typename TL, typename TR>
struct Concat;

template<std::size_t... SL, std::size_t... SR>
struct Concat<StList<SL...>, StList<SR...>> {
	typedef StList<SL..., SR...> type;
};

template<typename TL, typename TR>
using Concat_t = typename Concat<TL, TR>::type;

// Count from zero to n-1
template<size_t s>
struct Count {
	typedef Concat_t<typename Count<s - 1>::type, StList<s - 1>> type;
};

template<>
struct Count<0> {
	typedef StList<> type;
};

template<size_t s>
using Count_t = typename Count<s>::type;

// Get a scrambled character of a string
template<u32 seed, std::size_t index, std::size_t N>
constexpr uchar get_scrambled_char(const char(&a)[N]) {
	return static_cast<uchar>(a[index]) + Generate<seed, index>::value;
}

// Get a ciphertext from a plaintext string
template<u32 seed, typename T>
struct cipher_helper;

template<u32 seed, std::size_t... SL>
struct cipher_helper<seed, StList<SL...>> {
	static constexpr std::array<uchar, sizeof...(SL)> get_array(const char(&a)[sizeof...(SL)]) {
		return{ { get_scrambled_char<seed, SL>(a)... } };
	}
};

template<u32 seed, std::size_t N>
constexpr std::array<uchar, N> get_cipher_text(const char(&a)[N]) {
	return cipher_helper<seed, Count_t<N>>::get_array(a);
}

// Get a noise sequence from a seed and string length
template<u32 seed, typename T>
struct noise_helper;

template<u32 seed, std::size_t... SL>
struct noise_helper<seed, StList<SL...>> {
	static constexpr std::array<uchar, sizeof...(SL)> get_array() {
		return{ { Generate<seed, SL>::value ... } };
	}
};

template<u32 seed, std::size_t N>
constexpr std::array<uchar, N> get_key() {
	return noise_helper<seed, Count_t<N>>::get_array();
}


/*
// Get an unscrambled character of a string
template<u32 seed, std::size_t index, std::size_t N>
char get_unscrambled_char(const std::array<uchar, N> & a) {
return static_cast<char> (a[index] - Generate<seed, index>::value);
}
*/

// Metafunction to get the size of an array
template<typename T>
struct array_info;

template <typename T, size_t N>
struct array_info<T[N]>
{
	typedef T type;
	enum { size = N };
};

template <typename T, size_t N>
struct array_info<const T(&)[N]> : array_info<T[N]> {};

// Scramble a string
template<u32 seed, std::size_t N>
class obfuscated_string {
private:
	std::array<uchar, N> cipher_text_;
	std::array<uchar, N> key_;
public:
	explicit constexpr obfuscated_string(const char(&a)[N])
		: cipher_text_(get_cipher_text<seed, N>(a))
		, key_(get_key<seed, N>())
	{}

	operator std::string() const {
		char plain_text[N];
		for (volatile std::size_t i = 0; i < N; ++i) {
			volatile char temp = static_cast<char>(cipher_text_[i] - key_[i]);
			plain_text[i] = temp;
		}
		return std::string{ plain_text, plain_text + N };
	}
};

template<u32 seed, std::size_t N>
std::ostream & operator<< (std::ostream & s, const obfuscated_string<seed, N> & str) {
	s << static_cast<std::string>(str);
	return s;
}

//compiletime Seed for random string obfuscation
#define RNG_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) + \
              (__LINE__ * 100000)


#define DECRYPTSTRING(STR) \
    obfuscated_string<RNG_SEED, array_info<decltype(STR)>::size>{STR}

#pragma endregion

Well, now the usage:

#include "stdafx.h"

auto FooBar = DECRYPTSTRING("FWEFWEFWEFWefwehkdl2hei1o;eh23khdBlahBlahBlah");

int main()
{
	std::cout << DECRYPTSTRING("You can use it like this also") << std::endl;
	std::getchar();
    return 0;
}

 

This code obfuscate your string values just like VMProtect.DecryptString ("Foobar") does. Such technique can be used for protect constant string values like public RSA/XXTea/etc. keys, connection IP string or any other string values. It prevents simple reading such values via OllyDbg or IDAPro software. Works like a charm at Visual Studio 2015/2017 x86 Release builds.

Enjoy 😉

 

 

 

 

 

  • Like 2

Share this post


Link to post
Share on other sites
18 hours ago, Guruu said:

Pretty cool 🙂 Could be documented a lot better though. Commenting skills go a long way in the real world industry if that is where you aim to be. 

Agreed the docs could be better. This could be useful for someone making an indie game tho if it doesnt create a bunch of overhead to encode/decode their chat strings

 

Edit: I love your content fenrisus I just wish you were more descriptive, 9/10  people don't understand this stoof just by reading it, I can *kinda* figure it out because not only have I programmed C but I dabble in numerous other languages so the syntax makes sense to me, but someone who is just starting out this would just be a bunch of gibberish

Share this post


Link to post
Share on other sites
On 4/22/2019 at 2:10 PM, Tater Pie said:

Agreed the docs could be better. This could be useful for someone making an indie game tho if it doesnt create a bunch of overhead to encode/decode their chat strings

On 4/21/2019 at 7:53 PM, Guruu said:

Pretty cool 🙂 Could be documented a lot better though. Commenting skills go a long way in the real world industry if that is where you aim to be. 

 

Hey @Fenrisus I don't really know you but i also agree with these other 2 fellows. I love seeing these type of things as i am myself a developer, It's amazing to see you wanting to improve the developing community, I hope too see more post like this i hope this help someone in need! :classic_love:
- mod.gifDex

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...

Important Information

By using our forums or services as a guest you agree to our Terms of Service: Terms of Use Privacy Policy: Privacy Policy and Guidelines