Возник на днях у нас вопрос: «Как спрятать от любителей hex-редаторов строчки текста в скомпилированном приложении?». Но спрятать так, чтобы это не требовало особых усилий, так, между прочим…
Задача состоит в том, что бы использовать в коде строки как обычно, но при этом в исполняемом файле эти строки в явном виде не хранились, возможности сторонних утилит, которые работают с уже скомпилированными бинарными файлами, задействовать так же не хочется, все нужно делать из обычного C++ кода.
Ясно, что нам придется подключить возможности С++ в области метапрограммирования и вычислять шифрование строк на этапе компиляции. Но шаблоны в чистом виде не позволяют использовать в качестве параметров инициализации строки. К счастью, в C++11 появились constexpr – функции, результат которых может быть вычислен на этапе компиляции. В собственно C++11 их возможности довольно ограничены (нельзя использовать, например, циклы и условия), но в новом стандарте C++14 они были существенно расширены практически до возможностей обычных функций (естественно, это должны быть только чистые функции без побочных эффектов).
Получившийся небольшой пример:
Пример не претендует на законченную программу и демонстрирует лишь сам принцип.
Шифратор и дешифратор просто для примера инкрементируют и декрементируют оригинальные символы строки, в теории можно прикрутить достаточно сложные алгоритмы с ключами и расшифровкой хоть на удаленном сервере. Правда есть ложка дегтя, потребовалось задействовать возможности С++14, возможно кто-то знает способ лучше?
ПС. Пример компилировался на Arch Linux с помощью clang 3.5.0 следующей командой:
Авторы: Токарев А.В., Гришин М.Л.
Задача состоит в том, что бы использовать в коде строки как обычно, но при этом в исполняемом файле эти строки в явном виде не хранились, возможности сторонних утилит, которые работают с уже скомпилированными бинарными файлами, задействовать так же не хочется, все нужно делать из обычного C++ кода.
Ясно, что нам придется подключить возможности С++ в области метапрограммирования и вычислять шифрование строк на этапе компиляции. Но шаблоны в чистом виде не позволяют использовать в качестве параметров инициализации строки. К счастью, в C++11 появились constexpr – функции, результат которых может быть вычислен на этапе компиляции. В собственно C++11 их возможности довольно ограничены (нельзя использовать, например, циклы и условия), но в новом стандарте C++14 они были существенно расширены практически до возможностей обычных функций (естественно, это должны быть только чистые функции без побочных эффектов).
Получившийся небольшой пример:
#include <string> #include <iostream> #include <iterator> //хранилице зашифрованных строк template<std::size_t SIZE> struct hiddenString { //буффер для зашифрованной строки short s[SIZE]; //конструктор для создания объекта на этапе компиляции constexpr hiddenString():s{0} { } //функция дешифрации в процессе исполнения приложения std::string decode() const { std::string rv; rv.reserve(SIZE + 1); std::transform(s, s + SIZE - 1, std::back_inserter(rv), [](auto ch) { return ch - 1; }); return rv; } }; //вычисление размера строки на этапе компиляции template<typename T, std::size_t N> constexpr std::size_t sizeCalculate(const T(&)[N]) { return N; } //функция шифрации на этапе компиляции template<std::size_t SIZE> constexpr auto encoder(const char str[SIZE]) { hiddenString<SIZE> encoded; for(std::size_t i = 0; i < SIZE - 1; i++) encoded.s[i] = str[i] + 1; encoded.s[SIZE - 1] = 0; return encoded; } //макрос для удобства использования #define CRYPTEDSTRING(name, x) constexpr auto name = encoder<sizeCalculate(x)>(x) int main() { //выведем зашифрованную на этапе компиляции строку, //если посмотреть содержимое скомпилированного файла, //то оригинал там отсутствует CRYPTEDSTRING(str, "Big big secret!"); std::cout << str.decode() << std::endl; return 0; }
Пример не претендует на законченную программу и демонстрирует лишь сам принцип.
Шифратор и дешифратор просто для примера инкрементируют и декрементируют оригинальные символы строки, в теории можно прикрутить достаточно сложные алгоритмы с ключами и расшифровкой хоть на удаленном сервере. Правда есть ложка дегтя, потребовалось задействовать возможности С++14, возможно кто-то знает способ лучше?
ПС. Пример компилировался на Arch Linux с помощью clang 3.5.0 следующей командой:
$: clang++ -std=c++1y -stdlib=libc++ -lc++abi sample.cpp -o sample
Авторы: Токарев А.В., Гришин М.Л.
