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

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

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

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


Разбираемся с механизмами отладки и пишем собственный дебаггер

Думаю, ты не раз сталкивался с отладчиком: чужую прогу взломать, свою отладить - тут без него никуда. Дебаггер - незаменимая для хакера или кодера вещь. Но задумывался ли ты, как он работает? Как отлаживает? Если да, то тебе очень пригодится этот материал. В нем я постараюсь объяснить природу работы отладчиков, механизмы, с помощью которых на самом деле не очень сложная программа получает полную власть над любым процессом в системе. Причем не только объяснить, но и даже показать, как разработать несложный обезжучиватель самостоятельно!

[что такое отладчик]

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

В общем, что я хотел сказать, - разобраться с принципами работы отладчика будет не только интересно, но и невероятно полезно.

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

Для начала определим два важных действия, которые должен выполнять отладчик и чаще всего выполняет. Без них фактически невозможно вмешиваться в выполнение программы. Несомненно, такими действиями будут трассировка и установка брекпоинтов. Раз уж я взялся за экскурс в историю, вспомню замечательный компьютер ZX-Spectrum. Для тех, кто в танке, - это машина с примитивным процессором и 32 килобайтами (в базовой конфигурации) памяти. Ни о каком защищенном режиме и многозадачности в ней нет и речи, но даже на этом компьютере были отладчики, позволяющие трассировать программу и ставить брекпоинты.

Установка «бряков» заключалась в перезаписи 3 байт кода на инструкцию jmp указывающую на код дебаггера. Естественно, программа доходила до этой точки и передавала управление отладчику. После срабатывания брекпоинт снимался, а код программы возвращается обратно на свое место.

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

Содержание  Вперед на стр. 083-112-2