ГЛАВА V
МЕТОДЫ ЗАЩИТЫ ОТ ИССЛЕДОВАНИЯ ПРОГРАММ
Технологии противодействия заметно обгоняют эволюцию систем защиты
Крис Касперски.
Техника и философия
хакерских атак
·
Средства
исследования программ
·
Защита программ от
дисассемблирования
·
Защита программ от
работы под контролем отладчика
Противодействие
попыткам запуска и/или исполнения защищенной программы обязательно необходимо
сопровождать механизмами, предотвращающими возможность исследования программы,
в том числе и зарегистрированных (законных) копий.
Повторим, что для
взлома защиты нарушителю прежде всего необходимо найти защитный механизм и
понять логику его работы, то есть исследовать программу.
Средства исследования программ
Основными
инструментами для исследования программ являются дисассемблеры и отладчики.
Дисассемблирование - это
получение из исполняемого кода программы код на языке ассемблера.
Дисассемблер - программа, осуществляющая дисассемблирование.
Интерактивный дисассемблер - программа, тесно взаимодействующая с
пользователем в процессе дисассемблирования.
Отладчик - программа, предназначенная для анализа поведения другой
программы, обеспечивающая остановку в указанных точках и позволяющая
просматривать (редактировать) содержимое ячеек памяти, регистров процессора и
команды программы.
Эмулирующий отладчик - отладчик, который самостоятельно интерпретирует
и выполняет команды программы (без использования реального процессора).
Существует также
множество программ-утилит, предназначенных для вспомогательных операций по
изучению логики работы механизма защиты. Широко используются
· шестнадцатеричные
просмотрщики - редакторы;
· редакторы таблиц экспорта/импорта;
· так называемые файловые мониторы,
позволяющие отслеживать операции работы с файлами;
· а также мониторы реестра,
создающие протокол обращений к реестру
· и многие другие.
Например, с помощью
файлового монитора (FileMonitor) взломщик может отследить работу защищенной
программы с файлами и обнаружить ключ (пароль), хранящийся в некотором файле.
Произведя анализ протокола обращений к реестру с помощью монитора реестра (RegMon),
взломщик может обнаружить ключ (пароль), хранящийся в системной базе данных Registry.
Инструментарий
современного хакера на столько развит, что все попытки авторов защит противодействовать
исследованию программ с точки зрения высококвалифицированных хакеров считаются
безрезультатными.
С помощью современных версий интерактивных дисассемблеров и
эмулирующих отладчиков может быть обнаружена практически любая защита.
! |
Тем не менее отказываться от
использования приемов и методов защиты от дисассемблирования кода программы и
ее работы под отладчиком нельзя.
Напомним, что абсолютной защиты вообще не бывает.
Эффективной защитой считается такая, на взлом которой необходимы материальные и
трудовые затраты, во много раз превышающие затраты на покупку программного
обеспечения. Поэтому затруднение взлома защиты любыми путями и методами
является оправданным. Если преодолеть защиту не сможет молодой неопытный
взломщик, и заказчику придется обращаться к высококвалифицированному специалисту,
- это уже плюс.
Считая защиту от
дисассемблирования и отладки, рассчитанной на взломщика средней квалификации,
назовем такую защиту затруднением
анализа программ. Рассмотрим ее основные моменты.
Защита программ от дисассемблирования
Универсальным методом противодействия дисассемблированию
программы является шифрование.
Очевидно, что дисассемблирование зашифрованного кода бесполезно.
Применяя
шифрование кода программы для противодействия дисассемблированию, следует учитывать
распространенные ошибки реализации данного метода. Напомним их. Во-первых,
неэффективной является такая реализация, когда исполняемый код в полном объеме
и однократно шифруется / дешифруется (так как легко найти момент после
дешифрования). Во-вторых, необходимо осуществить выбор эффективного ключа и,
если необходимо, надежно хранить ключ. И в-третьих, следует учесть, что для
защиты программ от дисассемблирования, не рекомендуется использование
симметричных криптографических алгоритмов.
Рекомендуется
использовать шифрование с открытым ключом (алгоритм RSA, шифр Эль-Гамаля и др.). В
этом случае возможная удачная попытка расшифровать код и понять логику работы
защитного механизма не позволит внести изменения в защищенный код, так как для
полноценной последующей работы программы эти изменения необходимо внедрить в
код в зашифрованном виде. А нарушителю доступен лишь ключ для расшифровки.
Возможная атака в данном случае - нахождение «секретного» ключа с помощью
трудоемких математических вычислений в зависимости от используемого алгоритма
шифрования.
Усиливает защиту динамическое шифрование и многопроходная расшифровка кода.
На практике
неплохо зарекомендовали себя и методы, использующие вместе с шифрованием архивирование программного кода. К
достоинствам данного метода относят и уменьшение размера исполняемого файла.
Однако следует учитывать, что алгоритмы работы широко используемых архиваторов
известны многим взломщикам.
Широко распространены
на практике методы, основанные на динамическом
изменении кода программы в процессе выполнения. Суть этих методов
сводится к получению истинных исполнимых команд на этапе выполнения программы
путем некоторого преобразования первоначальных кодов. Часто этот способ защиты
называют самогенерируемыми, или
самомодифицирующимися кодами. Авторы предлагают различные преобразования,
например,
· перемещения
участков кода;
· всевозможные функции от
истинного кода (контрольной суммы истинного кода);
· или для генерации кода
одного участка используют коды предыдущего (или какого-нибудь другого) участка
программы (так называемая обратная связь).
Интересный прием защиты от дисассемблирования - использование нестандартной структуры
программы. В этом случае дисассемблер «не поймет» нестандартную
сегментацию программы.
Защита программ от работы под контролем отладчика
Для того, чтобы лучше понять методы борьбы с отладчиками и
пути увеличения эффективности этих методов, напомним суть процесса работы
программы под отладчиком.
Существует два отладочных механизма:
1)
контрольные
точки останова и
2)
трассировка
программы.
Идея первого механизма заключается во внесении в программный
код специального однобайтового кода (0xСС) - так называемой
контрольной точки останова. Заметим, что можно внести в программный код любое
количество таких точек. Во время выполнения программы при достижении контрольной
точки останова возникает исключительная ситуация - прерывание int 3. В
этот момент процессор останавливает работу программы для дальнейших распоряжений
пользователя. Для того, чтобы позже продолжить работу программы с точки
останова, в стеке запоминаются значения регистра флагов, регистра CS
(указатель текущего кодового сегмента) и регистра IP (указатель на следующую
выполнимую команду). При этом сбрасывается флаг трассировки.
Итак, для анализа программы с помощью отладчика в
исполняемый код программы необходимо внести контрольные точки останова,
следовательно, изменить код!
Этим фактом успешно пользовались авторы защит: достаточно
было обнаружить модификацию кода и либо удалить точку останова, либо прекратить
дальнейшее выполнение программы.
Для обнаружения модифицированного кода традиционно применялись следующие методы:
· подсчет контрольных сумм
критических участков;
· использование контрольной
суммы всего кода для расшифровки некоторого фрагмента;
· многопроходная расшифровка
кода с ключом, вычисляемым на основе контрольной суммы всего кода либо критического
участка;
· использование корректирующих
кодов, позволяющих определить местоположение контрольного байта;
· контроль времени выполнения
критического участка по сравнению с эталонным временем;
· контроль относительного
времени выполнения участка программы (относительно другого участка)
· и другие.
Интересные методы противодействия отладчикам реального (!)
режима основаны на перехвате
необходимого отладчику прерывания int 3. Предлагается заменить
команды обработчика прерывания int 3 «мусором» либо
использовать обработчик прерывания в целях защиты, например, для расшифровки
кода. Тогда в первом случае отладчик будет просто нейтрализован, а во втором -
возникнет конфликт между механизмом защиты и отладчиком.
Существует целая группа
приемов, основанных на использовании отладчиком стека.
Одним из таких
приемов является следующий. При выполнении критического участка необходимо
присвоить указателю стека нулевое значение. Таким образом, стек считается
полным и не может быть использован для сохранения необходимых регистров.
Операционная система в таком случае завершает работу приложения.
Другой прием -
хранить в стеке (полностью используя стек) данные, необходимые для работы программы.
Отладчик, при использовании стека для записи значений необходимых регистров,
удалит (затрет) критические данные, и программа станет неработоспособной.
Рассмотрим второй отладочный механизм - трассировку кода
программы.
Трассировка - это пошаговое выполнение программы.
Установка специального флага
трассировки (TF) приводит к генерированию после каждой команды исключительной
ситуации - прерывания int 1, называемого
трассировочным прерыванием.
При этом, аналогично обработке исключительной ситации int 3, в
стеке сохраняются необходимые для дальнейшей работы значения регистра флагов и
регистра IP (указатель на следующую выполнимую команду).
Поэтому наряду с простыми проверками - установлен ли флаг
трассировки - для противодействия
трассировке могут быть использованы и перечисленные выше приемы.
Понятно, что трассировщик будет стараться следить за флагом
TF и корректировать его. Поэтому необходимо для получения оригинального
флага трассировки использовать специальные приемы.
Проверять
установку флага трассировки можно, исходя из аппаратных особенностей процессора,
например, используя потерю
трассировочного прерывания. Этот метод базируется на том, что после команд,
изменяющих сегментный регистр SS (до процессора Intel 80386
- любой сегментный регистр), не происходит трассировочное прерывание даже при
установленном флаге трассировки. Чтобы получить истинное значение флага
трассировки, достаточно перед проверкой регистра флагов переслать сегментный
регистр SS.
Для усиления
защиты от пошагового выполнения программы авторы успешно используют значение
флага трассировки (в совокупности с другими параметрами) для расшифровки критических
участков или, что еще сложнее для взлома, в арифметических выражениях.
Современные
операционные системы и отладчики позволяют установить аппаратные точки останова. Аппаратная отладка основана на
использовании специальных отладочных регистров (всего 8 регистров) и
возможности простановки четырех контрольных точек останова.
! |
Аппаратные точки останова никак не
модифицируют код и, следовательно, не могут быть обнаружены традиционными средствами.
Однако существуют приемы,
позволяющие, в принципе, обнаружить работу программы под аппаратной отладкой.
Для этого можно использовать все отладочные регистры для нужд программы или
поместить в отладочные регистры «мусор». Усиливается защита использованием всех
четырех контрольных точек останова. Но реализация таких приемов требует высокой
квалификации программиста и вряд ли оправдана, так как для взлома защиты
нарушитель может воспользоваться другими технологиями и инструментами.
Для взлома
механизмов защиты сегодня применяются мощные эмулирующие отладчики. Они самостоятельно
(без помощи процессора) интерпретируют и выполняют команды исследуемой
программы. Существуют так называемые отладчики с неполной эмуляцией. Эти отладчики
интерпретируют только некоторые команды, а остальные выполняют на реальном
процессоре.
Очевидно, что
против таких отладчиков бессильны любые приемы противодействия. Поэтому «сегодня
уже мало кто решается противодействовать отладчику и включать в свое приложение
антиотладочный код. Мода на это давно прошла» [20, с. 140].
Единственным
средством борьбы с отладкой сами хакеры называют эмуляторы процессора.
___________________________________________________________
Подробнее
1.
Аппаратная
отладка - К. Касперски «Техника и философия хакерских атак» [20], стр. 154 -
159.
2.
Технологии
эмуляции процессора - К. Касперски «Техника и философия хакерских атак» [20], стр.
163 - 167.