Originally published at
KMiNT21: Blog. Please leave any
comments there.
Чаще всего такая необходимость возникает тогда, когда в программе приходится хранить пароли в открытом виде. Лично у меня задача была несколько другая - получить возможность простым изменением одной-двух циферок в коде на выходе получить файл с новыми сигнатурами без использование пакеров и протекторов.
Строк в коде много, потому объявлять их в виде массива байт, предварительно закодировав внешним инструментом, - не вариант. А попытаться автоматизировать этот процесс - слишком хлопотно и чревато глюками.
И тут нам на помощь приходят макросы. Не знаю как в других компиляторах (кто дополнит?), но в MSVC все решается вот так (немного упростил код для примера):
//Ключ, которым будем XOR-ить
#define K1 77
// Макс. допустимая дл. строки тут 10 байт
#define MYCRYPT10(str) { MYCRYPT10_(str “\0\0\0\0\0\0\0\0\0\0″) }
#define MYCRYPT10_(str) (str)[0] ^ K1, (str)[1] ^ K1, (str)[2] ^ K1, (str)[3] ^ K1, (str)[4] ^ K1, (str)[5] ^ K1, (str)[6] ^ K1, (str)[7] ^ K1, (str)[8] ^ K1, (str)[9] ^ K1, ‘\0′
// Пример объявления
char szMyPlainTextPassword[] = MYCRYPT10(”superpass”);
Теперь в EXE строки будут уже в зашифрованном виде. Перед использованием этих строк в коде их необходимо расшифровать. Функция дешифровки:
void decrypt(char * buf) {
for (int i=0; i<10; i++)
buf[i]^=K1;
}
Перед обращением к строке (или сразу после загрузки приложения) делаем вызов: decrypt(szMyPlainTextPassword).В чем преимущество данного метода? Все строки (ключи реестра, ссылки, сообщения и т.д.) остаются в читабельном виде. Такой код удобно поддерживать и изменять.
Но еще остался вопрос - как удобней всего организовать шифрование ресурсов внутри EXE? Причем так, чтоб при каждой сборке набор байт был новый. У кого какие мысли будут?