Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #83, НОЯБРЬ 2005 г.

Строим отладчик

Ms-Rem (Ms-Rem@yandex.ru)

Хакер, номер #083, стр. 083-112-2


[современные способы отладки]

С появлением x86-процессоров все стало гораздо проще. Камни стали поддерживать отладку на аппаратном уровне, а начиная с 386 еще и отладку в защищенном режиме с аппаратными точками останова.

Что же у нас здесь есть для установки брекпоинтов? Самая часто используемая возможность - третье прерывание. Просто один байт отлаживаемой программы заменяется на однобайтовую инструкцию int 3, которая при срабатывании передает управление отладчику. Этот способ несколько напоминает старый трюк с jmp, но в отличие от него позволяет производить отладку в защищенном режиме и размещать отладчик там, куда не доберется отлаживаемая программа, как бы она этого не захотела (в нулевом кольце защиты). Достоинство этого метода в том, что он позволяет ставить неограниченное число брекпоинтов, а недостаток - в непосредственной модификации кода программы. Многие защиты проверяют целостность своего кода, а значит, такой метод на них срабатывать не будет.

Однако современные способы на этом не заканчиваются. Процессоры серии 386+ имеют чрезвычайно удобный и полезный отладочный механизм - аппаратные DR-регистры. Их всего шесть: dr0, dr1, dr2, dr3, dr6 и dr7, причем первые четыре используются для задания точек останова, а последний управляет режимом работы всей этой системы. И что же нам это дает? А дает нам это немало:

1) Останов по чтению/записи/исполнению областей памяти: от 1 до 4-х байт.

2) Останов по инструкциям ввода-вывода (in и out) для определенных портов.

3) Возможность отслеживать попытку изменения содержимого регистров dr0-dr3 (контролируется GD битом в cr4).

Взгляни на структуру отладочных регистров, изображенную на картинке. Как видишь, dr0-dr3 содержат линейный адрес точки останова. Этот адрес (при использовании страничной адресации) может не совпадать с физическим. Единственное, что нам тут надо учесть - это то, что линейный адрес брекпоинтов на исполнение кода берется относительно регистра cs, а для доступа к данным - относительно ds. Поставить «бряк» на области памяти, адресуемые через другие сегменты, можно только тогда, когда они перекрываются с cs, либо ds, и при этом нам надо вычислить виртуальный адрес нужных данных в другом сегменте. Где может понадобиться такой трюк? Скорее всего, для отслеживания установки программой SEH-обработчиков (доступ в сегменте адресуемом через fs).

Назад на стр. 083-112-1  Содержание  Вперед на стр. 083-112-3