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

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

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

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


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

Context.ContextFlags := CONTEXT_FULL;

GetThreadContext(Pr.hThread, Context);

Dec(Context.Eip);

Сontext.EFlags := Context.EFlags or $100;

SetThreadContext(Pr.hThread, Context);

WriteProcessMemory(Pr.hProcess, EntryPoint, @OldByte, 1, Bytes);

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

[для дизассемблирования кода используется дизассемблер CADt]

begin

if (Cmds > 0) then

begin

Context.ContextFlags := CONTEXT_FULL;

GetThreadContext(Pr.hThread, Context);

Context.EFlags := Context.EFlags or $100;

SetThreadContext(Pr.hThread, Context);

ReadProcessMemory(Pr.hProcess, pointer(Context.Eip), @Cmd, 32, Bytes);

DisCommand := DisasmCommand(@Cmd, Context.Eip);

writeln(DisCommand);

DisCommand := DisCommand + #13#10;

WriteFile(hFile, PChar(DisCommand)^, Length(DisCommand), Bytes, nil);

end;

Dec(Cmds);

end;

В итоге мы получим вполне работающий трейсер, который использует Debug API, умеет трассировать программу и ставить брекпоинты. Тестовый пример запускается из командной строки и принимает два параметра, первый из которых - путь к отлаживаемой программе, а второй - глубина трассировки (количество команд). Пример выводит дизассемблерный листинг в консоль и записывает его в файл c:\trace.log.

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

[эмуляция]

Эмуляция процессора - очень мощный метод отладки, не накладывающий вообще никаких ограничений на возможности отладчика, однако обладающий одним неприятным недостатком - для использования на реальных программах ему необходимо эмулировать не только процессор, но и все оборудование компьютера. Подобным эмулятором является виртуальная машина BOCHS. Это в настоящее время единственный отладчик-эмулятор пригодный для практических целей. Он обычно используется для отладки загрузчиков ОС, кода BIOS и других специфических случаев, недоступных для отладки обычными средствами. Для защищенных программ он, к сожалению, непригоден, так как не всегда корректно эмулирует специально составленные нестандартные команды, да и, надо заметить, существующий набор команд 386 эмулирует не полностью. К тому же, подобные эмуляторы легко обнаружить по специфическому набору эмулируемого оборудования. По моему мнению, создать необнаружаемый отладчик-эмулятор практически невозможно, так как в эмуляции процессора и оборудования есть множество мелких недокументированных тонкостей, которые не важны для работы обычных программ, а любое несоответствие поведения эмулируемого оборудования реальному может быть использовано защитой для обнаружения отладчика. Но для отладки операционных систем подобные эмулирующие дебаггеры незаменимы.

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