Защита программных продуктов

Автор: manager Воскресенье, Март 16th, 2008 Нет комментариев

Рубрика: Безопасность

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

Один из способов защиты программного обеспечения — использование программно-аппаратных алгоритмов, отличающихся от программных использованием в своем составе аппаратных электронных ключей. Современные электронные ключи — это достаточно сложные (и дорогостоящие) устройства с энергонезависимой памятью, предназначенной для хранения различных данных, участвующих в самой защите, «прозрачные» для разных периферийных устройств, в разрыв с которыми включают эти ключи. Немного о технологиях, применяемых в электронных ключах «Stealth».
Использование микропроцессорной технологии (а куда сейчас без нее?). Электронные ключи, выполненные по технологии Stealth, имеют встроенный микроконтроллер. Это обстоятельство открывает множество принципиально новых возможностей защиты (а заодно и возможностей снятия их :) ).
В процессе создания защиты используются аппаратные алгоритмы типа Y=F(X). В отличие от своих прототипов, Stealth-ключи имеют аппаратные алгоритмы кодирования данных. Они обеспечивают дополнительный уровень защищенности от взлома.
Используется до 18 алгоритмов в одном Stealth-ключе, т.е. в одном Stealth-ключе можно организовать до 18 различных аппаратных алгоритмов и, соответственно, для защиты одного программного продукта можно одновременно пользоваться несколькими алгоритмами (до 18). Это еще больше усложнят процесс взлома защиты.
Аппаратные алгоритмы обладают достаточно высокой сложностью. В формировании каждого аппаратного алгоритма участвует так называемый определитель — последовательность байт, защищенная от чтения и модификации. Длина определителя может достигать 200 байт или 1600 бит. Нетрудно подсчитать, что для подбора алгоритма с таким определителем придется перебрать до 21600 различных комбинаций. Взяв минимальное время работы такого алгоритма, получим, что для его подбора потребуется порядка 10475 тысячелетий (теория, теория…).
Уникальность аппаратных алгоритмов каждого пользователя защиты. Каждый пользователь защиты на базе Stealth-ключей получает электронные ключи с несколькими созданными по умолчанию аппаратными алгоритмами, вид определителя которых уникален.
Есть возможность создания собственных аппаратных алгоритмов. В результате электронный ключ станет кодировать данные по алгоритму, конкретный вид и свойства которого будут отличаться от свойств и вида другого ключа.
Использование свойств аппаратного алгоритма. В создании аппаратного алгоритма Stealth-ключа участвует также и комбинация свойств алгоритма, которую можно задать самому. Можно сделать алгоритмы одинаковыми у всех Stealth-ключей для данного защищаемого программного продукта, либо сделать их зависимыми от абсолютно уникальной величины — ID Stealth-ключа. Можно создать алгоритм с ограничением числа его запусков для надежной защиты демо-версий программ.
Кодирование до 255 байт данных одновременно. Любой из аппаратных алгоритмов Stealth-ключа за один сеанс способен обработать до 255 байт (или 2040 бит) данных. Причем на шифруемую последовательность длиной N байт накладывается нециклическая шифрующая последовательность длиной N байт. Возможность кодирования большого объема данных обеспечивает дополнительную защиту от подбора верных ответов Stealth-ключа.
Наличие «быстрых» алгоритмов. Помимо аппаратных алгоритмов, можно использовать для защиты алгоритм быстрого преобразования данных. Эта возможность позволяет производить кодирование сверхбольших объемов данных с такой высокой скоростью, что сам процесс будет совершенно незаметен для пользователя защищенного приложения.
Множественность кодов доступа к электронному ключу. Для выполнения любой операции со Stealth-ключом требуется задать код доступа к нему. Существуют Общий код и 3 Личных кода доступа. Не зная какого-либо из Личных кодов, невозможно выполнить с ключом и соответствующий этому коду набор операций. Использование нескольких кодов доступа значительно осложняет задачу получения любого нелегального доступа к Stealth-ключу.
Аппаратные запреты. Можно наложить аппаратные запреты на чтение или запись любой области доступной памяти Stealth-ключей. И тогда никакими программными средствами не удастся ни считать, ни модифицировать данные, записанные в этой области памяти (если бы все было так).
Кодирование данных в памяти Stealth-ключа. Все данные хранятся в памяти Stealth-ключей в кодированном виде, причем в каждом ключе кодирование производится уникальным образом. Самим же процессом кодирования/декодирования занимается микроконтроллер ключа. Такой метод хранения данных теоретически делает бессмысленным их считывание — даже при помощи дорогостоящих аппаратных устройств. Например, для получения аппаратной копии ключа нужно эти данные записать в другой Stealth-ключ (так называемый ключ-копию). Но микроконтроллер любого другого Stealth-ключа будет неверно интерпретировать эти данные, так как будет декодировать их иначе — в соответсвии со своим алгоритмом (тогда какая это, блин, копия?).
Аппаратная блокировка отладчиков. Stealth-ключ имеет уникальную аппаратную защиту от изучения логики его работы под отладчиком. Если ключ обнаружит, что протокол обмена с ним выполняется в среде отладчика (а в этом случае все временные интервалы неизбежно увеличиваются), он попросту перестает отвечать на любые запросы.
Это по поводу прозрачности ключа — периферийное устройство работает как-будто бы без него.

Протокол обмена со Stealth-ключом:
«Плавающий». Вместе с реальными данными между защищенной программой и ключом передается специально генерируемый «мусор»— ничего не значащие данные (для исследования-то они как раз значащие).
Кодированный. Все данные, курсирующие между программой и электронным ключом, непрерывно кодируются.
Эти два свойства протокола помогают обеспечить надежную защиту от создания эмуляторов Stealth-ключей.
Самонастраивающийся. В процессе работы происходит оптимальная настройка параметров протокола на особенности аппаратного и программного окружения.
С автоматической верификацией. Любая операция записи в память Stealth-ключа сопровождается автоматической операцией верификации — записанные данные обязательно проверяются на адекватность.
С автоповторами. Если из-за помех, вносимых другими устройствами, при обмене с ключом возникает сбой, то производятся автоматические повторы выполнения операции.
Эти свойства значительно повышают надежность обмена со Stealth-ключом и обеспечивают ему высокий уровень совместимости с аппаратным и программным обеспечением.

Исследование и снятие защиты.
Создание аппаратной копии электронного ключа.

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

Создание аппаратных копий ключа применимо только в тех случаях, когда известен конкретный тип микросхемы памяти, когда имеется программатор для записи данных в микросхему памяти ключа-копии и, самое главное,— при условии, что память электронного ключа никак не защищена от ее нелегального считывания. Именно это третье условие и стало слабым местом некоторых марок электронных ключей, именно слабость (а то и полное отсутствие) защиты данных в памяти ряда ключей обусловило распространение и успешное применение этого метода взлома.

Методу присущи несколько недостатков. Главный из них в том, что, даже получив нелегальную копию программы, не удастся решить задачу ее незаконного распространения — ведь копия так и осталась защищенной, просто теперь она “привязана” к “левому” электронному ключу. Кроме этого, достаточно велика стоимость такого копирования — зачастую дешевле просто купить легальную копию продукта. Поэтому такой метод не получил широкого распространения.

Создание эмулятора электронного ключа.

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

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

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

Но в любом случае эмуляторы должны верно воспроизводить не только посылаемые ключом данные, но и протокол обмена с ним (в противном случае защищенная программа не сможет «понять» передаваемые эмулятором данные).

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

1. «Плавающий» протокол обмена с электронным ключом. Данные, передаваемые между электронным ключом и программой, искусственно «зашумляются», причем с течением времени характер передаваемого вместе с данными «шума» меняется хаотическим образом. Так как эмулятор обязан воспроизводить не только поступающие от ключа данные, но и все особенности протокола обмена с ним, «зашумление» протокола обмена сильно усложняет (и удорожает) задачу написания эмулятора. В настоящее время практически все разработчики электронных ключей применяют «плавающие» протоколы обмена.

2. Использование для защиты аппаратных алгоритмов электронного ключа. Оно позволяет существенно усложнить логику работы ключа — на запрос программы он будет возвращать нечто гораздо более сложное, чем просто «да / нет». Соответственно, для того чтобы написать универсальный эмулятор такого ключа, нужно как минимум составить список верных ответов на все возможные вопросы, что может быть чрезвычайно трудоемко и дорого. Сегодня электронные ключи многих марок содержат аппаратные алгоритмы, отличающиеся степенью сложности и свойствами. Однако, к сожалению, отнюдь не всякий аппаратный алгоритм способен надежно защитить электронный ключ от эмуляции. Для этого аппаратный алгоритм должен быть сложным, чтобы его нельзя было вычислить эмпирическим путем; он должен уметь обрабатывать большой объем информации за один сеанс (например, если алгоритм может одновременно преобразовывать только 2 байта данных, это означает, что количество всех возможных вопросов — а значит и ответов — ключа равно 65536. Для составления полной таблицы ответов такого ключа потребуется меньше часа. Электронные ключи у разных пользователей системы защиты должны содержать разные аппаратные алгоритмы, чтобы нельзя было написать универсальный эмулятор для всех электронных ключей этой марки.

Отделение модуля автоматической защиты.

Метод автоматической защиты готовых программ (его еще называют методом envelope или «конвертом» защиты) доступен практически во всех системах программно-аппаратной защиты. Его преимущества: при помощи специальной утилиты в считанные секунды можно «повесить» защиту на любую готовую программу. Экономится масса времени, которого всегда не хватает, не требуется никаких навыков в области построения защиты, а порой этот метод вообще является единственно возможным (например, если по каким-либо причинам недоступны исходные тексты защищаемых программ). Однако у этого метода есть слабое место. Так как защита устанавливается на готовую программу, она не может образовать с программной неразрывного целого. Модуль автоматической защиты как бы «приклеивается» к программе, а это значит, что есть теоретическая возможность отделить, «отклеить» его — причем без ущерба для самой программы. Да и опыт в этом плане накоплен большой, есть даже специальные утилиты автоматического взлома программ, защищенных таким методом.

Абсолютно надежного способа противодействия взлому автоматической защиты не существует, и ее взлом — это лишь вопрос времени. А время взлома такой защиты, в свою очередь, зависит от ее качества. В наибольшей степени страдает автоматическая защита тех систем, разработчики которых не учли уже используемых специфических приемов взлома. Но существует и весьма надежная автоматическая защита, которая не поддается «стандартным» утилитам автоматического взлома и вынуждает выполнять большую часть работы вручную. Соответственно возрастает стоимость взлома, и в ряде случаев оказывается более выгодным приобрести легальную копию программы.

Другой действенный метод спасти защиту от быстрого взлома — это комбинирование автоматической защиты с защитой при помощи функций API. В этом случае, даже «отсоединив» модуль автоматической защиты, еще не получим незащищенной программы — во многих местах ее тела останутся нетронутыми вызовы функций API защиты.

Удаление вызовов функций API.

Помимо автоматической защиты, в распоряжение пользователя предоставлен набор функций API защиты. Как правило, API существуют для всех популярных языков программирования и содержат самые разнообразные функции. Пользователь защиты должен вписать вызовы нужных функций в исходный текст защищаемой программы, скомпилировать и слинковать его с соответствующим объектным модулем API. В результате защита будет внедрена глубоко в тело программы, и при правильной организации логики своей работы будет составлять с программой неразрывное целое. Взломать защиту такого типа гораздо сложнее, чем автоматическую — хотя бы потому, что невозможно создать универсальное средство автоматического взлома. При помощи дисассемблеров и отладчиков изучается логика работы программы, находятся места, в которых происходят вызовы функций API (либо точки входа в сами эти функции — смотря что оказывается проще), и нужным образом исправляется программный код. Для борьбы с этим методом взлома есть несколько испытанных способов:

1. Комбинирование защиты при помощи функций API с автоматической. Хорошая автоматическая защита умеет защищать программу и от дисассемблера, и от отладчика. Следовательно, для того чтобы использовать весь инструментарий в полную силу, придется сначала «снять» модуль автоматической защиты. Кстати, именно поэтому все разработчики защиты рекомендуют комбинировать оба метода. Модуль автоматической защиты должен образовывать «внешний уровень обороны», защищая программу от дилетантов и скрывая от любопытных глаз ядро защиты, реализованное функциями API. 2. Усложнение логики работы самих модулей защиты. Профессиональные системы защиты имеют в своем арсенале много внутренних методов борьбы с изучением логики их работы. Кодирование тела модулей автоматической защиты и библиотек API, «зашумление» фрагментов их кода, подсчет контрольных сумм важных участков кода — эти и многие другие меры способны существенно усложнить процесс исследования логики работы самих модулей защиты.

3. Разработка нетривиальной логики взаимодействия программы и защиты. Не приходится рассчитывать на приемлемый уровень защищенности программы, если информация, возвращаемая функциями API, используется программой для банального сравнения: «верно / неверно». Есть множество эффективных приемов усложнения логики работы программы с модулями защиты. Откладывание реакции программы на информацию, полученную от ключа, использование ответных данных ключа в качестве индексов каких-либо массивов, подсчет контрольных сумм данных с использованием значений, полученных от ключа и т.д.— это лишь наиболее простые из таких приемов. Воспользовавшись ими и им подобными, можно создать защищенную программу, разобраться в логике работы которой будет уже сложнее. В результате шансы удалить из программы все вызовы функций API без последствий для самой программы станут минимальными. «Остатки» защиты постоянно будут проявляться во взломанной программе, ограничивая ее возможности и нарушая нормальный ход ее работы. Такую программу можно рассматривать лишь как демонстрационную — ведь пользователь не сможет использовать все ее возможности и рано или поздно будет вынужден приобрести легальную копию такой программы.

4. Использование ответов аппаратных алгоритмов в работе программы. На этапе установки защиты важные для программы данные можно закодировать при помощи аппаратного алгоритма ключа и в таком виде записать их в тело программы. В процессе работы программа в нужные моменты будет запускать аппаратный алгоритм, декодирующий эти данные, а затем использовать их по назначению. При такой схеме организации защиты даже полное удаление из программы всех обращений к функциям API ничего не дает. Ведь защищенная программа содержит свои важные данные в кодированном виде, и раскодировать их, не имея электронного ключа, нельзя.

Кого заинтересовала данная тема — можете подробнее почитать о ключах Stealth здесь.

Источник: http://www.sura.ru/shadow/

Оставить комментарий

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

Похожие посты