Думаю, этот вопрос заслуживает обновленного ответа.
Когда я задал этот вопрос несколько лет назад, я не учел разницу между обфускацией и шифрованием . Если бы я знал эту разницу тогда, я бы включил в заголовок термин Обфускация .
C ++ 11 и C ++ 14 имеют функции, которые позволяют реализовать обтекание строк во время компиляции (и, возможно, шифрование, хотя я еще не пробовал), эффективно и разумно простой способ, и это уже сделано.
ADVobfuscator - это библиотека запутывания, созданная Себастьеном Андриветом, которая использует C ++ 11/14 для генерации запутанного кода во время компиляции без использования какого-либо внешнего инструмента, только кода C ++. Нет необходимости создавать дополнительные этапы сборки, просто включите его и используйте. Я не знаю лучшей реализации шифрования / обфускации строк во время компиляции, которая не использует внешние инструменты или этапы сборки. Если вы делаете, пожалуйста, поделитесь.
Он не только запутывает строки, но и имеет другие полезные вещи, такие как FSM времени компиляции ( Finite State Machine ), который может случайным образом запутывать вызовы функций, и генератор псевдослучайных чисел времени компиляции, но это выходит за рамки этого ответа.
Вот простой пример обфускации строки с использованием ADVobfuscator:
#include "MetaString.h"
using namespace std;
using namespace andrivet::ADVobfuscator;
void Example()
{
/* Example 1 */
// here, the string is compiled in an obfuscated form, and
// it's only deobfuscated at runtime, at the very moment of its use
cout << OBFUSCATED("Now you see me") << endl;
/* Example 2 */
// here, we store the obfuscated string into an object to
// deobfuscate whenever we need to
auto narrator = DEF_OBFUSCATED("Tyler Durden");
// note: although the function is named `decrypt()`, it's still deobfuscation
cout << narrator.decrypt() << endl;
}
Вы можете заменить макросы DEF_OBFUSCATED
и OBFUSCATED
вашими собственными макросами. Eg.:
#define _OBF(s) OBFUSCATED(s)
...
cout << _OBF("klapaucius");
Как это работает?
Если вы посмотрите на определение этих двух макросов в MetaString.h , вы увидите:
#define DEF_OBFUSCATED(str) MetaString<andrivet::ADVobfuscator::MetaRandom<__COUNTER__, 3>::value, andrivet::ADVobfuscator::MetaRandomChar<__COUNTER__>::value, Make_Indexes<sizeof(str) - 1>::type>(str)
#define OBFUSCATED(str) (DEF_OBFUSCATED(str).decrypt())
По сути, существует три различных варианта класса MetaString
(ядро обфускации строки). У каждого свой алгоритм обфускации. Один из этих трех вариантов выбирается случайным образом во время компиляции с использованием генератора псевдослучайных чисел библиотеки (MetaRandom
) вместе со случайным char
, который используется выбранным алгоритмом для xor
строковых символов.
"Привет, но если мы выполним математику, 3 алгоритма * 255 возможных ключей символов (0 не используется) = 765 вариантов запутанной строки"
Ты прав. Одну и ту же строку можно запутать только 765 разными способами. Если у вас есть причина для чего-то более безопасного (параноик / ваше приложение требует повышенной безопасности), вы можете расширить библиотеку и реализовать свои собственные алгоритмы, используя более сильную запутывание или даже шифрование ( Криптография White-Box - это в дорожной карте библиотеки).
Где и как хранятся запутанные строки?
Одной вещью, которую я нахожу интересной в этой реализации, является то, что она не хранит запутанную строку в разделе данных исполняемого файла.
Вместо этого он статически сохраняется в самом объекте MetaString
(в стеке), и алгоритм декодирует его на месте во время выполнения. Такой подход значительно затрудняет поиск запутанных строк, статически или во время выполнения.
Вы можете глубже погрузиться в реализацию самостоятельно. Это очень хорошее базовое решение для запутывания и может быть отправной точкой для более сложного.