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

Предварительное архивирование также не представляет особых
затруднений для хакера, но является более эффективным по сравнению с
шифрованием, так как решает сразу две задачи: уменьшает размер
защищаемого модуля и скрывает код от дизассемблера. Как это делается?
Возьмем файл рисунка. Он содержит поточечное описание всех строк
экрана (цифры - это точки определенного цвета, ноль - ее отсутствие).
Например, рисунок красной линии на экране, состоящей из 200 точек,
записывается в файл в виде 200 байт, а значение каждого байта равно 4
(код для красного цвета). Архиватор заменяет перечисление одинаковых
цифр (эти 200 четверок) элементарным шифром - двумя байтами (первый -
количество повторов, второй - значение цвета), и размер файла резко
уменьшается (в примере - с 200 до 2 байт). Для других типов записей
существуют свои методы сжатия. Большинство из них описано в
литературе, поэтому не будем останавливаться.
Метод самогенерируемых кодов наиболее сложен в реализации, но
очень эффективен. Суть его такова. В программу вложен массив данных,
который сам по себе может быть исполняемым кодом (реально получающим
управление) или смысловым текстом, но после некоторых арифметических
или логических операций преобразуемый в участок программы, выполняющий
иные, не менее важные функции.
Нужно быть виртуозом программирования, чтобы заметить
самомодифицирующуюся ловушку. Ведь при анализе листинга и с явными
алгоритмами разбираться сложно (автор комментарии не оставляет), так
что уж говорить о потайном смысле вроде бы расшифрованного участка.
Впрочем, и новичок-разработчик создать такие ловушки не сможет.
Но коль скоро он взялся за написание защитных механизмов, то ему
придется осваивать изощренный стиль программирования, который
запутывает дизассемблер нестандартной интерпретацией некоторых команд
и нарушает общепринятые соглашения. Например, использование необычной
структуры программы (совмещение стекового и кодового сегментов ).
Интеллектуальные дизассемблеры, как правило, это плохо воспринимают. А
перекрестные вызовы процедур, многократные переходы из модуля в модуль
и увеличение количества точек входа в них - не позволяют выявить
блочную структуру программы.
Замена команд переходов, вызовов подпрограмм и прерываний
направляет дизассемблер по ложному следу. Здесь вместо стандартного
оператора вставляется группа других, в конечном счете выполняющих то
же самое. Для неискушенных программистов на рисунке 4.1 (а-д)
приведены такие варианты. Впрочем, для аналогичных эффектов достаточно
в команде перехода изменить значение операнда (примеры е-ж). И еще
проще модифицировать косвенные переходы (з-и).
Кстати, и саму команду можно модифицировать. Например, на рис. 4.1
(к) дизассемблер по адресу m: покажет PUSH AX (запись регистра AX в
стек), поскольку этот байт имеет код 50h (01010000b), но перед ее
выполнением один бит (4-й) меняется, в результате получается INC AX с
кодом 40h (01000000b, увеличение содержимого регистра AX на 1) - то
есть совсем другая команда, не отраженная в листинге.
Кропотливая работа преобразует участок до неузнаваемости. А
"умный" дизассемблер (например, Sourcer), отслеживая "явную" передачу
управления (в другое место), не найдет спрятанный блок и,