Старые антиотладочные приемы на новый лад

Программа, которая трассирует себя сама


Один из древнейших приемов основан на "поглощении" трассировочного прерывания отладчиком. Рассмотрим его поподробнее. Как известно, x86-процессоры имеют специальный trap-флаг (или, сокращенно TF). Когда он взведен, после выполнения каждой инструкции генерируется специальное отладочное прерывание, обрабатываемое отладчиком (если, конечно, он установлен и действительно отлаживает программу). В противном случае управление получает обработчик по умолчанию. В ms-dos он представляет собой "холостую" заглушку, состоящую из одного лишь IRET, и выполнение программы не прерывается, а вот Windows возбуждает исключение, приводящее к появлению хорошо всем известного диалогового окна "программа совершила недопустимую операцию и будет закрыта".

Формально, флаг трассировки является частью регистра флагов и потому может быть сохранен в стеке командной pushf/pushfd, однако, распознать факт трассировки таким способом скорее всего не удастся, поскольку многие отладчики маскируют свое присутствие. При пошаговом выполнении программы они осуществляют дополнительную проверку— а не является ли только что выполненная команда инструкций pushf и если это так — лезут в стек и корректируют сохраненное значение регистра флагов, сбрасывая TF в ноль. Правда, тут можно схитрить. Например, добавить несколько лишних префиксов перед командой pushf — есть шанс, что отладчик не сможет их распознать. Еще можно использовать самомодифицирующийся код, расположив команду pushf в стеке с таким расчетом, чтобы сохраненное значение регистра флагов затирало ее напрочь, правда тут есть одна маленькая проблема. Производители аппаратно-программного обеспечения наконец-то признали тот факт, что научить программистов программированию им так и не удалось, а теперь уже и не удастся. Операционные системы и приложения буквально нашпигованы ошибками переполнения буфера, через которых распространяются черви, троянские программы и другая зараза. Чтобы прикрыть лазейку пришлось пойти на довольно жесткую, спорную и радикальную меру — неисполняемый стек. И хотя распространения червей он все равно не остановит, ведь существуют и другие типы переполняющихся буферов (множество статей на эту тему лежит на ftp://nezumi.org.ru), для нас (пользователей и программистов) в практическом плане это означает, что огромное количество программ перестанет работать, поскольку они защищены упаковщиками и протекторами, использующими самомодифицирующийся код, исполняющийся в стеке. Поэтому, Microsoft предусмотрела возможность отключения защиты. При первой попытке исполнения кода на стеке, Windows XP выбросит грозное диалоговое окно (см. рис. 2) и при утвердительном ответе пользователя выполнение защищенной программы будет продолжено, так все не так уж и плохо.



Содержание раздела