Go back to the home page
Background
After the introduction of constexpr in C++11, I had an idea to use it to automatically obfuscate string literals in C++ programs. Indeed it was only in C++14 with the acceptance of N3652 i.e relaxing constraints on constexpr functions, that it became much simpler to implement. It was actually a very small project compared to what I have done in the past, with only 200 lines of code. Since its initial release it has become quite popular due to its simplicitly, and I have been maintaining it and incrementally improving it ever since.
Whats the problem?
When plain text string literals are used in C++ programs, they will be compiled as-is into the resultant binary. This causes them to be incredibly easy to find. One can simply open up the binary file in a text editor to see all of the embedded string literals in plain view. A special utility called strings exists which can be used to search binary files for plain text strings.
What does Obfuscate do?
This header-only library seeks to make it difficult (but not impossible) for embedded string literals in binary files to be found by encrypting them with an XOR cipher at compile-time using a constant expression, forcing the compiler to work with the encrypted string instead of the plain text literal. Usage of AY_OBFUSCATE
additionally removes the need for a const pointer to the string, which more often than not (for small strings) convinces the compiler to inline the encrypted string, building it up at runtime in a series of assembly operations, protecting the binary image against simple XOR decryption attacks. Encrypted strings will then be decrypted at runtime to be utilised within the program.
Technical features
- Guaranteed compile-time obfuscation - the string is compiled via a constexpr expression.
- Global lifetime - the obfuscated string is stored in a function level static variable in a unique lambda.
- Implicitly convertible to a char* - easy to integrate into existing codebases.
- Random 64-bit key - obfusated with a random key each time.
By simply wrapping your string literal "My String"
with AY_OBFUSCATE("My String")
it will be encrypted at compile time with a random 64 bit key and stored in an ay::obfuscated_data
object which you can manipulate at runtime. For convenience it is also implicitly convertable to a char*
.
For example, the following program will not store the string “Hello World” in plain text anywhere in the compiled executable.
#include "obfuscate.h"
int main()
{
std::cout << AY_OBFUSCATE("Hello World") << std::endl;
return 0;
}
Examples of usage
Because the obfuscated data that is generated by AY_OBFUSCATE
has global lifetime it is completely fine to also use it in both a local and a temporary context.
char* var = AY_OBFUSCATE("string");
const char* var = AY_OBFUSCATE("string");
static const char* var = AY_OBFUSCATE("string");
std::string var(AY_OBFUSCATE("string"));
function_that_takes_char_pointer(AY_OBFUSCATE("string"));