Защита shareware приложений от взлома с помощью armadillo. Часть 2

September 18, 2007


Специализированная программная система SoftwarePassport/Armadillo Software Protection System
(ее домашний сайт http://www.siliconrealms.com/ ) служит для защиты созданного вами программного
обеспечения на языках (delphi/c++/.net) от взлома. Добавляет функции trial периода по 
различным критериям: время работы, количество запусков. Обеспечивает функции защиты от взлома,
позволяет контролировать работу программы в сети (сетевое лицензирование). Есть методы
привязки к аппаратному обеспечению. Достаточно простое api позволяет вызывать функции armadillo
из программ на разных языках.
В прошлый раз я начал рассказ о специализированной системе защиты ПО: armadillo. Armadillo выступает в роли “бронированного сейфа”, скрывая и защищая внутри себя некоторую программу от взлома. Для доступа к которой мы создавали ключи и сертификаты. Сегодня я продолжу рассказ об особенностях создания сертификатов, о привязке созданных ключей к конкретному “железному” обеспечению, а также покажу, как можно создать приложение, взаимодействующее с armadillo с помощью специального программного интерфейса (api).

В прошлой статье я остановился на том, что рассказал об методике создания сертфикатов – в терминологии armadillo – это правило по которому мы можем использовать защищенную программу. Я рассказал обо всех основных приемах: ограничение по времени работы, ограничение по количеству запусков, ограничение на время установки/первого запуска. Осталось рассмотреть еще немного хитростей. Прежде всего, это правило “обновления сертификатов”. Итак, если вы выпускаете и продаете как shareware некоторый программный продукт, то очевидно, что несколько последующих версий (исправлений/дополнений) пользователь должен получать бесплатно. Когда вы создаете сертификат, и этот сертификат не является сертификатом по-умолчанию (напоминаю, что этот сертификат устанавливается автоматически и традиционно именно в нем закладываются ограничения на использование нашей shareware-программы). Так вот при создании обычного сертификата, вы можете указать на закладке “Upgrade Keys” перечисление тех сертификатов, с которых возможно выполнить обновление версии. Например, сертификат версии “basic” может быть обновлен на сертификат версии “professional” и так далее. Как именно разделить функционал программы по уровню сертификата я расскажу немного позже. Если пользователь имеет ключ к сертификату “basic”, то он может купить ключ для сертификата “professional” (разумеется, что обмануть armadillo и установить новый сертификат без предыдущего не возможно).'

Настоятельно рекомендую заранее предусмотреть все возможные способы использования вашей программы (например, разделение по функционалу, срокам работы) и создать сертификаты для всех этих действий. Так при выполнении операции “защитить программу” все сведения о сертификатах шифруются и вкладываются внутрь вашей программы. Соответственно если вы выпустите ключ для сертификата неизвестного на момент защиты программы или же этот сертификат был отключен (закладка “other options”), то такой ключ будет не распознан. Если вы после создания защищенной программы даже просто поменяли некоторые параметры сертификата (например, увеличили время работы), то он также не будет распознан при вводе ключа.

Для защиты созданных ключей от многократного дублирования, когда один и тот же, (пусть даже честно купленный), ключ используется на множестве разных компьютеров, можно применять две базовые методики: привязку к аппаратному обеспечению и сетевое лицензирование. Сначала об более простом и (более удобным, если быть честным) методе сетевого лицензирования. Есть две базовые методики: “peer-to-peer” и “client-server”. В первом случае при запуске программы выполняется поиск по локальной сети запущенных версий этой программы и проверяется, под каким ключом они работают. Если некоторое число одновременно работающих копий было превышено (это число можно указать на закладке “Network Licensing” и не должно быть более чем 255), то запуск программы блокируется. В зависимости от загрузки сети время запуска программы может увеличиваться, но основную сложность составляет все же работа с firewall, который может блокировать служебный трафик armadillo. Как вывод, режим “peer-to-peer” говорит, что ключи должны быть установлены на каждой из клиентских машин, просто в одно время не возможно запустить более чем X экземпляров, использующих одинаковый ключ.

Второй режим сетевой защиты – “client-server” предполагает, что в сети предприятия существует специальный сервер лицензирования, который и хранит сведения о ключах. При запуске программа соединяется с этим сервером, который и принимает решение о возможном или нет запуске защищенного приложения.

Для каждого из этих двух режимов можно управлять признаком “копия”. Что считается за копию программы – каждый ее запущенный экземпляр (даже если пять штук запущены на одной машине) или же количество собственно компьютеров. Также сведения об том предельном количестве копий может быть сохранено не внутри сертификата - а ключа. Это избавляет вас от необходимости создавать двадцать сертификатов-клонов отличающихся только одной цифрой: 1,2,…10,11 одновременно запущенных экземпляров. Для режима “client-server” интересна и опция “don’t fall back to standalone mode”. Проще говоря, что делать, если сервер не запущен или не может быть найден в сети. Если это случилось, то при включенной опции запуск программы будет не возможен, иначе будет использован установленный на локальной машине ключ. Теперь вопрос: а откуда возьмется этот самый сервер лицензирования? Сервер лицензирования будет встроен в саму программу. Например, я решил защитить стандартный калькулятор windows, после чего получил новый файл размером в 750 кб. (и это выросло из исходный 150 кб.). Для того чтобы запустить сервер я выполнил из командной строки команду: “calc.exe SERVER”. После чего появилось окно со статистикой, где отображено то, сколько копий программы было уже запущено и запуск лишних блокируется, как это показано на рис.1.



Через 60 секунд окно сервера автоматически будет скрыто, но если же вы хотите его полностью завершить, то используйте строку команды: “calc.exe SERVERDOWN”. Поиск сервера выполняется автоматически по всей сети, но если вы хотите переопределить этот параметр, то возможно в файле настроек (это текстовый файл в формате ini, который должен размещаться в той же папке что и собственно защищаемая программа) указать конкретный IP-адрес сервера. На этом про сетевую защиту все – переходим к методам привязки к аппаратному обеспечению.

Комплектующие, из которых состоит ваш компьютер, имеют свои уникальные цифровые отпечатки. Еще до создания сертификата в свойствах проекта armadillo вы на закладке “Std Hardware locking” включаете отметку “unlock”, затем решаете какие именно “железки” компьютера будут считаться как уникальные. Возможно выбрать CPU, BIOS, сетевое имя компьютера, информацию о геометрии жесткого диска, его параметры SMART, также уникальный номер MAC сетевого адаптера, объем физической памяти. Главное относиться к пользователю уважительно и дать ему возможность менять не ключевые компоненты компьютера без лишних сложностей. Например, привязка к сетевому имени или объему памяти слишком жесткая. В любом случае на этой же закладке “Std Hardware locking” вы можете указать некоторое число – предельное количество сменившегося оборудования. После чего необходимо создать новый сертификат для которого на закладке “hardware Locking” отметить какой режим аппаратной привязки будет использовании: стандартный или расширенный. Если вы все сделаете правильно, то диалоговое окно ввода ключа при регистрации изменится: появится строка со значением вашей “аппаратной подписи” см. рис. 2. Этот же номер следует указать при генерации ключа.



При работе с hardware-основанными ключами можно делать две интересные операции: перенос ключа и отказ от ключа. В первом случае вы хотите ключ привязанный к машине “A” перенести на машину “B” (естественно, что при этом первоначальный ключ станет не действительным и запустить с его помощью программу на первой машине будет уже не возможно). Ранее мы опускали вопрос того, какой именно алгоритм используется armadillo для генерации ключа. На самом деле это очень важно, так если вы зайдете на первую же закладку при создании сертификата “name/template/sig.level” то увидите набор радио-переключателей управляющих тем как будет формироваться и защищаться сам ключ. Общее правило таково: чем выше уровень “signature”, тем надежнее. Однако если вы хотите создать аппаратный ключ и разрешить для него операцию переноса, то необходимо использовать режим “unsigned” (без специальной защиты).

После чего вы можете на закладке сертификата включаете отметку пункта “allow TRANSFER command” и теперь можно запустить программу из командной строки с параметром TRANSFER. После того как вы согласитесь с тем, что ключ перестанет после переноса работать на вашем компьютере, необходимо в еще одном диалоговом окне указать значение “цифрового снимка” для того компьютера, на который вы хотите выполнить перенос ключа. После чего в корне диска “c:\” появится файл с именем “transfer.txt”, в котором и будет находиться новый сгенерированный ключ, действительный для другого компьютера.

При запуске программы вы можете указать некоторый набор параметров командной строки, мы уже познакомились с опциями SERVER и SERVERDOWN, когда разбирали методы лицензирования по сети. Также можно использовать параметр INFO – он приводит к появлению на экране окна сообщения с регистрационным номером (довольно опасная вещь, скажу прямо). Затем REGISTER приводит к появлению окна ввода ключа, даже если программа уже зарегистрирована, это полезно, в случае если вы хотите сменить сертификат, например, перейти с “basic” версии на “professional”. Аналогично опция UNREGISTER приводит к отмене регистрации. При этом появляется специальное диалоговое окно, в котором находится специальный код – подтверждение отмены регистрации. Клиент может отправить его разработчику программы, мол, так и так, не понравилась мне ваша программа и я возвращаю вам этот ключ, а также прошу вернуть мне мои денежки. Естественно, что если вы после этого решите схитрить и попробуете ввести старый ключ повторно, то получите сообщение об ошибке “ключ был израсходован, давайте новый”. В свою очередь разработчик получив от клиента код подтверждения об отказе, не обязан верить ему на слово и используя меню: “keys->check key” в специальном диалоговом окне вводит имя пользователя, его ключ, цифровой отпечаток компьютера (fingerprint), а также код отзыва. И в результате получает подтверждение или наоборот узнает, что его хотели обмануть и подсунуть фальшивый код отзыва.

При генерации аппаратно-зависимого ключа можно использовать режим привязки к ключу расположенному на USB-флэшке. К сожалению, я так этот режим не попробовал, поскольку мало того, что мне нужна какая-то особая флэшка (чем именно она так “особенна” можно узнать на сайте www.u3.com), так еще и ключи не возможно сгенерировать без помощи какой-то организации digital river. А идея, вообще-то, очень хороша: информацию о регистрации программы хранится не в реестре компьютера, а на USB-носителе, так что, придя и сев за любой компьютер, вам достаточно вставить флэшку с ключом - и программа заработает.

Чем больше я разбираюсь с возможностями armadillo,тем более удостоверяюсь, что забота об удобстве конечных пользователей у них на первом месте. Вот, например, такая простая ситуация: для того чтобы защитить программу от “timeback” (методика взлома, основанная на откате в прошлое значения системных часов) armadillo блокирует запуск программы, если “timeback” был обнаружен до тех пор, пока вы не вернете часы назад. Однако возможен и “несчастный случай”, когда у вас по какой-то причине часы были установлены в будущем времени, а затем вернули их в настоящее (правильное). Armadillo, естественно, не может отличить этот случай от злонамеренного timeback. Но предлагает сгенерировать вам специальный fixclock ключ, который может быть отправлен незадачливому клиенту. Он в свою очередь запускает вашу программу с параметром командной строки “FIXCLOCK” и вводит присланный ему ключ, после чего armadillo исправляет отсчет времени. Естественно, что fixclock ключ не вечен, и через пару дней он станет не действительным.

Если запустить вашу программу с параметром командной строки

SHOWNETUSERS, то вы увидите перечисление имен тех компьютеров, на которых запущены в режиме сетевого лицензирования “peer-to-peer” копии вашей программы.

Почти все описные мною выше опции командной строки, можно предварить ключевым словом SERVER, например SERVER FIXCLOCK. В этом случае опция будет действовать на сервер лицензирования в модели “client-server”.

Теперь, как я и обещал ранее, пора рассказать о методиках создания программ взаимодействующих с armadillo напрямую, о том как используя вызовы специальных функций api можно получить информацию о регистрации, вносить/удалять/изменять ключи самому. Простейшее применение, это разделение возможностей программы на несколько уровней: “basic”, “professional”. Мы научились создавать сертификаты различных уровней, но как спросить: а какая версия сертификат используется? Или спросить, а сколько дней осталось до завершения trial-периода этой программы? Самый простой способ организации подобного взаимодействия – использовать переменные окружения или возможно вызывать специальные функции, находящиеся в файле “ArmAccess.dll”. Стоит упомянуть, что на самом деле эта библиотека играет роль заглушки и просто перенаправляет все вызовы внутрь встроенного в сам защищаемый файл кода – одним словом библиотека получается виртуальной, что не совсем мешает вызывать из нее методы традиционным методом LoadLibrray, GetProcAddress или через декларацию “external”. Далее я создал приложение на Delphi в виде одной формы на которой разместил два текстовых поля: одно для ввода имени пользователя, второе – для ввода кода регистрации, также потребовалась кнопка по нажатию которой и происходит проверка введенного ключа и его последующее сохранение. Кроме того, моя программа будет защищена сертификатом по-умолчанию с лимитом в 100 запусков, поэтому я создал текстовое поле в которое при запуске формы заносится число равное количеству оставшихся запусков. Для того чтобы форсировать увеличение числа запусков я создал еще одну кнопку. И наконец, я покажу вам прием работы со слотами пользовательской информации. В защищенной armadillo программе можно создать девять ячеек, которые будут защищены, зашифрованы и помещены в секретное хранилище, так что эта информация сохраняется между несколькими запусками программы. Результат работы программы виден на рис. 3.
  1. Function SetUserString (which:LongInt;str:PChar) : Boolean; stdcall; external 'armaccess.dll';
  2. Function GetUserString (which:LongInt;buffer:PChar;bufferlength:LongInt) : LongInt; stdcall; external 'armaccess.dll';
  3. Function InstallKey (name,code:PChar) : Boolean; stdcall; external 'armaccess.dll';
  4. Function IncrementCounter : Boolean; stdcall; external 'armaccess.dll';
  5.  
  6. procedure TForm1.Button1Click(Sender: TObject);
  7. begin
  8.   if InstallKey (PChar( txtUser.Text), PChar (txtKey.Text)) then
  9.     ShowMessage ('Порядок, под подошел')
  10.   else    
  11.     ShowMessage ('Ошибка');  
  12. end;
  13.  
  14. procedure TForm1.btnIncCounterClick(Sender: TObject);
  15. begin  
  16.   IncrementCounter;
  17. end;
  18.  
  19. procedure TForm1.FormCreate(Sender: TObject);
  20. begin  
  21.   labCounterValue.Caption := GetEnvironmentVariable('USESLEFT');
  22. end;
  23.  
  24. procedure TForm1.Button2Click(Sender: TObject);
  25. begin  
  26.   SetUserString(0, PChar(txtSecret.Text));
  27. end;
  28.  
  29. procedure TForm1.btnGetSecretClick(Sender: TObject);
  30. var s: array[0..255] of char;
  31. begin 
  32.   GetUserString(0, s, 255); 
  33.   txtSecret.Text := s;
  34. end;


Завершу я данную статью, пожалуй, на следующем неприятном моменте: многие системы защиты (и armadillo не исключение) используют для хранения информации об установленном ключе реестр windows. Создавая для этого всяческие “мусорные” ключи имитирующие “правильные” записи реестра. Соответственно, если пользователь выполняет чистку реестра от мусора с помощью некоторых программ чистильщиков, то с некоторой долей вероятности возможна ситуация, когда эти ключи будут потеряны и необходимо будет выполнять повторную регистрацию. Приятный побочный эффект в том, что записи о регистрации некоторой триальной программы также могут быть “утеряны” и отсчет времени будет начат заново – на этом эффекте построены специальные “хакерские” утилиты чистильщики. Названий я специально не привожу – их легко можно найти в интернете. Как ведут себя разработчики чистящих утилит в плане сохранять или удалять ключи регистрации - вопрос открытый и прямых ответов они стараются избегать. Но даже если бы подобные ключи сохранялись, то вопрос осложняется тем, что рынок armadillo-подобных систем защиты достаточно велик, существует множество экзотичных продуктов, некоторые из которых уже покинули наш мир. Так что, есть вероятность после переустановки windows или прогонки подобной утилитой чистильщиком потерять информацию о регистрации программы. Максимум что я могу вам посоветовать - изучить api для armadillo и комбинировать стандартные методики защиты со своими собственными.

Хотя возможности armadillo остались еще не полностью рассмотренными, но все же, эту серию статей я временно приостанавливаю. Я планирую вернуться к armadillo и другим схожим с ним продуктам попозже, и рассмотреть несколько сценариев защиты для flash/java/php/.net-основанных приложений.