У них в значительной степени есть локальная копия Интернета, кэшируемого на тысячах ПК в пользовательских файловых системах.
Один из подходов - поместить код, выполняющий проверку лицензии, в отдельную DLL. В основном приложении загрузите DLL во время выполнения и вычислите контрольную сумму самой DLL. Приложение хранит контрольную сумму, которая была рассчитана с помощью библиотеки DLL. Если контрольные суммы не совпадают, у вас есть несколько вариантов, показать сообщение с неправильной версией - немного очевидно; Не вызывайте проверку лицензии - менее очевидно, но будет замечено, когда злоумышленник задается вопросом, почему проверка лицензии не вызывается; вызвать функцию с именем, аналогичным настоящей функции проверки лицензии.
Думайте об этом как об использовании шифрования открытого ключа . Используйте открытый ключ как часть конфигурации и сделайте закрытый ключ встроенным в приложение. Если они испортят открытый ключ, цифровая подпись приложения будет скомпрометирована обнаруживаемым способом.
Я согласен с @camccann, что это поможет понять, какой тип атаки вы ожидаете. В крайнем случае разделите проверку лицензии на как можно больше частей, чтобы затруднить обход путем изменения одной точки ветвления.
[РЕДАКТИРОВАТЬ]
Другой вариант - использовать конечный автомат . См. Пример структуры команды в верхнем ответе на этот вопрос . Поместите оценку проверки лицензии в форму хеш-поиска и набора фиктивных вызовов функций в массив вместе с нужным. Код решения, который оценивает проверку лицензии в таблице / поиске по хэшу для соответствующей функции, не будет выглядеть как ваша типичная конструкция
if(){ pass;} else { fail; }
.
Два преимущества,
1) нет логического условия для обхода и
2) они не могут выполнить простую инструкцию JMP, не зная адреса / имени функции, которой передается управление.
SO-поток в турториале конечного автомата .
SO-поток в реализациях конечного автомата
Обфускация не предотвращает , а просто обескураживает. Достаточно опытный и целеустремленный злоумышленник всегда сможет обойти любую используемую вами обфускацию, поэтому сначала вам нужно знать: каких людей вы пытаетесь остановить?
Вы можете вызвать сбой, разбросав чек по всей поверхности, например:
T* data = (T*) new char[sizeof(T) * (check() ? 1 : 0)]
array[i + 1 * (check() ? 0 : 42)].doStuff();
В Gamasutra есть хорошая статья о защите от трещин в Spyro , которая делает похожие вещи, а затем идет далее сделав так, чтобы игра не вылетала, просто работала все хуже и хуже. (Вы никогда не бьете врагов, вы ходите медленнее, некоторые важные объекты исчезают случайным образом и т. Д.)
Интересное чтение для всех программистов и, возможно, полезно для вас.
В Поваренной книге по безопасному программированию (О'Рейли) есть целая глава по защите от взлома (в самой книге есть глава, не знаю, что доступно на сайте). Хорошая штука.