Лекции. Введение. Защита программного обеспечения от несанкционированного использования с помощью программноаппаратных средств
Скачать 4.72 Mb.
|
Рис. 6.1. Рабочее окно отладчика SoftICE Экран SoftICE – основной инструмент при отладке приложения. Он подразделяется на 7 окон и строку подсказки, позволяющие контролировать различные стороны процесса отладки. В таблице 6.1. перечислены все окна в порядке убывания их значимости.
По умолчанию SoftICE выводит на экран строку подсказки и окна команд, кода и локальных переменных. В зависимости от задач можно открывать и закрывать другие необходимые окна. Для открывания и закрывания окон, а также для переключения из окна в окно используются следующие команды.
Команды отладчику SoftICE можно вводить только тогда, когда курсор находится в окне команд либо кода. Синтаксис команд Команды SoftICE имеют следующие общие правила построения: 1. Все команды представляют собой нечувствительные в регистру строки длиной от 1 до 6 символов. 2. Адрес в SoftICE может быть представлен парой селектор:смещение или сегмент:смещение, либо одним смещением. 3. В используемых выражениях могут использоваться: Символы группировки – круглые скобки ‘(‘, ‘)’. Числа в шестнадцатиричном или десятичном формате. Адреса. Номера строк. Строковые литералы. Идентификаторы. Операторы. Встроенные функции. Регистры. В окне регистров детально представлено, также, значение регистра флагов.
Строчный неподсвеченный символ означает, что флаг не установлен и имеет значение “0”. Выделенный заглавный символ показывает, что флаг имеет значение “1”. Например, o d I s Z a p c. Переключение значения флага, когда курсор находится в одном из них осуществляется клавишей INSERT. Использование прерываний в SoftICE Одновременно в SoftICE можно установить до 256 прерываний. SoftICE поддерживает следующие типы контрольных точек. 1. Прерывания на инструкции, располагающиеся по конкретным адресам в памяти. Данные типы прерываний устанавливаются командой BPX (либо щелчком мыши на команде). SoftICE заменяет существующие инструкции командами INT 3. 2. Прерывания на обращение к памяти. SoftICE использует отладочные регистры для прерывания работы, когда читается (или исполняется) определенный байт, слово или двойное слово в памяти, или по этому адресу производится запись. Данный тип прерываний основан на использовании отладочных регистров DRx и чрезвычайно полезен для выяснения вопроса, когда и где происходит изменение программных переменных, а также для установки контрольных точек в исполняемом коде, размещенном в памяти «только для чтения». Для установки такого типа прерываний используется команда BPM. 3. Контрольные точки на прерываниях. SoftICE перехватывает прерывания, модифицируя таблицу дескрипторов прерываний. Для таких контрольных точек используется команда BPINT. 4. Прерывания ввода/вывода. SoftICE использует расширения отладочных регистров процессоров Pentium и Pentium Pro, чтобы отслеживать инструкции IN и OUT по заданному номеру порта. Этот тип прерываний устанавливается командой BPIO. 5. Прерывания на сообщения Windows. SoftICE отслеживает поступление в окно определенного сообщения (или сообщений из заданного диапазона). Для установки такой точки прерывания используется команда BMSG. Любое из данных прерываний может быть задано со следующими дополнительными параметрами. Условное выражение [IF выражение]. Для возникновения прерывания выражение должно иметь в результате ненулевое значение TRUE. Действие при прерывании [DO “команда1; команда2; …”]. При возникновении прерывания будет автоматически выполнена указанная последовательность команд. Форматы команд Команда BPX BPX [адрес] [IF выражение] [DO “команда1; команда2; …”] Здесь, адрес указывает адрес установки прерывания. В качестве него может быть указан непосредственный адрес, либо имя вызываемой функции. Например, BPX MessageBoxA, Команда BPM BPM [B|W|D] адрес [R|W|RW|X] [отладочный регистр] [IF выражение] [DO “команда1; команда2; …”] BPM, BPMB – прерывание по обращение к заданному байту, BPMW – к слову, BPMD – к двойному слову. R, W, RW – прерывание по чтению, записи, или по чтению и записи. X – прерывание по исполнению указанного адреса (в отличие от команды BPX не производится модификация кода). Отладочный регистр – указывает, какой регистр должен задействоваться при реализации команды (как правило, определяется автоматически). Например, команда BPMD MyGlobalVariable W IF MyGlobalVariable==5 устанавливает прерывание по записи значения “5” в переменную размером двойное слово с именем MyGlobalVariable. Команда BPINT BPINT номер-прерывания [IF выражение] [DO “команда1; команда2; …”] Например, BPINT 2E IF EAX==1E. Команда BPIO BPIO номер-порта [R|W|RW] [IF выражение] [DO “команда1; команда2; …”] R,W,RW – прерывание по чтению из порта (IN) записи в порт (OUT) или по любой из них. Команда BMSG BMSG дескриптор-окна [L] [1-сообщение-диапазона [последнее-сообщение-диапазона]] [IF выражение] [DO “команда1; команда2; …”] L означает, чтобы сообщение было просто отображено в окне команд без активизации SoftICE. Диапазоны сообщений показывают, какие сообщения необходимо фиксировать. Например, BMSG 1001E WM_NCPAINT Для удаления контрольных точек используется команда BC, например, BC MessageBoxA. Для удаления всех контрольных точек можно воспользоваться командой BC *. Для того чтобы выключить контрольную точку без удаления необходимо воспользоваться командой BD, например BD MessageBoxA. Для включения отключенной контрольной точки существует команда BE. Отображение информации в окне данных Каждая строка окна данных отображает 16 байт области памяти в текущем формате в виде байт, слов, двойных слов или коротких или длинных вещественных значений. Для изменения адреса отображаемой области данных необходимо указать адрес в команде D. Можно казать как непосредственный адрес, так и сослаться на регистр. Например, :D es:1000 – выводит содержимое памяти, начиная с адреса ES:1000h :D ESI – выводит содержимое памяти, начиная с адреса, указанного в регистре ESI. Команда D может использоваться одновременно и для указания формата отображения. DB – формат побайтового отображения, DW – формат отображения в виде слов, DD – в виде двойных слов. Например, DW es:1000 Пошаговое исполнение кода Выполнять код в пошаговом режиме можно используя функциональную клавишу F8. По клавише F12 программа выполняется до тех пор, пока не встретится инструкция RET, ее можно эффективно использовать для выхода из подпрограмм. 6.2. Дизассемблирование программ с помощью интерактивного дизассемблера IdaPro Интерактивный дизассемблер IDA PRO, как и всякий дизассемблер предназначен для дизассемблирования кода программы в мнемонические инструкции на языке ассемблера. Рабочее окно IDA представлено на рис. 6.2. Большим удобством Ida Pro является то, что он «сворачивает» стандартные библиотечные функции, что во многом упрощает навигацию по файлу, позволяя втиснуть больше информации в тесное пространство экрана. «Развернуть» функцию можно, подведя к ней курсор и нажав “+”, или для сворачивания “-”. Кроме этого, IDA способна находить перекрестные ссылки, вызываемые из кода. На основе сигнатурного анализа, IDA умеет распознавать различные библиотечные операторы., например, “ostream::operator<<”. Дизассемблер IDA изначально проектировался как интерактивная среда, предназначенная для совместной работы с человеком. Преимуществом интерактивных дизассемблеров является то, что дизассемблеры, пытающиеся выполнить весь процесс автоматически, легко сбить каким-либо хитрым приемом. Человека же сбить не так легко. Рис. 6.2. Рабочий интерфейс дизассемблера Ida Pro В IDA реализован удобный С-подобный внутренний язык написания скриптов, позволяющий реализовать многие полезные действия (например, осуществить дешифровку зашифрованного участка кода). Ida Pro поддерживает инструкции для различного вида процессоров. Среди них – все версии процессоров INTEL, Motorola, Z80. Пример использования дизассемблера IDA Pro приведен ниже. Пусть у нас имеется следующий COM файл размером 292 байт. Код данного файла представлен на рис. 6.3. Рис. 6.3. Код исследуемого файла З агрузим данный файл в дизассемблер IDA, после чего получим следующую распечатку (рис 6.4). В идим, что дизассемблирование произведено не совсем до конца. IDA дизассемблировала только первые две команды. Дело в том, что для того, чтобы правильно распознать остальную часть кода, потребовался бы нетривиальный интеллектуальный алгоритм. За неимением последнего, IDA прекратился процесс, ожидая дальнейших команд от пользователя. Многие дизассемблеры пытаются дизассемблировать дальше, и, как правило, неверно. Попытаемся указать для IDA, что делать дальше. Если приглядеться к первым двум командам, то можно увидеть, что инструкция JMP в строке 103h вызывает переход по адресу 106h. Для того, чтобы объяснить это IDA, необходимо добавить новую перекрестную ссылку. Это можно сделать так. В меню “View” выбрать пункт “Cross references” и нажать INSERT. В Рис. 6.4. Текст файла после первоначального дизассемблирования поле “From” указать адрес, с которого происходит прыжок (в нашем случае seg000:0103). В поле “To” указать адрес, куда происходит прыжок (в нашем случае seg000:0106). Этого же самого эффекта можно добиться более быстрым путем – подвести указатель к адресу 106h и нажать клавишу “C”. Тем самым мы укажем, что с данного адреса идет участок кода. Однако недостаток этого варианта состоит в том, что непонятно, с какого места этот участок кода будет получать управление. Комментарии в дизассемблированном коде имеют очень большое значение, особенно в больших проектах. Например, в нашем случае, в строке 103h можно поставить комментарий, говорящий о том, что при выполнении инструкции JMP SI, значение регистра SI=106h. Для осуществления этого, подведем курсор к строке 103h, нажмем клавишу “:” и введем текст комментария “SI=106h”. С адреса 106h идет следующий участок кода.
Анализируя данный участок, видим, что данный участок осуществляет расшифровку некоторого фрагмента программы, находящегося с адреса 116h, при этом длина фрагмента хранится по адресу 114h и занимает 1 слово. Подведем курсор к адресу 114h и будем нажимать клавишу “D”, пока тип хранимых данных не изменится на «Слово» - «dw». Видим, что длина зашифрованного фрагмента равна 100h байт. Если проанализировать команду jmp si, находящуюся по адресу 112h и выполняемую после расшифровки, то можно увидеть, что управление передается на команду, находящуюся за зашифрованным фрагментом. Адрес этой команды равен 116h+100h=216h. Подведя курсор к адресу 216h и нажав клавишу “C”, мы получим следующий код, который выполняется после расшифровки.
Общий смысл данной последовательности команд – перемещение расшифрованного фрагмента памяти по адресу 100h и передача на него управление. Попытаемся узнать, что представляет собой зашифрованный участок кода. Для этого напишем скрипт на внутреннем языке IDA, который выполняет расшифровку. Следует отметить, что для доступа к произвольной ячейке памяти в IDA необходимо знать сегмент, в котором она расположена, и ее смещение. Seg000 в действительности не нулевой сегмент, а символическое имя. Для того, чтобы узнать базовый адрес, соответствующий данному сегменту, необходимо воспользоваться меню View/Segments. Вызвав его, видим, что ему соответствует адрес 1000h (рис. 6.5). |