Строим отладчик 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 эмулирует не полностью. К тому же, подобные эмуляторы легко обнаружить по специфическому набору эмулируемого оборудования. По моему мнению, создать необнаружаемый отладчик-эмулятор практически невозможно, так как в эмуляции процессора и оборудования есть множество мелких недокументированных тонкостей, которые не важны для работы обычных программ, а любое несоответствие поведения эмулируемого оборудования реальному может быть использовано защитой для обнаружения отладчика. Но для отладки операционных систем подобные эмулирующие дебаггеры незаменимы. |