"С.П.Расторгуев, А.Е.Долгин "Как защитить информацию" (пособие по борьбе с хакерами)" - читать интересную книгу автора

которой находится и сама подпрограмма. Тем не менее, SUBR нормально
отрабатывает и возвращает управление в точку вызова (но только не в
пошаговом режиме).
Трюк очень прост: так как длина конвейера не менее 4-х байт, то,
очевидно, команды, расположенные за REP STOSW, уже находятся в нем до
ее выполнения, что и обеспечивает нормальную работу подпрограммы даже
после затирания ее кода в ОЗУ. Выполнение же по одному шагу (то есть
по трассировочному прерыванию) нарушает очередность засылки кодов в МП
и приводит к непредсказуемому результату.
Пример на рис. 4.3 демонстрирует более изящное использование
конвейера. Он определяет - идет ли выполнение программы с трассировкой
или нет, и осуществляет ветвление (команда JMP с меткой m:) в
зависимости от этого. Здесь ветвление служит лишь для индикации работы
под отладчиком, но вы можете применить его по своему усмотрению.
На рис. 4.4 использование конвейера шины данных в иной
интерпретации и в более завуалированном виде. По существу, это
вариация на ту же тему и демонстрирует лишь разнообразие способов
работы с конвейером.
Аномальные явления, с которыми приходится сталкиваться при
программировании МП Intel 80x86, не менее интересная тема при
рассмотрении построения защитных механизмов. Информацию о них
программист чаще всего получает экспериментальным путем (что
становится его "ноу-хау"). Отступлений от стандарта обычно немного
(исключение составляют машины фирмы Compaq с длинным перечнем
особенностей). Об одном упоминалось в печати [2] - это потеря
трассировочного прерывания после команд, связанных с пересылкой
сегментных регистров типа MOV SEG.REG,R/M и POP SEG.REG. К сожалению,
в статье результаты исследований описаны неполно. Во-первых, для МП
8086/8088 (а точнее, японского аналога V20) существует еще один тип
команд, заставляющий пропускать трассировочное прерывание: MOV
R/M,SEG.REG. Во-вторых, для МП с более высоким номером также идет
потеря трассировки, но только для стекового сегментного регистра. Это
свойство с успехом можно применить для определения трассировки и типа
машин.
Известно, что отладчики при обработке 1-го прерывания анализируют
текущую команду на PUSHF (код 9Ch) и сбрасывают Т-бит. Поэтому
последовательность команд PUSHF, POP AX под отладчиком не позволит
получить установленный 8-й бит в регистре AX. На рис. 4.5 представлен
текст короткой программы, использующей эту особенность. Команда POP SS
заставляет отладчик пропустить следующую за ней команду PUSHF из-за
потери трассировки, и, благодаря этому, выявляется факт работы под
отладчиком.
Образцом знания особенностей работы МП и наиболее лаконичным
вариантом распознавания его типа мы считаем подпрограмму, текст
которой приведен в статье "Intel insight on specific instructions"
[3]. Вот два примера из нее:
1) Для определения типа МП, начиная с 80186 и выше, используется
тот факт, что для них в счетчиках сдвигов (линейных и циклических)
маскируются все биты, кроме 5-и младших, ограничивая тем самым
величину сдвига 31 битом.