21.02.2006
На тему защиты Shareware-программ написано уже немало, и вряд ли вы найдете что-нибудь новое в этой статье. Это лишь очерк некоторых методов, наиболее эффективных на мой взгляд. Если вы надеетесь найти здесь конкретные примеры или исходники - я вас огорчу, все описания методов защиты приведены в общем виде, статья содержит только теорию.
Некоторые способы защиты придуманы мной лично (хотя наверняка кто-то уже додумался до них раньше меня). Другие были взяты из посторонних источников. Источники я не указываю по одной простой причине - их очень много, как отечественных, так и зарубежных, и каждый из них присваивает авторство себе. Так что определить настоящего автора того или иного способа невозможно. Статья преследует лишь образовательные цели, а реализация методов предполагает знание программирования, математики и наличие творческого мышления. Любая защита требует творческого подхода, и только работая своей головой вы сможете создать что-либо уникальное, надежное и заслуживающее внимания.
Ключи регистрации Метод: Генерация ключа Для генерации ключей ни в коем случае нельзя использовать параметры, вводимые пользователем (имя, email и т.п.). Просто генерируйте ключ, который будет соответствовать некоторым правилам. Многие разработчики для проверки ключа используют регистрационные данные (например имя), генерируют ключ в самой программе, и сравнивают значения – это грубейшая ошибка. Достаточно отловить сгенерированное значение и защита сломана. Лучше используйте серийные номера, соответствующие набору правил, и не привязанные явно к чему либо.
Метод: Защита от кейгенов Используйте асимметричную криптографию, а именно – цифровую подпись (RSA, DSA, ECDSA… и др.). Подробнее об ЭЦП можно найти на том же яндексе или гугле.
Естественно, если ваша программа занимает пару сотен килобайт, и стоит полбутылки пива, то встраивать подобную защиту не имеет смысла – получится Неуловимый Джо, хотя возможно это и к лучшему. К тому же время проверки ЭЦП может занимать до нескольких секунд, так что если вы писали не клон Photoshop или Corel, то пользователю это вряд ли понравится.
Если вы далеки от криптографии и не знаете что такое электронная цифровая подпись – рекомендую все же зайти на google и поискать (в интернете информации по ЭЦП навалом).
Для тех кто в танке, т.е. прочитал и до сих пор не понял как ЭЦП может помочь – объясняю:
Вы генерируете 2 ключа – секретный (он будет хранится у вас) и открытый (прошиваете его в программу, причем желательно его зашифровать). На секретном ключе будут подписываться все регистрационные ключи, которые вы высылаете пользователям, на открытом же ключе будет производится проверка подлинности ключа – выписан ли ключ вами (регистратором), или нет. Делайте проверку подписи в первую очередь, если подпись не совпадает – сразу же прерывайте процедуру проверки ключа, тем самым вы не дадите взломщику даже узнать правила проверки ключей. Если все же взломщик получил от вас регистрационный код, подписанный на вашем секретном ключе или, покопавшись с отладчиком, обошел проверку подписи и узнал правила проверки регистрационного кода, то для написания кейгена ему понадобится до нескольких миллионов лет (примерно столько времени уйдет на вычисление вашего секретного ключа из открытого, при солидном модуле преобразований в ЭЦП). Если вы сильны в криптографии и математике вообще, то можете разработать свой алгоритм ЭЦП. Это конечно займет уйму времени, но оно того будет стоить, даже если алгоритм далек от совершенства. Дело в том, что взломщик может подменить ваш открытый ключ на свой, если он знает алгоритм используемой ЭЦП, но если вы использовали свой собственный алгоритм и не предали его огласке, то ему придется еще разбирать ваши труды, пошагово, с отладчиком, что также может затянуться на миллионы лет, все зависит лишь от вашей фантазии.
Естественно ничто не мешает предать регистрационный код огласке, подменить открытый ключ, или выпустить патч – но это уже другая история.
Метод: Hash vs RSA Недавно мне попалась на глаза статься Владимира Каталова, где он описывал, как использовать направленное шифрование для защиты программ. Суть его метода заключалась в следующем - он генерировал несколько серийных номеров случайным образом, шифровал их по алгоритму RSА на открытом ключе 128 бит, и прошивал в программу в виде ресурсов. Для проверки серийников, он шифровал введенные пользователем значения на том же открытом ключе и сравнивал с прошитыми зашифрованными значениями. Автор хвастался, что не нужен даже секретный ключ, т.к. зашифрованные ключи не нужно дешифровать. Мне лично непонятно - а зачем тогда вообще RSA? Проще хешировать эти серийники и прошить в программу, а при вводе хешировать введенный ключ и сравнивать с прошитыми. К сведению - написание собственного хеша займет не больше дня, если имеются соответствующие навыки. Реализация же RSA требует в несколько раз больше времени, а шифрование занимает намного больше ресурсов системы, чем хеширование. Дабы не повторять его ошибок используйте хеш функции, например Haval или SHA.
Также не имеет смысла использовать направленное шифрование для защиты исполняемого кода, как рекомендует Владимир. В частности, он шифровал фрагменты кода (некоторые функции, которые должны работать только в зарегистрированной копии "Advanced ZIP Password Recovery") тем же RSA, а для генерации ключа дешифрования использовал часть кода регистрации, одинаковую для всех пользователей. Не повторяйте и эту ошибку. С тем же успехом можно использовать любой блочный симметричный алгоритм, например Twofish или AES, это намного быстрее и эффективнее.
Если вы думаете, что RSA надежнее - вы глубоко ошибаетесь. Более надежным может оказаться лишь использование эллиптических кривых с модулем более 2^160 (что по стойкости равносильно RSA с модулем 2^1024), но на реализацию уйдет куча времени, а сложность преобразований сильно скажется на быстродействии. Факторизация же ключа RSA в 128 бит занимает около 143 млн. групповых операций, так что на любом домашнем компьютере секретный ключ дешифрования подбирается за несколько минут.
Метод: Привязка к железу В этом нет ничего сложного. Достаточно использовать для генерации ключа серийный номер винчестера или проца. Но есть одна загвоздка – апгрейд. Пользователь может сменить винт, проц, да все что угодно. К тому же винчестер – это первое что выходит из строя (из личного опыта). Привязываться же к метке тома просто глупо, пользователь переставит систему – и ключ будет недействителен. Хотя если ваш софт периодически работает с сетью (качалка, почтовый клиент и т.п.), и вы можете обеспечить доставку ключа в течение пары часов, то привязаться к железке – идеальный вариант. Вы можете давать пользователю возможность перезапросить ключ регистрации, т.е. он отсылает свои данные, вы выписываете ему новый ключ, а старый помещаете в базу недействительных.
Еще один вариант - использование ключевых железок (дискет, дисков, HASP ключей и т.п.). Это очень неудобно как для пользователей, так и для вас (реализатора или разработчика). Пользователю надоест каждый раз при запуске программы вставлять дискету в дисковод, или проверять, подключен ли HASP ключ. К тому же такая защита требует начальных финансовых затрат со стороны разработчика. Если вы планируете продавать свою программу через Интернет, то высылать каждому пользователю ключ или дискету может оказаться накладно. Как правило, подобная защита используется лишь для узкоспециализированного и дорогого (стоимостью >200$) ПО.
Метод: Код активации Конечно могут найтись умники, которые будут внаглую требовать новый ключ каждый день, мотивируя это апгрейдом, потерей ключа, переустановкой системы, вашей проги, или еще чем. Могут и просто использовать ключ, выложенный кем-то на обозрение. В таком случае рекомендую следующее: использовать дополнительно код активации. Привязывайте ключ к email адресу юзера, и высылайте код только на него. Лишняя защита не помешает, если вы разрабатываете действительно серьёзный продукт, рассчитывая получить миллионную прибыль. Совсем не обязательно делать онлайновую проверку ключа при каждом запуске программы. Просто используйте дополнительный ключ (код активации). Каждый раз при регистрации программы (вводе ключа), он может отсылаться на сервер, который будет уже автоматом генерить код, соответствующий некоторым правилам, и высылать его на email, соответствующий введенному ключу. Это поможет избежать таких неприятностей, как использование ключей посторонними. При каждом запросе кода активации проверяйте ключ по базе, и если этот ключ уже недействителен или не существует в базе – не высылайте код. Для оффлайновых программ (например файловых менеджеров, графических или текстовых редакторов и т.п.), такая система не подходит по вполне понятной причине – с Сетью они работают мало, или вообще отношения к ней не имеют.
Хранение ключей Хранить ключи регистрации в каком-нибудь файле или реестре ненадежно, т.к. отследить и скопировать такой ключ не представляет труда. Для хранения лучше использовать некоторый свободный кластер в файловой системе, и запрещать к нему доступ с помощью драйверов ФС, например, пометив его как поврежденный. Это не защитит на 100% от копирования, но немного затруднит процесс. Перед разработчиком возникают и другие трудности, как определение типа ФС и сложность работы с разными драйверами.
Не храните всякие "секретные" значения, которые определяют, зарегистрирована ли программа. Храните все данные регистрации в том виде, в котором пользователь их ввел.
Защита от патчинга Метод: CRC и прочие хеши Для проверки целостности файла можно использовать различные хеши и контрольные суммы. Обойти эту проверку достаточно просто, но лишняя предосторожность не помешает. Храните результаты хеширования в разделах ресурсов исполняемых файлов (желательно в зашифрованном виде), а проверке подвергайте либо исполняемый код, либо весь файл, исключая секцию, где записан хеш. Напишите свою собственную функцию хеширования. Немного усложнив жизнь себе вы очень сильно усложните жизнь взломщику. К тому же написав свою функцию хеширования вам возможно удастся найти коллизию, такую, что хеш от всего файла, будет равен прошитому в файл значению.
Вопреки распространенному мнению проверка CRC в большинстве случаев никак не защищает от вирусов. Только если вирус подменил часть кода в программе. В большинстве случаев вирус просто дописывает себя вначале программы, и запустив программу, вы в первую очередь запустите вирус, а уже потом саму программу, которая проверит свою CRC и благополучно загнется.
Метод: Опять ЭЦП Можно использовать ЭЦП для проверки целостности исполняемого файла. Проверка осуществляется на открытом ключе. К достоинствам этого метода можно отнести то, что для подмены подписи необходимо вычислить секретный ключ, так что сам результат подписи можно хранить в открытом виде в любом файле. Но не забывайте, что асимметричная криптография забирает много ресурсов.
Метод: Учимся на ошибках Если вдруг в вашей программе обнаружилась мааааленькая ошибочка, например, выскакивает access violation при сохранении файла, но при этом она никак не влияет на работоспособность программы, а лишь надоедает пользователю – то оставьте её в покое до поры до времени. Начинайте отлавливать такие ошибки только после выхода основного релиза.
Казалось бы, как это может защитить от взлома? Дело в том, что взломщик вряд ли будет отлавливать такую незначительную ошибку в вашей программе, удалять или изменять коды процедур и т.п., это для него лишнее. Его основная цель – снять защиту (слепить кейген или патч к программе). Для пользователя же основная цель – получить работоспособный продукт, и рано или поздно ему надоест видеть десяток окошек с кодами ошибок при каждом сохранении файла. Вот на этом мы и сыграем. Начинайте действовать, когда на ваш почтовый ящик начнут приходить письма с жалобами. Отловив и исправив ошибку не спешите обновлять релиз, а просто выпустите патч. Для применения патча можно проверять сразу кучу параметров, как размер, дата файла, CRC, и т.п. Тут есть 2 пути:
вы можете исправлять ошибку только в оригинальном файле, сгенерив патч как разницу между файлом релиза с ошибкой и файлом исправленного релиза,сгенерить патч как разницу между взломанным исполняемым файлом и оригинальным с исправленной ошибкой, т.е. такой, который приведет программу обратно к не зарегистрированному виду.
Второй вариант не всегда подходит, т.к. кряков к программе может быть много, и конечный результат от их действия может отличаться. Но надеюсь вы уловили суть – пользователь, сломавший защиту вашей программы либо не сможет её пропатчить, либо вернет её к первозданному виду. И ему придется выбирать между экономией нервов и денег. Взломщик же вряд ли станет возиться еще и с патчами к вашей программе. Недостаток – подобные ошибки могут просто отталкивать пользователя.
Метод: Проверка CRC из другого процесса Параллельно запускается еще один процесс, возможно как отдельная библиотека внутри того же winlogon, и из него периодически проверяется хеш главного исполняемого файла. Можно устроить и взаимную проверку по системному таймеру, значительно усложнив взлом. Этот исполняемый код можно хранить в ресурсных разделах файла, и запускать как безфайловый процесс. Пофантазируйте – может придумаете что-то оригинальнее.
Метод: Упаковщики Упаковав программу, вы сможете защитить её от дизассемблирования, но только если вы использовали нестандартный упаковщик. Например, написанный вами лично. Тот же UPX или ASPack серьёзной защитой не являются. И понятно - зная упаковщик можно распаковать любую программу. С другой стороны, используя стандартный упаковщик, вы можете подменить заголовки, его названия и т.д., значительно затруднив распаковку и дизасемблирование.
Метод: Полиморфизм Полиморфизм - это наверное один из лучших способов защиты, но за все приходится платить. Дело в том, что изменение самого исполняемого кода (например изменение адресов процедур случайным образом при каждом запуске) делает невозможным патчинг программы, но на реализацию подобной защиты уйдет уйма времени. Хотя можно ограничиться просто дописыванием какого-нибудь мусора в конец программы при каждом её запуске и/или инсталляции. Кроме того, в инсталляторе можно хранить фрагменты исполняемого кода в зашифрованном виде, при инсталляции их дешифровать, и шифровать снова на серийном номере винта, или ещё чего-нибудь, а при запуске программы снова дешифровать их. Плюсы - привязка к железу и сложность для патчинга.
Ключи шифрования Прошивать в программу ключи шифрования в открытом виде (а в каком же ещё), мягко говоря, ненадежно. При знании ключа и алгоритма на расшифровку уйдет пара секнуд. Поэтому многие разработчики используют динамически получаемые значения, например - стандартные коды ошибок системы или хеши системных файлов. Для генерации ключа можно использовать и некоторый генератор - маленькую функцию, генерирующую заранее определенное значение. Можете использовать переполнение буффера в своей программе для запуска этой функции. В отладчике смотрится очень эффектно.
Защита от отладчиков Метод: Функции API Проверка результатов API функций ядра типа IsDebuggerPresent. Защитит от ламеров, возомнивших себя крутыми хакерами. Пользы мало, но лишняя предосторожность не помешает.
Метод: Процессорное время Проверяются метки времени и счетчика процессора при выполнении любой процедуры. Если за минуту-две было выполнено лишь пару сотен команд – пора бить тревогу. Точно так же можно ставить метки вначале и в конце процедур. Если простенькая процедура выполнялась несколько минут – значит её останавливали. Как вариант - можно запускать самый обыкновенный таймер в отдельном потоке, и по прошествии нужного времени проверять, завершена ли процедура. Если нет - значит процедура остановлена. Отлавливать 2 независимых потока - это вам не одну процедурку ковырять, многие взломщики сдаются на этом этапе.
Метод: Память Подсчет контрольной суммы области памяти, где находится исполняемый код, и сравнение его с заранее прошитым значением. Таким способом можно выявить внесенные в процессе отладки исправления, и вернуть программу к первозданному виду.
Метод: Изврат Запуск фрагмента кода на нулевом кольце (если такое допускает система) и убиение дебаггера или самой программы. Это лишь идея, но зато какая!
Метод: Еще больший изврат Написав свою собственную виртуальную машину, вы очень сильно усложните жизнь взломщику. Можно возложить задачу проверки регистрации на некоторый псевдокод или скрипт, выполняющийся в вашей виртуальной машине. Протрассировать подобную защиту очень сложно, и даже для опытных взломщиков это может оказаться непреодолимой трудностью, но не забывайте - нет ничего невозможного.
Метод: Средства ввода Думаю вы уже догадались, о чем пойдет речь. Конечно же о блокировании клавиатуры и, желательно, мыши. Но не навсегда, а на время выполнения процедуры проверки регистрационного ключа. Новичков подобные методы вводят в ступор - при попадании на заранее поставленную точку останова появляется ощущение, что машина просто напросто повисла, и спасет только reset. И только дизассемблировав или протрассировав программу взломщик увидит, что блокируется клавиатура. От дизассемблирования может защитить шифрование или даже просто упаковка программы. Для малобюджетных и несерьёзных проектов этой защиты вполне достаточно.
Метод: Средства вывода Если Вы писали серьёзный продукт, например, мощный 3D редактор или солидную игру, то на время выполнения проверки регистрационного ключа можно блокировать вывод на экран. Это, конечно же, может вызвать дискомфорт у конечного пользователя, но взломщик просто задолбается отлавливать и править эту часть защиты. У начинающих кракеров иногда вызывает шок.
Метод: Контроль прерываний Ассемблер и еще раз ассемблер. Опытные взломщики знают его досконально, так что противостоять им, используя языки высокого уровня, просто бесполезно.
Защита с помощью контроля и подмены прерываний выглядит следующим образом: копируется содержимое вектора, который нужно вызвать, в новый вектор, а в исходный помещается случайное значение. Вызывается же новый вектор прерывания, вместо известного взломщику исходного. При этом отслеживание известных исходных векторов не даст взломщику ничего, кроме набора случайных значений. А постоянное применение команд разрешения и запрещения прерываний незаметно при нормальной работе программы, но очень сильно затрудняет отладку.
Другие виды защиты
Метод: Правовая защита Устанавливая программу, юзеры обычно пропускают лицензионное соглашение. Вы и сами небось всего пару раз их читали. Поэтому при установке или первом запуске программы делайте таймаут на лицензию, не давая пропустить её. В общем дайте юзеру время прочитать и все обдумать. Делайте период таймаута раза в 1,5 короче, чем время, необходимое вам на прочтение вашей же лицензии.
Если вы решили составить ЛС самостоятельно, то следуйте нижеприведенным рекомендациям:
Не пытайтесь что либо выдумать сами, для начала почитайте ЛС известных продуктов, они обычно составляются грамотными специалистами. После чего отметьте для себя важные детали и скомбинируйте.
Не повторяйте в тексте ЛС по нескольку одинаковые по смыслу фразы.
Составляйте ЛС так, чтобы оно не напоминало постановления кабмина. Делайте его понятным даже простому школьнику.
Не используйте предложения в сотню слов, как это делают многие - разбейте его по пунктам.
Если есть деньги и время лучше обратиться к специалистам.
Не давайте слишком много гарантий, исходите строго из своих возможностей.
Чтобы пользователю не приходилось читать ЛС каждый раз при переустановке проги, можете создать некую метку в реестре, обозначающую, что на этой машине продукт уже устанавливался. Если вы написали нечто уникальное, например архиватор со степенью сжатия 1:1000000000000....., и не хотите распространять его забесплатно, то конечно же, необходимо защитить свои авторские права, запатентовать алгоритм, и заверить нотариально все документы.
Метод: Социальная инженерия Лучше сразу предупредить пользователя о последствиях взлома или нелегального использования программы. Кроме того, можно и запугать. Например, что после взлома прога не будет работать как надо, или вообще может повредить систему. Для взломщика это конечно не указ, но на пользователей подействует. Хотя, если вы написали например сканер диска или какой-нибудь дефрагментатор, лучше вообще не упоминать о гарантиях и, тем более, о возможных повреждениях, т.к. если у юзера барахлит винт, то он может свалить вину за повреждения и потерю файлов на вас. Потом доказывай, кто прав. Подобные программы, даже самые известные и выпускаемые солидными фирмами, как правило распространяются по принципу "As Is".
Вообще с помощью СИ можно защитить программу не хуже, чем всеми вышеприведенными способами, если, конечно, вашей целью не является вызов хакеру или группе кракеров. Такая практика сводится не к защите от взлома, а скорее к более успешному продвижению вашей программы на рынке ПО. Пользователи охотнее покупают программы, гарантирующие качественную и надежную работу. Очень высоко ценится регулярная тех. поддержка. Бесплатная регистрация новых версий также может подействовать. Главное - не наобещать лишнего.
С помощью СИ можно и взламывать программы, хотя взломом это назвать очень сложно. Это больше походит на выпрашивание или вымогание ключей регистрации. Ни один уважающий себя хакер до такого не опустится, и не станет притворяться бедным Васей Пупкиным из Урюпинска, у которого P150 с битым винчестером, а 100 рублей на регистрацию равносильно месячному голоданию всей его семьи. Это скорее "развод", и является уделом кидал и приколистов. С другой стороны - такая ситуация может оказаться вполне реальной, и посылать ли этого Васю на три байта - решать уже вам самим. Как вариант - могут быть и угрозы, например: "...ваша программа форматнула мне винчестер, и если вы не дадите мне ключ, то я подам на вас в суд...". Тут уже явно просматривается вымогательство. Если вы уверены, что в вашей программе нет и намека на форматирование винчестера, то смело рекомендуйте автору письма дислоцироваться в генитальной аппроксимации. Бывают и предложения протестировать ПО в обмен на регистрацию. Как поступать в такой ситуации - решайте сами. Конечно, приславший подобное предложение может оказаться хорошим помощником в отладке программы, но как показывает практика - скорее всего он вообще не будет браться за тестирование. В лучшем случае сообщит через месяц, что все в порядке.
Заключение
Надеюсь, что данный материал помог вам расширить свои познания в области защиты программ от нелегального копирования, и применив свои знания и умения на практике вы все же добьетесь желаемого результата. Помните, что наилучший вариант - когда защита программы не привязана ни к какому стандарту, уникальна, и не документирована. Последний момент, конечно, спорный, так как Open Sorce действительно является кратчайшим путем к совершенствованию, но в данном случае неосведомленность взломщика только сыграет вам на руку. Я также не рекомендую разработчикам использовать чужие компоненты для защиты, желательно написать свою собственную реализацию с нуля. Но если речь идет о шифрах, хешах, или ЭЦП, то можно воспользоваться чужими трудами, сильно сэкономив себе время.
|