Ключик к сердцу Chingachguk/HI-TECH Спецвыпуск: Хакер, номер #057, стр. 057-094-3 $30 – и вся защита! Перейдем к построению общей схемы алгоритмов и компонент защищенного программного продукта. Начнем с защищаемого кода. Пусть имеется "нетронутый" защитой build release разработчика. Назовем его prog.exe. Его необходимо защитить аппаратным ключом таким образом, чтобы было очень сложно (а лучше невозможно) использовать функциональность prog.exe в отсутствие ключа. Простые подпрограммы проверки наличия ключа сведут на нет все достоинства аппаратной защиты: при их обнаружении и удалении они оставят реверсеру prog.exe в первозданном незащищенном виде, поэтому интеграция проверок с телом prog.exe должна быть максимальной. Например, самое простое - число проверок должно стремиться к максимально возможному, насколько это позволяет быстродействие обмена данными с ключом из prog.exe, но разработчики обычно не знают меры в этом и, по всей вероятности, используют простую формулу "Время торможения программы из-за присутствия аппаратной защиты = 2 x максимальное время терпения пользователя" ;-). Идем дальше. Максимальным количеством проверок дело обычно не ограничивается, хотя история взломов программ, защищенных dongle'aми, знает множество примеров того, как разработчик выполнил... Две-три тривиальные проверки наличия ключа, которые по сложности взлома в мириады раз уступают качественно спроектированной защите на основе обычного кода активации. Здесь используются техники, присущие всяким программам, в которых необходимо скрывать код/алгоритмы - от троянов и вирусов до хитрых математических библиотек. Такие техники изначально совершенствовались вирусописателями, например в полиморфных вирусах. Но в наше время разработчики защит вполне уверенно используют их, нисколько не заботясь о чужом (пусть и незарегистрированном) копирайте. Итак, в код prog.exe максимально плотно внедряются алгоритмы проверки наличия и валидности ключа. Необходимо отметить криптографические методы привязки ключа к prog.exe. Допустим, ключ может аппаратно реализовывать функцию: typedef struct { ... } tSecrectKey; tSecrectKey Get_SecretChiperKeyFromDongle( void ) { ... } Получив в программе по запросу к ключу SecrectKey, программист может выполнить шифровку/дешифровку собственного кода. Например у prog.exe есть еще secret.dll, в которой находятся важные функции. Разработчик выполняет шифрование тела secret.dll неким хорошим криптографическим алгоритмом: Chiper.DLL = Encrypt(secret.dll, SecretKey) Далее в своей программе prog.exe он предусматривает, что при ее запуске произойдет расшифровка критичного кода: secret.dll = Decrypt(Chiper.DLL, SecretKey) Разумеется, SecretKey не содержится внутри prog.exe - она может взять его только из аппаратного ключа, если выбранный алгоритм Encrypt/Decrypt стойкий. А его возможно выполнить из широкого спектра известных и проверенных алгоритмов - DES, AES, BlowFish... или даже рискнуть написать свой, особенно если жалко денег на лицензионный и криптографически вроде бы неуязвимый. |