Введение в архитектуру компьютеров

Способы увеличения эффективности и надежности защиты от копирования


Остановимся на существенных недостатках известных программных механизмов защиты от НСК и укажем основные пути и способы увеличения их эффективности и надежности;

· большинство защитных механизмов является пристыковочными и отрабатывает, как правило, один раз перед передачей управления на исполняемый код защищенной программы;

· отсутствует возможность теоретической оценки надежности системы защиты от НСК. Сегодня качество защитных механизмов того или иного пакета оценивается субъективно по времени, которое требуется для снятия защиты с защищенной программы конкретному человеку;

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

-для аппаратной заглушки используется способ сканирования компьютеров при помощи подключения через "прозрачную" аппаратную заглушку второго компьютера, который отслеживает все передаваемые между компьтером и заглушкой сигналы;

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

· используемые дефектные секторы на дискете всегда можно определить предварительным тестовым считыванием ключевой дискеты, после чего ключевая дискета уже не нужна.

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

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

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

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



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

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

Следующий способ борьбы с дизассемблером – это применение нестандартных приемов выполнения некоторых команд с нарушением общепринятых соглашений.


Среди них:

· использование нестандартной структуры программы;

· скрытые переходы, скрытые вызовы программ и прерываний;

·   переходы и вызовы подпрограмм по динамически изменяемым адресам.

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

Второй способ предполагает использование нестандартной реализации команд типа JMP, CALL, INT, RET, IRET.

Третий способ подразумевает модификацию байтов адреса перехода или вызова подпрограммы.

Не менее сложная задача для "взломщика" – преодолеть недопущение исследования программ стандартными отладчиками.

Эффективным средством против пошагового выполнения программы отладчиком является назначение стека в тело программы. Если в целях недопущения переназначения стека за пределы исполняемого кода в стек помещены данные, необходимые для работы программы, то проблема вскрытия защиты еще более осложняется. Для повышения эффективности метода можно часто менять местоположение стека в программе. Защитные механизмы, которые будут использовать стек, делают практически невозможным применение стандартных отладочных средств.

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

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


Если программа работает под отладчиком, то очевидно, что время выполнения контрольного участка будет значительно большим, чем время его "чистой" работы. Данный метод эффективен в сочетании с механизмом защиты от НСК, имеющим привязку к аппаратным особенностям машины.

Один из способов затруднения работы "взломщика" при анализе работы программы – это метод использования так называемых "пустышек". В качестве их выделяются участки программы достаточно большого объема, производящие некоторые значительные вычисления, но не имеющие никакого отношения к работе программы. В "пустышки" необходимо включать какие-либо фрагменты, которые могли бы заинтересовать "взломщика". Например, это могут быть вызовы таких прерываний, как 13Н, 21Н, 25Н, 26Н, их перехват и т. п.

Принципиально новый подход к защите программного обеспечения от исследований отладочными средствами и дизассемблерами является метод динамического изменения кода исполняемого модуля. Полное изменение исполняемого кода становится возможным благодаря адекватной замене одной или нескольких команд программы другой последовательностью команд без изменения выполняемых программой функций. Например, команда MOV может быть заменена парой команд PUSH и POP, команда CALL – парой PUSH и YMP и т. д. Всегда можно организовать работу программы так, чтобы при каждом ее выполнении происходила замена исполняемых команд на эквивалентные, которые выбирались бы из специальной таблицы эквивалентных команд, хранящейся в определенном месте программы. При этом необходимо постоянно изменять и саму таблицу эквивалентных команд, переставляя в ней местами эквивалентные команды. Можно также внести в таблицу случайный признак модификации таблицы. В результате после каждого выполнения программы ее код будет изменен до неузнаваемости (случайным образом), однако все свои функции программа будет выполнять точно так же, как и раньше. Единственное, что может при этом изменяться – это время выполнения программы.


Содержание раздела