пятница, 14 февраля 2014 г.

Есть ли жизнь после триала?

Предпродажная демонстрация возможностей ПО обычно сводится к двум решениям:
  1. Ограничение функциональности ПО, так называемый демо-комплект.
  2. Введение временного (тестового) периода, в течении которого ПО работает с полным функционалом, так называемая триальная версия (или попросту - триал).
Есть, конечно, варианты демонстрации возможностей в офисе разработчика/продавца, но это не относится к программированию и скорее всего называется менеджментом (или как там это умное слово называются?) :)

Как только на руки взломщику попадает именно триальная версия - он начинает довольно потирать руки, так как все что от него требуется, это заставить приложение думать, что его триальный период еще не истек.

А это, как правило, сделать довольно просто.
Есть такая старая поговорка: если что-то запустилось и работает, можно запустить и заставить работать неограниченное количество раз :)

В данной статье я попробую рассказать почему в 99 процентах случаев сделать грамотную триальную защиту не возможно и постараюсь дать точки опоры, от которых можно будет оттолкнуться при реализации такого вида защиты.


0. Слоган: "Я самая лучшая программа для создания триала!!!"


Видели такое (или вариации данного слогана)?
Если да, то смело закрывайте такой сайт - вам предложат мусор.

На данный момент не существует протекторов, готовых предоставить более-менее серьезную триальную защиту. И хотя в большинстве навесных защит такая опция присутствует - полагаться на нее особого смысла нет.

Суть триала заключается в следующем:
  1. Необходимо где либо прописать время и дату установки ("хвост")
  2. При старте приложения сверить дату из "хвоста" с текущей, и если истек триальный период - завершить работу приложения.
Очень просто и на самом деле очень сложно.

Суть проблемы заключается в следующем вопросе: а куда спрятать сам "хвост" так чтобы его не мог обнаружить и подменить взломщик?

Вариантов решения этого вопроса множество, впрочем утилит, снимающих все эти "псевдо триалы" в разы больше, впрочем...

1. Как потерять свой "хвост"?


Понятие "потеря хвоста" сводится к тому, что в качестве ожидаемых вами данных при его чтении, вы можете получить их в измененном виде, которые вам любезно предоставил взломщик.

Вариантов, куда можно сохранить "хвост", в принципе, не много:
  1. В файл на диске
  2. В реестр
  3. Опять же на диск, но в неиспользуемые файловой системой кластеры (с их пометкой как испорченные).
  4. На какой-то внешний сетевой ресурс.
Все четыре варианта являются уязвимыми по причине того, что есть набор замечательных утилит от Марка Руссиновича и Брюса Когсвела, отслеживающие операции как с файловой системой, с реестром, так и с сетью.

Впрочем большинство триальных приложений эти варианты устраивают.

Некоторые делают их модификации:
  1. К примеру пишут "хвост" не в произвольный файл, а в уже существующий (hosts или win.ini и т.п.)
  2. Пишут в реестр и "скрывают" ключ реестра, добавляя в его наименование нули, или маскируют его под каким либо CLSID.
  3. Если файл расположен на файловой системе NTFS - хранят "хвост" в NTFS потоке.
  4. Часто "хвост" шифруется разработчиком, иногда даже на асиметричных алгоритмах, наивно полагая что отсутствие Private ключа в составе ПО, обеспечит гарантию от подмены.
Вариантов таких "велосипедов" много.

В свое время, году эдак в 1997-ом, мне была поставлена задача прикрутить триал на некий софт (связанный со складским учетом), причем триал не по времени, а на количество запусков. 
Я не стал излишне заморачиваться и взял в качестве хранилища "хвоста" библиотеку, отвечающую за отображение справки. 
Если честно, я уже не помню как она там называлась, но суть крылась в следующем:
  • целостность данной библиотеки не контролировалась ОС
  • в составе ее ресурсов был битмап размерами (1х160) из черных и белых точек (кажется он использовался как картинка разделителя между параграфами)
  • логика хранения "хвоста" была примитивная - изымался данный битмап, бралось значение первого пикселя (по умолчанию он черный RGB(0, 0, 0)), производился инкремент пикселя на единицу и все писалось обратно. 
Для человеческого глаза что RGB(0, 0, 0), что RGB(10, 0, 0) не заметны, однако для кода защиты ПО - это счетчик.

Очень грубое решение и легко детектируемое - но на тот момент (97 год) оно было достаточно эффективным :)

В современных реалиях ни один из данных способов не может рассматриваться серьезно.

2. Как происходит подмена"хвоста"


Это достаточно простой этап (и самый действенный).
Если хвост не зашифрован - то взломщику нужно все лишь изменить хранящиеся в нем данные.

Вариантов два:
  1. Правим сами данные
  2. Перехватываем функции, которые читают данные и подменяем на свои
Иногда не нужно производить даже этих действий.
Если триал завязан на время и не контролирует изменение текущей даты - достаточно просто поменять время в настройках системы. 
Кстати - эта ошибка присутствует у большинства ПО с триальной защитой.

Более сложный вариант выглядит в виде правки тела приложения и отключения проверки на валидность "хвоста" с ожидаемым.

Шифрование тут не сильно спасет, ибо если взломщик решился на такой шаг, он скорее всего отреверсит и саму логику шифрации данных или вытащит сам ключ, если используется что-то стандартное.

На шифрование "хвоста" асиметричным алгоритмом закладываться так же сильно не стоит.
Во первых, кто-то должен поместить зашифрованый приватным ключом "хвост" на диск (как правило это будет делать инсталятор).
Во вторых, достаточно произвести атаку на ключ, сгенерировав свою пару приват/паблик ключей, и изменив публичный ключ в теле приложения, мы сможем выдавать ему валидные (с точки зрения взломанного приложения) данные, зашифрованные нашим приватом.

3. Как можно уйти от изменения времени


Вариантов несколько - к примеру вы знаете время установки ОС и время установки своего софта.
Самое логичное заключается в том, что текущая дата не может быть раньше этих двух составляющих, как собственно и время установки софта не может быть меньше чем дата установки ОС.
Опорными точками могут выглядеть время компиляции системных библиотек (читается из PE заголовка) которое так же не может быть больше текущей даты.
Одним из хороших решений является чтение системного журнала, по записям которого можно сверится с текущим временем.
Реестр хранит в себе множество записей с пометками о текущем времени, на основании которых можно сделать вывод о том что время системы было изменено.
Скорее всего, в случае изменения времени, выхода в интернет у вас не будет, но если он есть - не забывайте о серверах реального времени и сверяйтесь с ними.

4. И куда деть "хвост"?


В случае отсутствия внешнего хранилища, неподконтрольного взломщику - только в файл/реестр/внешний сервер.

Впрочем даже тут можно использовать несколько трюков:

К примеру время триала будет хранится в качестве составляющей GUID-а некоего COM сервера, без которого работа приложения не возможна. Нюансы с доступом к такому серверу оставляю на ваше усмотрение.

Вы работаете с базой?
Если да - храните данные в ней, но не полем, а частью некоего BLOB-а изменяемого при каждом запросе.

Вы пишете драйверы режима ядра?
Вся FS в вашем распоряжении - определитесь с местом хранения, застрахуйтесь от перехвата собственной правкой таблиц и пишите этот DWORD

Вы храните данные на внешнем сервере? 
Только шифрование - но это утопично.

5. Так есть ли жизнь после триала?


В 99 процентах случаев - конечно есть и ваше приложение во всех этих случаях будет гарантированно взломано.

Остается только один махонький процент, который обеспечивает действительный фактический триал разработчику и выглядит это следующим образом:

1. вынос логики работы на внешний сервер, где сервером принимается решение о завершении периода триала.
2. вынос логики работы на электронный ключ защиты, где по истечению заданного разработчиком периода времени, ключ перестает работать.

Только в этих условиях можно говорить о такой "бутафории" как "триал".

6. В заключение


Триал - одна из самых примитивных и не надежных схем защиты ПО.
Если разработчик пошел на этот шаг и не выбрал реализацию "демо" - видимо были определенные причины.

Впрочем, я хотел сделать только краткий обзор этой темы (без сильного разжевывания нюансов), ибо в последнее время почему-то участились вопросы на форумах о триале.

Если появились вопросы или требуется уточнение определенных моментов - я всегда на связи.

Удачи.

---

© Александр (Rouse_) Багель
Февраль, 2014

14 комментариев:

  1. "Опорными точками могут выглядеть время компиляции системных библиотек (читается из PE заголовка) которое так же не может быть меньше текущей даты."
    По идее "больше", а не "меньше".

    ОтветитьУдалить
  2. Интересно на мой взгляд реализован алгоритм у касперского, начиная с какого-то патча:
    как я понял при завершение пробного периода, информация заносится в ключ реестра, индивидуальный для каждого компьютера. Правда взломщик запускает утилиту которая мониторит обращение к реестру - по описанию ждать необходимо до нескольких суток. Т.е. касперский через рандомное время начинает обращаться к ключу. Ну и запись в потоки ntfs.

    ОтветитьУдалить
  3. Как по мне, так запись/чтение кучи CLSID в случайные промежутки времени во время работы программы в качестве текущего значения триала - вполне секьюрно.
    И даже понятно, что теоретически можно вычислить верный ключ, отвечающий за trial, но возиться с парой десятков ключей - запускать/перезапускать/работать мониторя ключи regmonitor-ом, а потом сравнивать и анализировать километровые логи - задача на любителя. А если еще и программа тяжеловесная и запускается не моментально, а с задержкой в десяток секунд.
    А если еще и эти значения CLSID на каждом компьютере уникальные, да еще и меняются от версии к версии. И апдейты программы выходят часто и регулярно.
    Вот даже и не знаю, захочет ли кто связываться.

    В IbExpert-е что-то подобное реализовано. И он кстати бесплатный если на компьютере установлен русский язык как язык по умолчанию для неюникодных программ.

    ОтветитьУдалить
    Ответы
    1. Можно сделать слепок реестра до установки и сравнить после - все такие "секурные" ключи видны как на ладони :)

      Удалить
    2. Да-да. Только там их штук 30.Тридцать штук разных GUID-в в CLSID. Остается только вычислить, какие из них секурные, а какие для отвода глаз - и это еще один квест =)

      Удалить
    3. ну это не так уж и сложно, как кажется :)

      Удалить
  4. В дополнение к идее ограничения по времени:
    ModelMaker Code Explorer довольно забавно реагирует на попытку продлить триал. Он как бы работает, но при этом сыпет Access Violation-ами. Причём так сыпет, что проще его снести чем продолжать с таким жить. И это не баг, это фича (специально у автора узнавал).
    Ну или более радикальный метод - скандально известный по Doom-у. При превышении определенного количества установок - программа форматировала жесткий диск. :D Сейчас конечно такое не прокатит. Хотя, производители железа (типа промышленных станков) до сих пор не брезгуют подобными методами - читал статью о том, что в случае если координаты станка существенно изменились - он блокируется (региональная защита - или что-то типа того). O_o

    ОтветитьУдалить
    Ответы
    1. ModelMaker не смотрел, но часто встречается такой подход:
      Суть в том, чтобы выставить фейковый триальный "хвост" наружу так, чтобы он сразу бросался в глаза (к примеру в том же реестре), плюс в довесок иметь скрытый хвост. В таких случаях я делал следующим образом: скрытый хвост был в виде 4 байт по определенному офсету в приложении, которые правил инсталятор при установке ПО, ну а открытый "хвост" просто проверялся на валидность со скрытым (код проверки был скрыт внутри виртуальной машины).

      Правда это тоже не панацея. т.к. достаточно сделать две установки и сравнить контрольнае суммы файлов, но для простых утилиток - пойдет.

      В ModelMaker скорее всего такой же подход (раз он детектирует попытку изменения триала).

      Удалить
    2. Возможно. На мой взгляд, судя по тому, что работающих креков CodeExplorer-a не появлялось в паблике со времён 6й версии (сейчас 10я) - т.е. уже лет 5, это вполне работающее решение. =)

      Удалить
    3. Или это просто "Неуловимый Джо" :)

      Удалить
    4. Это Джо и есть. Утилита достаточно специфичная(эксперт для дельфи, если помнишь я пиарил в свое время) и стоит копейки.

      Удалить
  5. Про шифрование: асинхронное -> асимметричное.
    Асинхронное это про другое.

    ОтветитьУдалить