Obfusheader.h is a portable header file for C++14 and higher which implements multiple features for compile-time obfuscation for example string & decimal encryption, control flow, call hiding. It has no external dependencies, works on both windows and unix platforms, supports g++, gcc and visual c++ compilers. Obfusheader.h is intended to be the most easy way to provide a basic protection for sensitive data in your binaries. It's also designed to work with any g++ arguments which affect the compilation (-O3, Os, -fPIC, etc).
Unlike Windows x86_64 with VMProtect, Themida and other tools, on some platforms there's no good ways to protect your binaries, for example Arm64 / Arm32 android or linux ones. Because of that developing native ARM software (for example gaming mods) becomes a big problem - your product can be easily cracked by anyone. This gave me inspiration to create a handmade compile-time obfuscation using C++ macros, templates and constant expressions to provide basic protection measures for any platform, including android and Arm linux.
- Support gcc, g++, clang, visual c++. C++14 and higher
- Works with any compiler flags (-Os, O3, O2), 100% safe
- Constant encryption (strings, any xor-able decimal types)
- 2 encryption modes (with thread-local storage and without)
- Basic inline ControlFlow (messes up with IDA / GHIDRA decompilers)
- Call hiding for both windows & linux (dlsym & GetModuleHandle)
- Dynamic key generation in compile-time (__TIME__ and __COUNTER__)
You can change them in the start of the header. This will affect how to obfuscation works in different ways. The default settings are the best so you won't need to change anything for it to work unless it's a special case. Note that disabling THREAD_LOCAL mode will expose your constant while compiling with optimization flags such as -O3, O2 so don't disable it if you use them.
// Settings
#define THREAD_LOCAL
#define CFLOW
#define FORCE_INLINE
You can encrypt strings and any xor-able decimals easily. The macro is universal - it accepts any supported type as an argument.
#include <stdio.h>
#include "obfusheader.h"
int main() {
printf(OBF("%s, %d, %c"), OBF("TEST"), OBF(123), OBF('c'));
return 0;
}
Without optimization flags (regular G++):
With -O3 (agressive compiler optimizations):
You can hide any calls exported from external libraries on both linux and windows.
Windows call hiding example:
#include <stdio.h>
#include "obfusheader.h"
int main() {
HANDLE stdOut = OBFUSCALL("kernel32.dll", "GetStdHandle", HANDLE(*)(DWORD))(STD_OUTPUT_HANDLE);
if (stdOut != NULL && stdOut != INVALID_HANDLE_VALUE) {
DWORD written = 0;
const char * message = OBF("Hello, world!");
OBFUSCALL("kernel32.dll", "WriteConsoleA", HANDLE(*)(HANDLE, const char*, DWORD, LPDWORD, LPVOID))
(stdOut, message, strlen(message), &written, NULL);
getchar();
return 0;
}
}
Linux call hiding example:
#include <stdio.h>
#include "obfusheader.h"
int main() {
OBFUSCALL("printf", int(*)(const char*...))(OBF("There's no call here %d%% for sure"), OBF(100));
return 0;
}
There already are some similar solutions for compile-time obfuscation, but all of them have problems that forced me to implement my own.
-
Seems like a really good compile-time obfuscator, has an universal macro with input type detection and control flow implementation. But sadly is affected by optimization flags in general.
Test C++ source:
Used compiler:
The string remains in the binary (compiled without -O3):
When compiling with -O3 the string is encrypted, but the control flow gets eaten:
-
Another one more old compile-time obfuscation header. Works pretty fine without any compiler flags, but the encryption gets completely simplified if optimization flag is added.
Test C++ program:
Without -O3 arguments:
With optimizations: