КАК ЗАЩИТИТЬ ИНФОРМАЦИЮ
(пособие по борьбе с хакерами)


Авторы: С.П.Расторгуев, А.Е.Долгин, М.Ю.Потанин
Редакторы: гл.редактор: А.Н.Перевозчиков; лит.редактор Ю.Ф.Филатов; редактор: В.А.Алексеев


СОДЕРЖАНИЕ

1. О программах-отмычках, взломанных файлах и несанкционированном копировании.

2. Идентификация пользователя: "СВОЙ" - "ЧУЖОЙ"?

3. Может ли компьютер стать графологом?

4. Как защититься от "размножения".

5. Защита от исследований.

6. Самомодификация программ - эффектно и полезно.

7. Исполняемый модуль - что можно сделать без исходных текстов?

8. Как очистить прогармму от вирусов и пристыкованных защит.

9. Проверка усвоенного.

10. Анонс вместо заключения.

Приложение 1. Словарь терминов.

0. ВВЕДЕНИЕ

В редакцию журнала "ТЕХНИКА-МОЛОДЕЖИ" нередко приходили письма с просьбой публиковать компьютерные программы. Однако массовый научно-художественный журнал не мог давать специфические материалы. Поэтому было решено издать приложение, укомплектованное дискетой: прочитал, и тут же запустил программу с дискеты. А тематика самая разная - от алгоритмов игр и борьбы с вирусами до справочных материалов по операционным системам, распространенным программам и периферийному оборудованию (например, как подключить принтер и сконструировать собственные шрифты). Ну а первые выпуски посвятили защите информации. Все алгоритмы, рассчитанные на непосредственное применение в работе, можно использовать и как пособие в практических занятиях. Это актуально, ведь учебников по способам пресечения информационного воровства до сих пор не существовало.

1. О ПРОГРАММАХ-ОТМЫЧКАХ, ВЗЛОМАННЫХ ФАЙЛАХ И НЕСАНКЦИОНИРОВАННОМ КОПИРОВАНИИ
(предисловие к серии приложения "ТМ").

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

Начнем с "защиты информации" - тема выбрана не случайно. Несмотря на недавно принятый Закон о защите программ и баз данных, нелегальное копирование, компьютерные диверсии (вирусы, "бомбы", "троянские кони"), а также количество финансовых преступлений с использованием вычислительной техники - не уменьшаются. Поэтому сохранность информации является проблемой номер один не только у нас, но и во всем мире. Ее усугубляют отсутствие элементарных знаний у большинства пользователей, владеющих лишь простейшими навыками копирования файлов, выработанная с годами привычка никогда не покупать программы и кажущаяся легкость бесплатного добывания дорогостоящего программного обеспечения.

Впрочем, для любителей головоломок и нестандартных решений тема защиты информации интересна сама по себе. Динамичность и сложность, в сочетании с краткостью применяемых алгоритмов, возможность предугадывать действия потенциальных хакеров ("взломщиков" программ) роднят ее с увлекательными играми, основанными на интеллектуальном поединке двух противников.

Как предупредить покушения на информацию? Можно ограничить доступ к ней посторонним, встроить в компьютер замок, отключающий клавиатуру, поставить сейф для дискет, вставить в один из разъемов ПК парольную "заглушку"... Из всего арсенала организационных, технических и программно-аппаратных средств выделим чисто программные. Они просты в тиражировании, технологичны в изготовлении и применении, не требуют каких-либо производстводственных мощностей, в то же время обеспечивают достаточный уровень защищенности. Впрочем, надежность в этом случае определяется знанием последних достижений общей теории программирования и умением разработчика использовать специальные приемы. Естественно, что новинки систем охраны влекут и совершенствование способов "взлома" - извечное противоборство "щита и меча".

Вот некоторые из наиболее популярных приемов защиты.

Преобразование ФОРМАТА ДИСКЕТЫ - наиболее простой путь предотвращения ее копирования средствами DOS. Даже незначительные изменения в структуре или расположении системных таблиц или каталога приводят к тому, что дискета становится непонятной "операционке". Можно "перепутать" адреса секторов, на которых расположены защищаемые файлы; пометить отдельные кластеры, занятые данными, как сбойные; переделав запись в BOOT-секторе, изъять из доступного системе пространства несколько треков (дорожек); в конце-концов - просто применить иную структуру, взяв за основу аналог из других операционных систем (например, RT-11 от ДВК). Разумеется, работать с такой дискетой сможет только специальная программа, полностью заменяющая стандартные функции ввода-вывода.

Одним из способов ШИФРАЦИИ данных является их архивация по специальным алгоритмам, что позволяет к тому же и сэкономить место на магнитном носителе. Правда, сами кодирующие блоки программ оказываются слабым местом. Их исследование под отладчиком или дизассемблером позволяет хакеру понять алгоритм шифрации и повторить его. Поэтому особенно актуальна ЗАЩИТА ОТ ИССЛЕДОВАНИЯ. Важную роль здесь играет стиль программирования. В отличие от общепринятых "наглядности" и "структурности", для охранных механизмов следует применять "изощренность", то есть такой стиль, который позволит получить сложный и запутанный исполняемый модуль. Еще лучше - если он будет саморазворачивающимся в процессе работы (программа "дописывает" свои части, отсутствующие на винчестере). Очень полезными могут оказаться приемы, о которых журнал "ТМ" рассказывал в 1986 - 1988 годах в разделе "Клуб электронных игр" (использование кода оператора в качестве операнда, набора констант по прямому назначению и как подпрограммы, передача управления в середину сложной двух-трехбайтовой команды, проход "своим ходом" через данные и другие хитрости, не только экономящие память, но и запутывающие алгоритм).

Но это пассивная защита, а в качестве активной - рекомендуем ПРЕСЕКАТЬ ПОПЫТКИ ИССЛЕДОВАНИЯ ИЛИ НЕСАНКЦИОНИРОВАННОГО "РАЗМНОЖЕНИЯ": периодически определять контрольную сумму всех кодов образа задачи в процессе работы (не "отрезан" ли какой-либо блок); сравнивать свободную память с тем объемом ОЗУ, к которому программа привыкла или приучена (не запущены ли паралельно резидентные "отмычки"); проверять вектора прерываний (нет ли их перехватов); используя компьютерный таймер, контролировать время прохождения отдельных частей (выявление "остановов" и "потактового режима" отладчика).

Изучение операционных систем, аппаратных особенностей ЭВМ позволяет выделить индивидуальные отличия и использовать их для НАСТРОЙКИ НА КОНКРЕТНУЮ ПЭВМ, СИСТЕМУ или ДИСКЕТУ, что делает программное обеспечение непереносимым без санкции разработчика. Правда, в архитектуре большинства компьютеров не существует аппаратной особенности, анализ которой помог бы выделить одну машину из серии таких же. Зато динамические характеристики различных частей (вращение винчестера и дисководов, скорость обращения к оперативной памяти и реакции клавиатуры) и их соотношения между собой индивидуальны, хотя и не очень устойчивы. Для повышения надежности рекомендуется использовать аппарат математической статистики. Вы не знакомы с ней? Мы снабдим вас необходимыми алгоритмами. Кстати, передаваемые в комплекте с лицензионными программами специальные электронные устройства, искусственно создающие аппаратную уникальность конкретной машины (так называемые "заглушки", которые подключаются к одному из разъемов ПЭВМ и по предусмотренному автором ПО запросу выдают парольную комбинацию байт), не всегда эффективны. Хакеры, используя принцип спаривания компьютеров, отслеживают на втором все передаваемые "заглушкой" сигналы, чтобы затем для несанкционированных копий повторить их программой-"псевдозаглушкой".

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

Надежную ИДЕНТИФИКАЦИЮ ПОЛЬЗОВАТЕЛЯ можно провести по почерку (скорость, привычки в использовании основных или вспомогательных частей клавиатуры, "любимые" комбинации клавиш при альтернативных вариантах, выполнение "сдвоенных" и "строенных" нажатий одной или двумя руками и т.д.), по росписи с использованием мышки, с помощью психологических тестов и паролей.

ПОИСК И УНИЧТОЖЕНИЕ ПОХИЩЕННОЙ ИНФОРМАЦИИ осуществляется специальными резидентными драйверами (находящимися в памяти даже после выгрузки пакета), которые постоянно контролируют операции ввода-вывода, "просматривают" другие директории винчестера и дискет, вставленных в дисководы. По сути это практическое применение вирусных механизмов для защиты. Отдельных читателей может шокировать такой способ охраны. Однако, если речь идет о важной информации и вирус настроен исключительно на уничтожение украденных данных, то криминала нет. Даже сторож яблоневого сада вооружается ружьем, так что же говорить о допустимых средствах борьбы с утечкой интеллектуальных ценностей?

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

Каждый алгоритм обладает своей степенью НАДЕЖНОСТИ. Как показывает опыт - 98 процентов "любознательных" программистов отступятся от защиты, если она гарантирует: невозможность копирования дискет с двух - трех попыток распространенными средствами типа COPY II-PC, COPYWRITE или UNLOCK; невозможность разобраться в алгоритме стартовых блоков программы с помощью известных отладчиков и дизассемблеров (удача же на первых шагах, наоборот, подхлестнет "спортивный" интерес); уникальность применяемых систем (если на один и тот же "замок" закрыты программы разных авторов, то с ним стоит и повозиться). А если к тому же пакет решает специальные задачи (не интересен широкому кругу пользователей) и обходится дешевле, чем оплата профессионального хакера, - то можно быть спокойным, "краж" не будет.

Но, предположим, перед неким хакером все же поставили такую цель. К сожалению, пока не существует объективных критериев оценки надежности того или иного алгоритма либо их комбинаций, зато из субъективных можно взять за основу - время, которое понадобится для "взлома". Шансы того, что защита целиком будет вскрыта, могут быть подсчитаны на основании следующих параметров: вероятность наличия у хакера спецсредств копирования и анализа защищенных программ; объем и степень популярности примененной системы охраны; насколько интересна сама программа другим пользователям; стоимость программы и системы защиты.

Обеспечение БЕЗОПАСНОСТИ В ЛОКАЛЬНЫХ СЕТЯХ, пожалуй, самая сложная проблема. Она не решается автоматически, даже если на каждой ПЭВМ все обстоит благополучно, но системе в целом должного внимания не уделялось. Да и сам подход к построению защиты иной. Сначала необходимо разобраться: во-первых, к каким блокам имеющейся информации доступ должен быть максимально открыт (общая часть), ограничен (дополнительные сведения) или полностью закрыт (управление сетью, списки абонентов и их паролей); во-вторых, какие способы проникновения в базы данных возможны для легальных корреспондентов, включая сетевые серверы, и для хакеров. Теоретически всегда допустима ситуация, когда два защитившиеся друг от друга абонента контактируют с третьим через общие устройства - тут-то и возникают любопытные варианты похищения или порчи данных. Поистине неоценим зарубежный опыт борьбы и с сетевыми вирусами, автономно живущими в узловых компьютерах и накапливающими передаваемую информацию. Но поскольку сети в нашей стране только начинают развиваться, теория и практика их безопасности разработаны пока недостаточно.

Решение некоторых из этих проблем - вы найдете в этом выпуске приложения "ТМ", а остальные - в последующих.

2. ИДЕНТИФИКАЦИЯ ПОЛЬЗОВАТЕЛЯ: "СВОЙ" - "ЧУЖОЙ"?

Почерк уникален, это знают все. Но немногие догадываются, что в общении с компьютером индивидуальность пользователя проявляется также: скорость, привычка использовать основную или дополнительную часть клавиатуры, характер "сдвоенных" и "строенных" нажатий клавиш, излюбленные приемы управления компьютером..., с помощью которых можно выделить конкретного человека среди всех работавших на данной машине. И ничего удивительного, - это сродни способности меломанов различать на слух пианистов, исполняющих одно произведение.

Как же выявить индивидуальные особенности клавиатурного почерка? Также, как и при графологической экспертизе: нужны эталонный и исследуемый образцы текста. Лучше, если их содержание будет одинаковым (так называемая, парольная или ключевая фраза). Разумеется, по двум-трем, даже по десяти нажатым клавишам отличить пользователя невозможно, нужна статистика.

При наборе ключевой фразы компьютер позволяет зафиксировать много различных параметров, но для идентификации наиболее удобно использовать время, затраченное на ввод отдельных букв. А повторив ввод фразы несколько раз, в результате будем иметь множество временных интервалов для каждого символа. На базе полученных значений всегда можно рассчитать среднее время ввода каждого символа, допустимое отклонение от среднего, и хранить эти результате в качесте эталонов для каждого пользователя.

Уникальные особенности клавиатурного почерка выявляются двумя методами: по набору ключевой фразы или по "свободному" тексту. Каждый обязательно имеет режимы настройки и идентификации. При настройке определяются и запоминаются эталонные характеристики ввода пользователем ключевых фраз, например, время, затраченное на отдельные буквы. А в режиме идентификации, после исключения грубых ошибок, эталонное и полученное множества сопоставляются (проверяется гипотеза о равенстве их центров распределения).

Обе методики различаются лишь выбором парольной фразы. В первом случае это всегда одно и то же, а во втором - самый разнообразный текст, что имеет свои преимущества, позволяя получать те же характеристики незаметно, не акцентируя внимание пользователя на парольной фразе. Впрочем, на выбор схемы проверки влияет тематика защищаемого ПО. Предположим, некий владелец фирмы, желая узнать текущий финансовый оборот, запустил программу бухгалтерского учета, а компьютер, вместо короткой справки с коммерческой и потому секретной информацией, предлагает набрать 2 - 3 странички "свободного текста", дабы убедиться, что перед ним действительно директор или главбух. То есть, здесь лучше применить метод "парольной фразы". С другой стороны, лицо, имеющее допуск к секретам, может работать с такой программой целый день, время от времени отлучаясь от компьютера, а чтобы в этот момент злоумышленники не воспользовались раскрытой системой, желательно периодически проводить "негласную проверку" (просьба перенабрать "пароль" через каждые полчаса будет слишком назойлива).

Правильной идентификации помогает также рисунок почерка. Под этим понимается ряд значений, представляющих собой разность между соседними временными интервалами - своего рода "производная" по почерку, показывающая относительные замедления или ускорения при работе с клавиатурой. Характеристика достаточно индивидуальна, что подтверждается рядом экспериментов.

НАСТРОЙКА

Для определения эталонных характеристик пользователя необходимо выбрать ключевую фразу. Желательно, чтобы буквы были равномерно распределены по клавиатуре, например: "Внимание - идентификация пользователя по клавиатурному почерку". Затем раз десять набрать ее на клавиатуре, определить время, затраченное на ввод каждой буквы, и исключить грубые ошибки (те значения, которые резко выделяются из каждой десятки имеющихся). Рассчитать и запомнить величины математического ожидания (M), дисперсии (S) и число наблюдений (n). Эти значения и называются эталонными (на блок-схеме - с индексом "э"). Блок-схема алгоритма режима настройки приведена на рис. 1.1.

ИДЕНТИФИКАЦИЯ ПО НАБОРУ КЛЮЧЕВОЙ ФРАЗЫ

Определение математических параметров пользователя (на блок-схеме: M, S и n с индексом "и") при его идентификации проводится аналогично, как и в режиме настройки. Единственное отличие - множества по каждому символу будут состоять из меньшего количества значений (если фразу набирают несколько раз) или даже из единичных величин (при однократном наборе). Затем сравниваются дисперсии двух множеств (эталонного и только что расчитанного) и величины математического ожидания - равны ли, то есть совпадают ли центры распределения этих двух совокупностей. Разумеется, полного равенства не будет, потому алгоритм заканчивается оценкой вероятности того, что пользователь - тот же (если она больше 50%, то все несоответствия можно отнести за счет случайных факторов). Алгоритмы обоих вариантов набора ключевой фразы приведены на блок-схемах - рис. 1.2 (неоднократный) и рис. 1.3 (однократный).

ИДЕНТИФИКАЦИЯ ПО "СВОБОДНОМУ" ТЕКСТУ

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

А сравнение математического ожидания и дисперсии с эталонными такое же, как и раньше (если базисные величины двух множеств выбраны правильно, то они хорошо коррелируют), но прежде необходимо исключить грубые ошибки, которых в данном случае будет больше.

Приведенные методы достаточно просты и опираются на известные разделы математической статистики [1-3], в различных вариациях они используются во многих системах. Разумеется, можно воспользоваться дисперсионным, регрессионным и другими видами анализа и усложнить решения, доведя их до совершенства. Но это усложнит и жизнь пользователя, ведь затруднительно каждый раз перед началом работы вводить солидные куски парольных текстов.

Вполне естественно, что с течением времени характеристики пользователя меняются. Поэтому рекомендуется после каждой успешной идентификации корректировать эталоны по формуле Mи=(n*Mэ+X)/(n+1), где Mи, Mэ - характеристики исправленного и эталонного множеств, X - величина, полученная в ходе идентификации, n - количество опытов, вошедших в эталонное множество.

ДРУГИЕ СПОСОБЫ ИДЕНТИФИКАЦИИ

Люди по разному воспринимают происходящие события. Предложи за короткое время прикинуть количество точек или гласных букв в длинных словах, размеры горизонтальных и вертикальных линий, - сколько испытуемых, столько и мнений.

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

Рис. 1.1.


Рис.1.2.


Рис.1.3.


Рис.1.4.


Таблица 1.1. Значения t-распределения Стьюдента P.
P/n 0.95 0.99 P/n 0.95 0.99
4 2.78 4.60 16 2.12 2.92
5 2.57 4.03 17 2.11 2.90
6 2.45 3.71 18 2.10 2.88
7 2.37 3.50 19 2.09 2.861
8 2.31 3.36 20 2.086 2.845
9 2.26 3.25 25 2.064 2.797
10 2.23 3.17 30 2.045 2.756
11 2.20 3.11 40 2.023 2.708
12 2.18 3.06 50 2.009 2.679
13 2.16 3.01 70 1.996 2.649
14 2.15 2.98 80 1.991 2.640
15 2.13 2.95 100 1.984 2.627


Таблица 1.2. Значения t-распределения Стьюдента P.
P/n 0.95 0.99 P/n 0.95 0.99
5 3.04 5.04 16 2.20 3.04
6 2.78 4.36 17 2.18 3.01
7 2.62 3.96 18 2.17 2.98
8 2.51 3.71 20 2.145 2.932
9 2.43 3.54 25 2.105 2.852
10 2.37 3.41 30 2.079 2.802
11 2.33 3.31 40 2.048 2.742
12 2.29 3.23 50 2.030 2.707
13 2.26 3.17 70 2.009 2.667
14 2.24 3.12 80 2.003 2.655
15 2.22 3.08 100 1.994 2.639


Таблица 1.3. F-распределение для уровня значимости a=0.05.
k1=k2= 1 2 3 4 5 6 7 8 9 10
Результат 161 19.0 9.28 6.39 5.05 4.28 3.79 3.44 3.18 2.97
k1=k2= 10 20 30 40 50 60 70 80 90 100
Результат 2.97 2.12 1.84 1.69 1.60 1.55 1.50 1.46 1.42 1.39


Таблица 1.4. Значение функции Ф(y).
y=0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
0 0.079 0.158 0.235 0.31 0.38 0.45 0.516 0.576 0.632
y=1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9
0.68 0.728 0.77 0.806 0.838 0.866 0.89 0.91 0.93 0.94
y=2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9
0.95 0.96 0.97 0.978 0.983 0.987 0.99 0.993 0.995 0.996
y=3 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9
0.997 0.998 0.9986 0.999 0.9993 0.9995 0.9997 0.9998 0.9999 0.9999
y >=4.0
0.9999


Таблица 1.5. Значения для вероятности p = 0.01 и числа степеней свободы 1.
Число степ. свободы Результат Число степ. свободы Результ.
1 6.6 8 20.1
2 9.2 9 21.7
3 11.3 10 23.2
4 13.3 11 24.7
5 15.1 12 26.2
6 16.8 13 27.7
7 18.5


3. МОЖЕТ ЛИ КОМПЬЮТЕР СТАТЬ ГРАФОЛОГОМ?

Рукопись в своеобразии начертания букв доносит до нас что-то личностное. Графологи, продравшись сквозь частокол завитушек, многое расскажут об их авторе. А что можно узнать с помощью компьютера о человеке, "долбящему" по клавишам? Попробуем поискать аналогии.

Д.М.Зуев-Инсаров, автор фундаментальных работ по графологии, не только убедительно демонстрирует методы определения пола, возраста, образования, рода занятий писавшего, но и достаточное внимание уделяет экспериментальным основаниям этого научного направления. Его классификация содержит такие формальные признаки почерка, как: сила нажима, динамичность и напряженность движения, вытянутость, наклон и степень связанности букв, направление строки, расположение и содержательность текста, способ держания орудия письма, равномерность и соразмерность букв и слов, ритм и выразительность письма.

Что же из этого может позаимствовать "клавиатуровед"? Аналогии есть, это несомненно. Например, временные интервалы между вводом символов с клавиатуры по информативности ничем не уступают связанности букв в словах на бумаге. Действительно, если не новичок при хорошем темпе набора вдруг начал ошибаться, то скорее всего он охвачен внутренними переживаниями, не относящимися к выполняемой работе. А ровный темп, взятый в начале и сохраненный до конца, не хуже графологического признака "равномерность письма" свидетельствует о пунктуальности и аккуратности тестируемого.

Конечно, многие особенности рукописного почерка при работе на компьютере сопоставлять бесполезно, ведь клавиатура и драйверы стандартизируют написание букв. Зато здесь возможен анализ новых признаков: зависимость скорости ввода слов от их смысла, относительное время нажатия клавиш различных полей клавиатуры и другие. Причем они в некоторых случаях даже более информативны - например, реакция тестируемого на различные термины укажет сферу его интересов. Действительно, химик быстрее наберет "водород", "соединение", которыми он постоянно оперирует, чем "программа", "экскаватор". А модельеру будут привычнее - "манекен", "выкройка". (Кстати, это свойство "мышечной" памяти, не контролируемой сознанием, можно использовать для программы "Детектор лжи".) В данном случае появляется возможность отдельно анализировать левое и правое полушария мозга (отвечающие за образное и абстрактное мышление), поскольку они связаны с правой и левой руками человека, а письмо представляет только "одностороннюю" информацию.

Формулы для получения формальных признаков клавиатурного почерка приведены на рис. 2.1, а их соответствие графологической классификации - в таблице 2.1. Смысл, вложенный в некоторые термины, отличается от принятого Зуевым-Инсаровым, потому что похожие особенности в том и другом случаях выявляются разнымии методами, однако это не противоречит его работе [1].

Графологические исследования способствуют также диагностированию больного, так как почерк меняется при заболевании, возвращаясь к нормальному виду по мере выздоровления. Кто знает, не подойдет ли подобный анализ и при постановке предварительного диагноза работающего на компьютере.

Можно пойти и дальше - построить Личностный вектор и на его основе описать внешность, характер и судьбу человека [2]. Заключение хотя и кажется слишком категоричным, тем не менее основано на известных теориях и гипотезах из психологии. Впрочем, взаимосвязь внешнего и внутреннего облика очевидна: закомплексованность из-за физического изъяна отражается на поведении, которое, в свою очередь, влияет на способ общения с компьютером. Поэтому решение обратной задачи - определение по клавиатурному почерку характера и, через него, внешности - хотя и трудно, но допустимо, пусть пока теретически. Например, на нештатную ситуацию (якобы "сбой" компьютера, а на самом деле - предусмотренный автором программы психологический тест) вспыльчивый холерик и "вечно комплексующий" меланхолик отреагируют по разному. А кто меньше отвлекается при длительной работе? Флегматик, сангвиник или холерик? Вероятно, наибольшее возражение вызывает утверждение о возможности прогнозирования судьбы. Хотя и в его защиту можно привести немало аргументов. В данном случае даже нет необходимости опираться на астрологов, которые считают, что жизнь человека зависит от даты рождения. Возможно и другое объяснение. Выбор Судьбой для человека поступка/события из альтернативных вариантов - продиктованы его деятельностью в далеком и недалеком прошлом. То есть, свобода выбора - всего лишь иллюзия разума. Таким образом, выяснив главные вехи в биографии и определив основные черты характера, можно с достаточной степенью вероятности смоделировать линию поведения человека в той или иной ситуации. В конце концов даже по капле воды можно судить об океане, а по поступку о жизни. Поэтому возможность предсказания судьбы становится, пусть спорной, как почти все в этом мире, но понятной. И в принципе реализуемой - что стоит для хорошего компьютера учесть несколько тысяч величин? Лишь бы были тщательно проработаны математические формулы и введены числовые значения всех факторов, влияющих на человека.


           1) Темп набора тестового материала в целом:
                               Tm = T/n
              где T - время набора, n - число символов.

           2) Темп набора каждого слова:
                           Ts[i] = T[i]/k[i]
                  где T[i] - время набора i-того слова,
                      k[i] - число символов в нем.

           3) Средняя пауза между словами:
                         i=L
               Tp = (T -    (T[i]) ) / L
                         i=1
                  где L - число слов в тексте.

           4) Степень связности набора (вычисляется после исключения
         грубых ошибок):
                        -----------------¬
                  S =   (t[j] - M) /(n-1)
             где  t[j] - время между набором j и j+1 символа в
                         слове (пробелы исключаются),
                      i=L
                  M =    (T[i])/n.
                      i=1

           5) Общий рисунок почерка:
               dX[i] = t[i] - t[i+1] для всех i.


Рис. 2.1. ОПРЕДЕЛЕНИЕ ОСОБЕННОСТЕЙ КЛАВИАТУРНОГО ПОЧЕРКА.

Таблица 2.1. СООТВЕТСТВИЕ КЛАВИАТУРНЫХ И РУКОПИСНЫХ ХАРАКТЕРИСТИК ПОЧЕРКА
На клавиатуре В рукописи Особенность характера
Длительный поиск клавиши. Отсутствие связи между буквами слова. Душевный разлад (если за ПЭВМ не новичок).
Одинаковые паузы между словами. Равномерные интервалы между словами. Уверенность в себе, отсутствие отрицательных переживаний.
Длительность пауз между словами изменяется в широких пределах. Неравномерность интервалов между словами. Неустойчивость характера, несогласованность чувств, активность проявляется только в результате отдельных вспышек волевой энергии.
Ровный темп набора каждого слова при вводе всего тестового материала. Равномерность написания как первых так и последних строк рукописного текста. Способность к регулярной систематической работе. Привычки к порядку, пунктуальности и аккуратности.
Пауза между словами много кратно превышает паузы между отдельными буквами. Плотное написание слов с чрезмерными интервалами между ними. Истеричность.
Высокий темп в начале теста, заметно снижаюшийся к его завершению. Более правильное и четкое написание начала текста по сравнению с заключением. Быстрая утомляемость.
Темп ввода отдельных слов Тестируемый ранее неоднократно набирал их на клавиатуре.
Отдельные слова вводятся гораздо медленнее остальных. Тестируемый никогда не встречался с данными словами, возможно, даже не знает их правописания.


4. КАК ЗАЩИТИТЬСЯ ОТ "РАЗМНОЖЕНИЯ"
(идентификация ПЭВМ).

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

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

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

Наиболее эффективен второй путь, так как проверка компьютера проста и непродолжительна, может часто повторяться по ходу работы, не снижая общего быстродействия. Если же режим реального времени не обязателен и возможны многократные обращение к "медленным устройствам" типа гибких дискет или проверка клавиатурного почерка пользователя (конечно, когда он участвует в работе программы), то и остальные типы охраны могут быть встроены в блок защиты.


Разберем алгоритмы проверки компьютера. Программу удобнее привязать к следующим характеристиками машины:

1) быстродействие: процессор, память, контроллеры и т.д.; скорость вращения двигателей дисководов; скорость реакции на внешние воздействия;

2) конфигурация: тип микропроцессора (МП) и разрядность шины данных; наличие и тип контроллеров для внешних устройств и самих устройств (жесткие и гибкие диски, сопроцессор);

3) особенности: контрольная сумма BIOS; содержимое CMOS памяти; длина конвейера шины данных; аномальные явления в ходе его работы.


Их разделение на группы обусловлено лишь похожими алгоритмами определения и применения, а вообщем-то, оно весьма условно.

Легко заметить, что быстродействие (первая группа) в наибольшей степени отражает индивидуальные отличия машин - они, пожалуй, эффективнее других привяжут ПО к компьютеру. Правда, из-за нестабильности электронных элементов схемы, нестабильны и показатели его узлов. Незнание способов корректировки таких накладок чаще всего и отпугивает программистов.

Один из методов определения быстродействия компьютера представлен в процедуре "Sample" (рис. 3.1), который фиксирует отсчет таймера за время выполнения фрагмента 16 - 20. В регистр AX заносится для дальнейшего использования результат. Напомним, непосредственное его сравнение с некоторой эталонной величиной может привести к ошибке из-за нестабильности задающего генератора ПЭВМ. Отметим также, что реализация аналогичного алгоритма на языке BASIC даст еще больший разброс значений - это общий недостаток почти всех языков высокого уровня. Для исключения грубых ошибок и повышения точности необходимо провести многократные измерения и воспользоваться алгоритмом на рис. 1.1 (глава "Идентификация пользователя: "свой"-"чужой?").

Время выполнения одного и того же участка программы на разных компьютерах скорее всего будет отличаться, что и позволит выделить определенную ПЭВМ из ряда аналогичных.

Тот же пример (рис. 3.1) годится и для измерения скорости работы оперативного запоминающего устройства (ОЗУ). Его электрическая схема набирается из микросхем (МС), объемом по 16, 32 или 64 Кб (килобит). В зависимости от типа, 8 - 16 таких МС составляют 1 блок (электронщики называют их "блоком", а программисты "страницей"), емкостью 64 КБ (килобайт). Значит, в стандартном адресном пространстве IBM PC/XT в 640 КБ - 10 блоков МС, причем каждый имеет собственные характеристики, чуть-чуть отличающиеся от других. То есть быстродействие страниц ОЗУ у каждого компьютера различно. На участке 16 - 20 осуществляется простая перезапись содержимого области памяти (ее регенерация). Время регенерации всех страниц составит ряд из 10 чисел, значения и последовательность которых характерны только для данной ПЭВМ.

Скорость вращения двигателей дисководов определяется аналогично (например, замер по таймеру операции чтения/записи некоторого сектора или дорожки дискеты, как это делает COPYLOCK).

Под скоростью реакции на внешние воздействия понимается время, необходимое компьютеру на отклик после получения команды внешнего устройства, или размер паузы между выдачей команды, например, в контроллер накопителя гибких магнитных дисков (НГМД), и приходом сигнала готовности (аппаратное прерывание IRQ7 для НГМД). Измерения проводятся по отсчетам таймера, но можно использовать и свой программный счетчик, как это делает BIOS при дисковых операциях.

Если речь идет о компьютерах одной партии, то информация о типе и конфигурации не уникальна, хотя, как дополнительный элемент привязки к характеристикам ПЭВМ, не повредит. Ее можно получить через прерывание BIOS 11h (или по адресу 40h:0010h ОЗУ), а более исчерпывающую - из CMOS-памяти. Гораздо сложнее определить программным путем тип МП.

Характеристики третьей группы, очевидно, не всегда индивидуальны у конкретной машины. Общеизвестно, что в одной партии конрольная сумма BIOS одинакова (если, конечно, это не так называемая "белая" сборка). Энергонезависимая память CMOS, содержащая часы реального времени и информацию о конфигурации, также зачастую одинакова. К сожалению, формат CMOS различен на разных типах машин, а значит единого способа привязки нет. Если же расчет строится на определенный тип компьютера, то доступ к CMOS вполне возможен (с условием, что конфигурация не будет меняться в процессе эксплуатации программы).

Алгоритм чтения/записи байтов в ячейки CMOS приведен на рис. 3.2. Кстати, процедуру подсчета контрольных сумм можно усложнить, если арифметическую операцию "сложение" заменить на логическую или добавить к ней еще что-нибудь.

А на рис. 3.3 более интересный алгоритм, шифрующий и одновременно привязывающий программу к конкретному компьютеру. На определенные участки защищаемой программы накладывают некоторую область CMOS (например, операцией XOR). При запуске программа сама осуществит обратную процедуру, дешифрируя свой код (удобнее использовать область, защищенную контрольной суммой, байты 10h - 20h). Естественно, что на другом компьютере константа "CMOS" будет отличаться и, значит, процесс дешифровки испортит программу. Кстати, здесь годится и собственная информация, записанная в резервные ячейки энергонезависимой памяти, если, конечно, ее формат позволяет это делать, как, например, у компьютеров фирмы WIPRO Information Technology Limited (допускающих достаточно вольное обращение с CMOS: в том числе и с ячейками, защищенными контрольной суммой, с последующей корректировкой по адресам 2Eh,2Fh). А компьютеры SystemPro фирмы Compaq, хотя и не дают программисту возможности воспользоваться этим методом защиты, но обладают (как и некоторые другие на базе МП 80386 и выше) таким интересным свойством, как пользовательский пароль, который занесен в байты 38h - 3Fh и защищен от чтения и записи.

Последние две особенности третьей группы характеристик ПЭВМ, на наш взгляд, наиболее перспективны для защиты ПО от исследования и поэтому рассматриваются в следующей главе ("Защита от исследований").

Независимо от выбранного способа идентификации, больше всего вопросов вызывает сама передача программ покупателю. Ведь в этот момент они уже должны содержать в себе эталонные характеристики ПЭВМ пользователя, чтобы проводить соответствующие проверки. Хорошо, если автор может прийти и лично настроить свои программы, а как быть с иногородними покупателями?

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

Такую схему передачи можно применять даже при пересылке программных продуктов по почте - после самоуничтожения инстолятора владение ключевой дискетой становится бесполезным.

                        Ассемблер:                          
                        ----------                          
 1 0000          code    segment para public                
 2                       assume cs:code,ds:code             
 3                                                          
 4 0000          sample  proc                               
 5                                                          
 6 0000  FA          cli                                    
 7 0001  BA 0043     mov dx,43h      ; включить 0-й канал   
 8 0004  B0 34       mov al,34h      ; таймера              
 9 0006  EE          out dx,al                              
10 0007  B2 40       mov dl,40h      ; задать начальное     
11 0009  8A C6       mov al,dh       ; значение счетчика    
12 000B  EE          out dx,al                              
13 000C  EE          out dx,al                              
15                ;=======================================  
16 000D  33 F6         xor si,si        ;                   
17 000F  8B FE         mov di,si        ; Здесь может быть  
18 0011  B9 8000       mov cx,8000h     ; расположен любой  
19 0014  FC            cld              ; ваш текст         
20 0015  F3> A5        rep movsw           ;                
21                ;=======================================  
23 0017  BA 0043   mov dx,43h   ; зафиксировать текущее     
24 001A  B0 04     mov al,4     ; значение счетчика         
25 001C  EE        out dx,al                                
26 001D  B2 40     mov dl,40h   ; считать значение счетчика 
27 001F  EC        in  al,dx    ; в AX                      
28 0020  8A E0     mov ah,al                                
29 0022  EC        in  al,dx                                
30 0023  86 E0     xchg ah,al                               
31 0025  FB        sti                                      
32                                                          
33        ; здесь должна быть проверка считанного значения  
34                                                          
35 0026  B8 4C00        mov ax,4c00h                        
36 0029  CD 21          int 21h                             
37                                                          
38 002B         sample  endp                                
39 002B         code    ends                               
40              end     sample                              
                                                            
                        BASIC:                              
                        ------                              
100     OUT     &H43, &H34                                  
110     OUT     &H40, 0                                     
120     OUT     &H40, 0                                     
        . . . . . . . . . . . . . . . . . . .               
                                                            
        ' Текст замеряемого участка программы               
                                                            
        . . . . . . . . . . . . . . . . . . .               
300     OUT     &H43, 4                                     
310     X% = INP ( &H40 ) + INP ( &H40 ) * 256              
320     PRINT X% 
рис. 3.1


1)  чтение:                                                 
    Ассемблер:                         BASIC:               
    ----------                         ------               
      . . .                           . . .                 
mov al,номер байта CMOS    300  OUT &H70, номер байта CMOS  
  out 70h,al                 310  X% = INP ( &H71 )         
  jmp $+2                                                   
   in al,71h                               . . .             
     . . .                                                  
2)   запись:                                                 
 Ассемблер:                     BASIC:               
 ----------                     ------               
  . . .                          . . .                
mov al,номер байта CMOS    300  OUT &H70, номер байта CMOS
out 70h,al                 310  OUT &H71, новое значение  
jmp $+2                                                   
mov al,новое значение               . . .                 
out 71h,al                                                
 . . .
рис. 3.2


  Ассемблер:              BASIC:                          
  ----------              -----                           
   . . .                     . . .                           
  mov ax,0f800h         500  DEF SEG = &Hf800               
  mov es,ax             510  S = 0                          
  xor ax,ax             520  FOR I = 0  TO  32766  STEP 2   
  mov bx,ax             530  S = S + PEEK(I) + PEEK(I+1)*256
  mov cx,4000h          540  NEXT                           
rpt:                    550  PRINT S                        
  add ax,es:[bx]                                            
  inc bx                   . . .                            
  inc bx                                                    
  loop rpt                                                  
   . . .
рис. 3.3

5. ЗАЩИТА ОТ ИССЛЕДОВАНИЙ.

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

Четкой грани между дизассемблированием и анализом полученного текста под отладчиком - нет (часто эти функции совмещены в единой программе), что и позволило объединить методы борьбы с обоими способами "взлома" в рамках одной статьи. Но приемы против каждого из них - свои. Ведь противодействовать декодировке записанного на дискете файла нельзя (допустима лишь пассивная защита - запутывание алгоритма или шифрация самих кодов), зато при работе защищенных модулей на компьютере ( пусть даже в пошаговом режиме отладки ) активное сопротивление вполне возможно.

Еще одно замечание. Искусственное усложнение исполняемого модуля затрудняет исследование алгоритмов. Надежность защиты, в данном случае, зависит от того, насколько программист отождествит себя со "взломщиком", угадает логику его мышления и представит проблемы, с которыми тот сталкивается. А для этого ему самому нужно побывать в роли хакера, почти по системе Станиславского.

ОБЫЧНЫЕ ПРОБЛЕМЫ ХАКЕРА

Проще всего разбирать чужую программу, если она уже распечатана на бумаге на любом языке высокого уровня (Паскаль, Си и т.д.), но в крайнем случае сгодится и ассемблер (машинные коды заменены их мнемоническим изображением). Кстати, в качестве универсального инструмента рекомендуем отладчик Turbo Debugger (TD), имеющий широкий сервис и удобный интерфейс.

Естественно, автор программы, предусмотрев это, применил шифрование или ее разновидность - архивацию. А потому непосредственное дизассемблирование уже не даст верных результатов, если вообще что-то даст. Опытный хакер быстро поймет, что вместо текста идет "мусор" и сразу же начнет поиск средств для снятия шифра. Обычно он достигает цели, так как рано или поздно программа сама производит нужную операцию (она ведь не подозревает, что ее запустил хакер). Определив момент завершения дешифрации, можно "снять" в файл содержимое памяти, занимаемой уже "нормальной" программой, и, прогнав его дизассеблером, получить желаемый результат.

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

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

В режиме отладки больше всего забот доставляет стек: его расположение, размер, варианты применения. Достаточно тонкое его использование зачастую делает невозможным даже запуск стандартных отладочных средств. Например, назначение в тело выполняемой задачи: стековый сегмент совпадает с кодовым, а указатель вершины стека SP указывает на саму программу. Тогда отработка отладчиком хотя бы одного прерывания (трассировочного) обязательно сотрет участок размером не менее 3-х слов. Тем более, что популярные отладчики (TD, CodView и другие) применяют только пользовательский стек, затирая в нашем случае коды на большую глубину. Кроме того, старые версии TD имеют принципиальную ошибку - при начальной загрузке совершенно произвольно уменьшают стартовое значение указателя стека на 2. Более умеренно работают со стеком отладчики AFD и PERISCOPE. И наиболее выгодно себя проявляет обычный DEBUG, поставляемый вместе с DOS.

Переназначение стека в свободную область памяти как средство борьбы с назначением его в тело программы не каждому "по плечу", тем более если через него передаются массивы данных из модуля в модуль, да и он сам активно участвует в работе (как, например, в пакете CONVOY фирмы "Элиас", осуществляющем через стек разархивацию защищенного файла). В этом случае корректный проход программы возможен только без трассировки (то есть пошаговый режим исключен).

Не менее важная и такая же сложная проблема, стоящая перед хакером, - отслеживание прерываний, перехватываемых исследуемой программой. Суть в следующем. Все стандартные отладчики для нормальной работы "забирают" первое и третье из них. Первое (трассировочное) используется для пошагового режима. Третье необходимо для точек останова программы по заданным адресам. Защитный механизм обязательно должен их перехватывать, чтобы предотвратить анализ под отладчиком. Хакер, если он разобрался с замыслом автора, может либо обойти данный участок (с не малой долей риска, если прерывание выполняет некоторую "полезную" функцию), либо изменить подпрограмму обработки прерывания таким образом, чтобы после ее отработки управление передавалось отладчику (но неумелое ее исправление тоже чревато...).

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

ОТПОР АНАЛИЗУ:
НА УРОВНЕ ТЕКСТОВ ...

Сформулируем приемы, мешающие анализу: шифрование и архивирование (как его разновидность); использование самогенерируемых кодов; изощренный стиль программирования и многое другое, что сможет придумать автор.

Шифрование исполняемых файлов - наиболее простое средство для реализации. Достаточно, например, к каждому байту модуля добавить некоторую константу, чтобы дизассемблер ничего "не понял".

Предварительное архивирование также не представляет особых затруднений для хакера, но является более эффективным по сравнению с шифрованием, так как решает сразу две задачи: уменьшает размер защищаемого модуля и скрывает код от дизассемблера. Как это делается? Возьмем файл рисунка. Он содержит поточечное описание всех строк экрана (цифры - это точки определенного цвета, ноль - ее отсутствие). Например, рисунок красной линии на экране, состоящей из 200 точек, записывается в файл в виде 200 байт, а значение каждого байта равно 4 (код для красного цвета). Архиватор заменяет перечисление одинаковых цифр (эти 200 четверок) элементарным шифром - двумя байтами (первый - количество повторов, второй - значение цвета), и размер файла резко уменьшается (в примере - с 200 до 2 байт). Для других типов записей существуют свои методы сжатия. Большинство из них описано в литературе, поэтому не будем останавливаться.

Метод самогенерируемых кодов наиболее сложен в реализации, но очень эффективен. Суть его такова. В программу вложен массив данных, который сам по себе может быть исполняемым кодом (реально получающим управление) или смысловым текстом, но после некоторых арифметических или логических операций преобразуемый в участок программы, выполняющий иные, не менее важные функции.

Нужно быть виртуозом программирования, чтобы заметить самомодифицирующуюся ловушку. Ведь при анализе листинга и с явными алгоритмами разбираться сложно (автор комментарии не оставляет), так что уж говорить о потайном смысле вроде бы расшифрованного участка.

Впрочем, и новичок-разработчик создать такие ловушки не сможет. Но коль скоро он взялся за написание защитных механизмов, то ему придется осваивать изощренный стиль программирования, который запутывает дизассемблер нестандартной интерпретацией некоторых команд и нарушает общепринятые соглашения. Например, использование необычной структуры программы (совмещение стекового и кодового сегментов ). Интеллектуальные дизассемблеры, как правило, это плохо воспринимают. А перекрестные вызовы процедур, многократные переходы из модуля в модуль и увеличение количества точек входа в них - не позволяют выявить блочную структуру программы.

Замена команд переходов, вызовов подпрограмм и прерываний направляет дизассемблер по ложному следу. Здесь вместо стандартного оператора вставляется группа других, в конечном счете выполняющих то же самое. Для неискушенных программистов на рисунке 4.1 (а-д) приведены такие варианты. Впрочем, для аналогичных эффектов достаточно в команде перехода изменить значение операнда (примеры е-ж). И еще проще модифицировать косвенные переходы (з-и).

Кстати, и саму команду можно модифицировать. Например, на рис. 4.1 (к) дизассемблер по адресу m: покажет PUSH AX (запись регистра AX в стек), поскольку этот байт имеет код 50h (01010000b), но перед ее выполнением один бит (4-й) меняется, в результате получается INC AX с кодом 40h (01000000b, увеличение содержимого регистра AX на 1) - то есть совсем другая команда, не отраженная в листинге.

Кропотливая работа преобразует участок до неузнаваемости. А "умный" дизассемблер (например, Sourcer), отслеживая "явную" передачу управления (в другое место), не найдет спрятанный блок и, следовательно, не будет дизассемблировать его.

... И В РЕЖИМЕ ОТЛАДКИ.

Опытный хакер, если ему не надоест разбираться с защитой, будет неоднократно прогонять непонятые куски программы отладчиком. Некоторые приемы борьбы с этим уже рассматривались.

Очень эффективное средство от пошагового выполнения программы - назначение стека в ее тело. А если там находятся данные для работы, то режим отладки усложняется. К тому же частое изменение местоположения стека, поверьте на слово, измотает хакера окончательно.

Напомним, что при пошаговом режиме хакеру рекомендовалось обходить участки, перехватывающие 1-е прерывание. Так вот, чтобы он не смог воспользоваться этим советом, нужно поручить подпрограмме обработки прерывания некоторую полезную функцию. Например, генерацию кодов или дешифрацию.

Напомним также традиционные методы защиты [1].

Программа должна подсчитывать и проверять контрольные суммы своих участков для определения "контрольных точек" или "точек останова", расставленных хакером. Дело в том, что стандартное применение 3-го прерывания предусматривает запись кода его вызова вместо байта программы, а это меняет контрольную сумму. Периодическая же проверка вовремя проинформирует программу о замене "родных" байт "чужими", то есть о попытке исследования программы под отладчиком.

Известно, что выполнение программы в режиме трассировки значительно уменьшает ее быстродействие. Поэтому по времени "прохода" отдельных кусков защищаемого ПО можно определить работу под отладчиком. По таймеру (например, запустив его 2-й канал) заранее просчитывают скорость выполнения некоторого участка и сравнивают его со значением, полученным в ходе работы программы. Если есть существенное расхождение в полученных результатах, то можно сделать вывод о выполнении данного участка под контролем. Из недостатков метода отметим лишь разное быстродействие процессоров на разных ПЭВМ, которое следует учитывать.

Интересный способ выматывания "исследователя" - применение достаточно больших процедур, производящих некоторую сложную и, на первый взгляд, важную работу, но на самом деле, не имеющих никакого отношения к логике работы программы, так называемых "пустышек". Для лучшей имитации их важности можно включать в них перехват 13h, 21h, 25h и 26h прерываний (обслуживающих ввод-вывод информации на внешние устройства), что, безусловно, заинтересует хакера.

Оригинальный способ защиты ПО от исследования, примененный в пакете COPYLOCK, использует конвейер шины данных микропроцессора. На рис. 4.2 изображен его фрагмент. (Надеемся, что не навлечем на себя гнев цивилизованных пользователей, афишируя некоторые тонкости программы: все равно она безнадежно устарела, да и не вскрыта лишь самыми ленивыми. А начинающим специалистам рекомендуем ознакомиться с ее работой. Полный листинг опубликован в электронном журнале "НСК", N1, 1992 г.). Фрагмент дан со значением смещений относительно кодового сегмента, чтобы читатель смог увидеть, как команда REP STOSW в подпрограмме SUBR затирает значением из регистра AX область ОЗУ, в которой находится и сама подпрограмма. Тем не менее, 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 битом.

2) Начиная с МП 80286, характерна следующая особенность: команда PUSH SP заносит в стек значение SP с учетом его декремента, а более низшие типы МП - без.

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

В качестве примера, реализующего некоторые приемы, была разработана утилита DLOCK. Правила пользования ею приведены в приложении 2.


Л и т е р а т у р а

1. Дмитриевский Н.Н., Расторгуев С.П. " Искусство защиты и "раздевания" программ", "СОВМАРКЕТ", 1991.

2. статья "Особенности работы МП 8086/8088 в пошаговом режиме", "Журнал д-ра Добба", N 2, 1991.

3. "Intel insight on specific instructions", "Personal Computer World", April, 1990.



         СОКРЫТИЕ АДРЕСОВ                                   
а) безусловного перехода                                    
    jmp m        mov ax,offset m  ; занести в стек          
    . . .        push ax          ; адрес метки.            
                 ret              ; перейти на метку.       
                 . . .                                      
  m:. . .     m: . . .                                      
    . . .        . . .                                      
б) вызов подпрограммы                                       
    call subr          mov ax,offset m  ; занести в стек    
    . . .              push ax          ; адрес возврата.   
    . . .              jmp subr         ; перейти на под-   
    . . .         m:   . . .            ; программу.        
  subr:        subr:   . . .                                
в) прерывание                                               
    int 21h           pushf         ; занести в стек флаги. 
    . . .             xor si,si                             
                      mov es,si                             
                      call dword ptr es:[21h*4]             
                        . . .                               
г) возврат из подпрограммы                                  
    . . .                  . . .          ; взять из стека  
    ret                    pop bx         ; адрес возврата и
                           jmp bx         ; перейти на него.
   . . .                  . . .                             
д) выход из прерывания                                      
   iret                mov bp,sp          ; переход на точку
                       jmp dword ptr [bp] ; возврата из пре-
   . . .               . . .              ; рывания.        
                       add sp,4           ; точка возврата. 
                       popf                                 
                       . . .                                
        МОДИФИКАЦИЯ                                         
е) перехода                                                 
     mov word ptr cs:m+1,1234h  ; адрес 1234h вписать вместо
     . . .                      ; 0000 у оператора безуслов-
  m: jmp 0000h                  ; ного перехода             
     . . .                                                  
ж) вызываемой подпрограммы                                  
      mov word ptr cs:m+1,es    ; изменить сегмент п/п      
      mov word ptr cs:m+3,5678h ; и адрес 0000 на 5678h     
      . . .                                                 
  m:  call far 0000h                                        
      . . .                                                 
з) косвенного перехода                                      
      mov bx,1234h                                          
      jmp dword ptr cs:[bx]                                 
      . . .                                                 
и) косвенного вызова подпрограммы                           
      les si,dword ptr cs:subr                              
      call word ptr es:[si]                                 
      . . .                                                 
к) команды                                                  
      and  byte ptr cs:m,0EFh ; обнулить 4-й бит по адресу m
      . . .                                                 
  m:  push ax              ; команда преобразуется в INC AX 
      . . .
рис. 4.1


               Фрагмент пакета COPYLOCK
   (использование конвейера шины данных микропроцессора)
         . . . . .                                          
cs:07FF          mov     cx,40Eh                            
cs:0802          mov     di,08A6h                           
cs:0805          call    subr                               
        . . . . .                                           
;=====================================                      
; Затирание участка памяти.                                 
        subr     proc    near                               
cs:0D63          pushf                                      
cs:0D64          cld                                        
cs:0D65          mov     ax,ds                              
cs:0D67          mov     es,ax                              
cs:0D69          rep     stosw                              
cs:0D6B          popf                                       
cs:0D6C          retn                                       
        subr     endp
рис. 4.2


           ОПРЕДЕЛЕНИЕ РЕЖИМА ТРАССИРОВКИ
                    (1 вариант)
 1 0000         code    segment para public                 
 2              assume cs:code,ds:code                      
 3                                                          
 4 0000         sample1  proc                               
 5                                                          
 6 0000  0E               push cs                           
 7 0001  1F               pop ds                            
 8 0002  C6 06 0008r 00   mov byte ptr m+1,0  ; изменение   
                                 ; смещения в команде JMP   
 9 0007  EB 06        m:  jmp short norm_ex                 
10 0009  BA 001Br         mov dx,offset trace ; выполнение с
                                              ; трассировкой
11 000C  EB 04 90             jmp exit                      
12 000F                       norm_ex:      ; выполнение без
                                            ; трассировки   
13 000F  BA 0026r             mov dx,offset norm            
14 0012               exit:                                 
15 0012  B4 09                    mov ah,9                  
16 0014  CD 21                    int 21h                   
17 0016  B8 4C00              mov ax,4C00h                  
18 0019  CD 21                int 21h                       
19                                                          
20 001B               trace   db 'Tracing!',0Ah,0Dh,'$'     
21                                                          
22 0026               norm    db 'Normal exit.',0Ah,0Dh,'$' 
23                                                          
24                                                          
25 0035         sample1  endp                               
26 0035         code     ends                               
27                       end     sample
рис. 4.3


               ОПРЕДЕЛЕНИЕ РЕЖИМА ТРАССИРОВКИ
                        (2 вариант)

 1 0000        code    segment para public                  
 2                     assume cs:code,ds:code               
 3                                                          
 4 0000        sample2    proc                              
 5                                                          
 6 0000  0E               push cs                           
 7 0001  0E               push cs                           
 8 0002  07               pop es                            
 9 0003  1F               pop ds                            
10 0004  BF 000Cr         mov di,offset m                   
11 0007  F9                   stc                           
12 0008  FC                   cld                           
13 0009  B0 88                mov al,88h                    
                           ; заменить код операции следующей
                           ; команды на mov byte ptr m, al. 
14 000B  AA                   stosb                         
15 000C  3A 06 000Cr  m:  cmp al,byte ptr m                 
16 0010  73 06            jnc norm_ex                       
17 0012  BA 0024r         mov dx,offset trace               
                                ; выполнение с трассировкой,
                                ; если бит CF остался       
18 0015  EB 04 90         jmp exit         ; установленным. 
19 0018           norm_ex:                                  
20 0018  BA 002Fr             mov dx,offset norm            
21 001B           exit:                                     
22 001B  B4 09                mov ah,9                      
23 001D  CD 21                int 21h                       
24 001F  B8 4C00              mov ax,4C00h                  
25 0022  CD 21                int 21h                       
26                                                          
27 0024           trace   db 'Tracing!',0Ah,0Dh,'$'         
28 0024                                                     
29 002F           norm    db 'Normal exit.',0Ah,0Dh,'$'     
30                                                          
31                                                          
32 003E        sample2  endp                                
33 003E        code     ends                                
34                      end     sample2
рис. 4.4


                ОПРЕДЕЛЕНИЕ РЕЖИМА ТРАССИРОВКИ
                          (3 вариант)

 1 0000        code    segment para public                  
 2                     assume cs:code,ds:code               
 3                                                          
 4 0000        sample3  proc                                
 5                                                          
 6 0000  0E           push cs                               
 7 0001  0E           push cs                               
 8 0002  1F           pop ds                                
 9 0003  17           pop ss                                
10 0004  9C             pushf                               
11 0005  58             pop ax                              
12 0006  F6 C4 01       test ah,1    ; бит TF установлен ?  
13 0009  74 06          jz norm_ex   ; нет - уйти на norm_ex
                               ; да  - вып-ие с трассировкой
14 000B  BA 001Dr       mov dx,offset trace                 
15 000E  EB 04 90       jmp exit                            
16 001          norm_ex:                                    
17 0011  BA 0028r          mov dx,offset norm               
18 0014            exit:                                    
19 0014  B4 09             mov ah,9                         
20 0016  CD 21             int 21h                          
21 0018  B8 4C00           mov ax,4C00h                     
22 001B  CD 21             int 21h                          
23                                                          
24 001D            trace   db 'Tracing!',0Ah,0Dh,'$'        
25                                                          
26 0028            norm    db 'Normal exit.',0Ah,0Dh,'$'    
27                                                          
28                                                          
29 0037        sample3 endp                                 
30 0037        code    ends                                 
31                     end     sample3
рис. 4.5


DLOCK ver 2.0

DLOCK.EXE - программа встраивания в .EXE файлы модуля защиты от отладчиков и дизассемблеров, которая сама может использоваться как часть защиты программного обеспечения. Ее достоинством является то, что пользователь выбирает место расположения встраиваемых защитных модулей в своей программе.

Формат запуска программы:

DLOCK <имя файла> <смещение> где:

<имя файла> - полное имя защищаемого .EXE файла.
<смещение> - смещение от начала файла, заданное в любой системе счисления до начала буфера , в который будет размещен модуль защиты (не менее 300h байт).

Для нормальной работы, при программировании необходимо зарезервировать в своей программе область памяти не менее 300h байт. Упростить поиск этой области в оттранслированном .EXE файле поможет какое-нибудь оригинальное ключевое слово. Например:

Ассемблер: DB 'figtebe',300h DUP (?)

C: char buf[0x300] = "figtebe" ;

Средствами поиска любой оболочки DOS (XTREE, Norton Commander, PCTOOLS и др.) находим ключевое слово и определяем по нему смещение, требуемое в качестве 2-го аргумента формата запуска программы. Например, если при просмотре командой View (в режиме Hex) в пакете XTREE .EXE файл выглядел так:

  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 000240    kstackstackstack
 000250    .3.P..........!.
 000260    ....figtebe.....
 000270    ................
 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
 
 то смещение равно 264 и формат запуска программы такой:

        DLOCK YOURFILE.EXE 0x264
рис. 4.6


6. САМОМОДИФИКАЦИЯ ПРОГРАММ - ЭФФЕКТНО И ПОЛЕЗНО

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

Впрочем, полностью самомодифицирующиеся модули - большая редкость. В профессиональных системах защиты чаще применяется частичная переработка кодов. Легче всего модифицировать EXE и COM-файлы при загрузке в ОЗУ, выбирая куски для переработки случайным образом, и при этом можно сразу же вносить изменения в исходный файл программы на магнитном носителе. Как именно? Познакомьтесь с несколькими способами.

ЗАМЕНА НА ЭКВИВАЛЕНТЫ

Самый простой - периодически заменять одну последовательнось команд на другую, внешне не похожую, но, в конечном итоге, выполняющую то же самое действие. Для этого подбираем эквиваленты. Например, команда MOV AX,BX и последовательность PUSH BX и POP AX - выполняют одно действие (пересылка содержимого регистра BX в регистр AX), команда CALL adr заменяется на последовательность PUSH IP+3 и JMP adr. Примерные варианты взаимозамены для основных команд ассемблера приведены в таблице 5.1 (естественно, для конкретных программ ее нужно дополнить и расширить).

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

Разумеется, конкретная таблица может иметь несколько альтернативных вариантов для каждой последовательности. А для выравнивания их длин можно использовать команду NOP или ее аналоги (пара PUSH - POP или MOV AX,AX).

Включение в алгоритм элементов случайности делает "внешность" задачи непредсказуемой. Пример этого способа приведен на прилагаемой дискете.

ИЗМЕНЕНИЕ КОДИРОВКИ

Более сложный способ - модификация кодов команд с изменением характера выполняемых операций (рис. 5.1). Делается это так. Написанный на ассемблере и уже отлаженный модуль транслируется в объектный код с получением листинга. На листинге, не обращая внимания на мнемонику, ищем участки с похожими закономерностями изменения величин кодов команд (вот где пригодится опыт решения математических задач, типа "найди закономерность", из популярных журналов). Затем выделяем найденные участки в отдельную подпрограмму и, используя подмеченную закономерность, составляем алгоритм ее преобразования в коды первого участка, второго, третьего... Этот алгоритм встраиваем вместо участков и по завершению преобразования подпрограммы - передаем ей управление. Как правило, с первой попытки полной аналогии с изъятым блоком не получается, поэтому нужно поманипулировать командами, переставить их местами, может быть - добавить лишние (тем не менее не нарушающими общего алгоритма), что-то заменить эквивалентной последовательностью.

ПРОХОД "СВОИМ ХОДОМ" ПО ДАННЫМ

Несмотря на кажущуюся простоту, одновременное использование некоторых байт как операторов и операндов является "высшим пилотажем" в программировании. Способ пришел от программистов для 8-разрядных процессоров типа Z80, К580 и др. Дело в том, что у них основные коды однобайтовых пересылок и букв совпадают, к тому же у компьютеров с МП Z80 маловато ОЗУ (приходится его экономить). Вот и используют участки осмысленного текста - как для появляющихся на экране сообщений, так и для загрузки нужных регистров. Разумеется, некоторые буквы оказываются лишними при прогоне участка, как кода программы. Но, с другой стороны, вслед за "сообщением" можно поставить несколько команд, корректирующих результаты ненужных операций. Пример приведен в распечатке листинга игры "Jetpac" фирмы "Ultimate" для компьютера "Spectrum-48" на рис. 5.2 (для МП Z80). По ходу космической игры в верхней части экрана появляются надписи: "1UP" (результат 1 игрока), "HI" (лучший результат за всю игру) и "2UP" (2 игрок). При анализе текста программы выяснилось, что эти надписи образуют отдельную подпрограмму, осуществляющую пересылки некоторого значения из ячейки ОЗУ (адрес 0D055h) в стек и из аккумулятора в эту же ячейку (то есть сложный обмен значениями между регистром A, стеком и ОЗУ).

Впрочем, то что легко программируется для 8-разрядных процессоров, вызывает определенные трудности на 16-разрядных: и характер операций у "буквенных" кодов другой, и однобайтовых команд мало (с двух - трехбайтовыми разбираться еще сложнее). Тем не менее, после некоторой тренировки можно и этот способ взять на вооружение.

ЗАМЕНА БЛОКОВ

Традиционный подход при использовании ветвления заключается в построении 2-х участков с разным набором команд. При выполнении запрограммированного условия - выполняется первый, в противном случае - управление передается на второй. В самомодифицирующихся модулях лучше отойти от общепринятой схемы, и применить переброску того или иного блока на один и тот же участок программы. Сработало условие - на следующие за ним адреса записывается первый набор команд, не сработало - другой, затирая предыдущие (тем более, что у МП 286 и выше - блочные пересылки выполняются легко и быстро).

Определить в распечатке такой "оверлейный" блок - очень сложно, особенно, если его куски хранятся в других сегментах.



                           БЛОК ДЕКОДИРОВАНИЯ
                (присланный Ерко В.Д., автор неизвестен):
            
    ; 1 модуль программы                            
n:  mov HL, nn   ; адрес начала блока               
    mov BC, ll   ; длина блока                      
    mov AX, kk   ; ввод ключа декодера              
    xor (HL)     ; декодирование                    
    mov (HL), AX ; замена закодирован. значения на раскодир.
    inc HL       ; переход к очередному байту       
    dec BC       ; уменьшение счетчика              
    jnz  n       ; повтор декодирования, если BC > 0
    ..........   ; продолжение модуля               
    ; 2 модуль программы                            
nn: db .......................                      
                 ; (Закодированный блок.)           
    db ........  ; конец блока, адрес = nn + ll     
мм: db ........  ; 3 модуль (и так далее)           
                                                    
      После декодирования 1  блока  и  исполнения  остальных
команд управление передается на декодированный блок, который
начинается  с  такой  же  процедуры,  декодирующей следующий
участок. И таких вложений - 156.
рис. 5.1


        ИСПОЛЬЗОВАНИЕ ТЕКСТА КАК КОДА ПРОГРАММЫ
                     (для микропроцессора Z80)

6E1E  C3 6C 71    jmp  716Ch      ; завершение предыдущего  
                                  ; участка         
6E21  47          mov  B,A        ; начало подпрограммы     
6E22  31 55 D0    mov  SP,0D055h  ;1UP - текст первого      
                                  ; сообщения       
6E25  47          mov  B,A        ;                 
6E26  32 55 D0    mov  (0D055h),A ;2UP - текст второго      
                                  ; сообщения       
6E29  45          mov  B,L        ;                 
6E2A  48          mov  C,B        ;H - третье сообщение     
6E2B  C9          ret             ;I   (оно же завершает    
6E2C  21 00 00    mov  HL,0000    ;     подпрограмму)
рис. 5.2


Таблица 5.1. ВЗАИМОЗАМЕНЯЕМЫЕ КОМАНДЫ.
Первичный код Альтернативный код
Команды пересылки:
mov op1,op2 push op2
pop op1
xchg op1,op2 push op1
push op2
pop op1
pop op2
lds r,dword ptr op mov r,word ptr op
mov ds,word ptr op+2
les r,dword ptr op mov r,word ptr op
mov es,word ptr op+2
Высокий темп в начале теста, заметно снижаюшийся к его завершению. Более правильное и четкое написание начала текста по сравнению с заключением.
Арифметические команды:
add op1,op2 xchg op2,ax
add op1,ax
xchg op2,ax
adc,sub,sbb и др. аналогично add
inc op add op,1
dec op sub op,1
Логические команды:
and,or,xor и др. аналогично add
not op xor op,0ff(ff)h
Цепочечные команды:
rep movsb      push ax
m: mov al,[si]
     mov es:[di],al
     inc si
     inc di
     loop m
     pop ax
repe(repne) cmpsb        push ax
m:   mov al,[si]
       cmp al,es:[di]
       jne(je) m1
       inc si
       inc di
       loop m
m1: pop ax
lodsb mov al,[si]
inc si
stosb mov es:[di],al
inc di
shift op,cnt       push cx
      mov cx,cnt
m:  shift op,1
      loop m
      pop cx
Команды передачи управления:
j(условие) loc       jn(условие) loc1
      jmp loc
loc1: . . .
loop loc dec cx
jne loc
jmp addr push addr
ret
jmp dword ptr addr push addr+2
push addr
retf
call addr       push m
      jmp addr
m:  . . .


Cокращения: op, op1, op2 - операнды команд; r - операнд-регистр; shift - код команды сдвига; cnt - счетчик в командах сдвига; loc - метка в командах перехода и цикла; addr - адрес в командах перехода и вызова подпрограмм.

7. ИСПОЛНЯЕМЫЙ МОДУЛЬ - ЧТО МОЖНО СДЕЛАТЬ
БЕЗ ИСХОДНЫХ ТЕКСТОВ?

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

Разумеется, приемы корректировки исполняемых модулей предназначены профессиональным разработчикам ПО для IBM PC в среде DOS. Поэтому опустим некоторые детали, которые профессионал должен знать, а в качестве примера возьмем лишь EXE-файлы - более сложные для модификации, поскольку все сказанное может быть отнесено и к COM-файлам.

Напомним, что EXE-файл состоит из заголовка, таблицы перемещения и собственно исполняемого кода. Информация заголовка используется операционной системой для загрузки модуля в оперативную память. Устанавливаются значения основных регистров, обрабатывается таблица перемещения, а затем управление передается задаче. В ходе работы все основные функции ввода/вывода, захвата или освобождения ОЗУ и т.п. обрабатываются операционной системой через прерывание 21h, а значит, всегда могут быть изменены с помощью специального драйвера, который либо резидентно находится в памяти, либо непосредственно включен в модифицируемый EXE-файл. Второй подход более удобен.

Для корректировки функций EXE-файла необходимо: внедрить в него этот драйвер; осуществить передачу управления на драйвер.

ВКЛЮЧЕНИЕ В ТЕЛО EXE-файла СВОЕГО МОДУЛЯ

Вариантов включения собственного блока в существующий EXE-файл несколько: можно добавить его в конец или в начало файла; встроить в свободное место внутри программы или "склеить" им оба EXE-файла (свой и модифицируемый).

Легче всего добавить дополнительные команды в конец EXE-файла и исправить в заголовке размер загружаемой части (с учетом добавленных байт). Однако предварительно необходимо проверить, возможна ли их загрузка в ОЗУ. Дело в том, что задача может быть оверлейной и DOS загрузит только ее корневой сегмент. Например, в BORLAND C++ размер BCC.EXE более 800 кб, а объем ОЗУ всего 640 кб. Ясно, что загрузкой и выгрузкой отдельных частей гиганта занимается специальный блок в корневом сегменте программы, который ничего не знает о "прилепленном" в конце модуле, и поэтому тот никогда не попадет в оперативную память. А в заголовке имеется информация только о корневом блоке, небольшом по размеру. Так что если к загружаемой части не относится "хвост", значит данный метод здесь не годится.

В этом случае можно поискать "пустые" места в загружаемой части EXE-файла. Например, цепочку любых повторяющихся кодов. Если размер найденного пространства больше модуля, то все в порядке и следует вписать туда свои команды.

Если же и этого нет, то пробуем включить свой модуль в начало программы, сразу за таблицей перемещения, конечно, при наличии там свободного места. Впрочем, в отличие от предыдущего способа, здесь его всегда можно создать. Достаточно "раздвинуть" файл и изменить таблицу перемещения с учетом сдвига, затем подправить заголовок (адрес первой исполняемой команды и размер загружаемой в память части файла). Кстати, пример такой программы с комментариями приводится на дискете.

В принципе, можно и не раздвигать файл, а создать модуль в виде такого же COM или EXE-файла. Затем изменить список распределения кластеров в FAT-таблице каталога, не трогая их самих.

FAT (File allocation table) - это таблица в начальных секторах дискеты, которая содержит связный список цепочек кластеров, занимаемых тем или иным файлом на диске или относящимися к свободному пространству [2]. Ее дополняет оглавление файлов (называемое также директорий или каталог). Два байта по смещению 1Ah в элементе оглавления каждого файла содержат номер начального кластера цепочки, а каждый элемент цепочки в FAT-таблице указывает на следующее звено или информирует о конце файла.

Для включения модуля в EXE-файл необходимо найти в FAT-таблице цепочку, отмечающую занятые модулем кластеры диска и заменить в ней метку "конец модуля" ссылкой на начальный кластер встраиваемого исполняемого файла. Затем в элементе оглавления файла исправить номер начального кластера (вместо него вписать стартовый номер кластера нашего модуля), а сам модуль пометить как удаленный.

В результате при запуске EXE-файла на выполнение операционная система загрузит в память содержимое всей цепочки кластеров с диска, в том числе и кластеров нашего файла, который первым получит управление. Теперь уже его команды должны отвечать за запуск исполняемой части EXE-файла, в который он был внедрен.

Основная сложность при "склейке" двух программ заключается в том, чтобы после первой корректно запустить вторую. Если первая - ваша, вопрос решается просто: при ее завершении нужно передать управление по адресам, взятым из заголовка второй задачи. Если же обе из "склеиваемых" - "чужие", причем завершаются в неизвестном месте и неизвестным способом, то выход один - необходимо изменить часть DOS, обрабатывающую функции завершения процессов.

Это можно сделать двумя способами. Первый. Создается специальный драйвер перехватывающий все функции завершения работы программ (назовем его монитор). Затем, "склеиваются" вместе все выбранные EXE или COM-файлы, причем сначала в полученном конгламерате размещается монитор. При запуске он принимает на себя обработку прерываний, а получив управление, анализирует - какая из задач уже отработала, освобождает ресурсы, выбирает и размещает в ОЗУ следующую задачу, и передает ей управление. После последней задачи монитор восстанавливает исходную подпрограмму DOS и завершает свою работу.

Второй вариант является модификацией первого. Разница заключается только в том, что монитор не обладает суверенитетом отдельной задачи, а прикрепляется к первой из них одним из уже описанных способов. После этого, к "зараженной" монитором задаче можно командой COPY добавлять любое количество EXE-файлов.

ПЕРЕДАЧА УПРАВЛЕНИЯ

Управление автоматически перейдет на модуль, внедренный в тело EXE-файла, если изменены начальные значения регистров CS и IP в заголовке файла (байты 20 - 23 заголовка) или первый оператор, на который указывают эти регистры (вместо него ставят команду перехода JMP либо CALL по адресу своего модуля). Но можно перехватить управление исправив номер прерывания в двухбайтовой команде INT. Рассмотрим эти методы подробнее.

Для изменения начальных значений регистров CS и IP в заголовке EXE-файла после внедрения блока команд в его тело нужно скопировать с 20 по 23-й байт заголовка (CS:IP) в специальный буфер, предусмотренный в модуле. Затем вписать в заголовок файла адрес первой команды модуля, а по его завершении передать управление на сохраненный в буфере адрес начала выполнения EXE-файла.

Впрочем, можно измененить первую команду (указанную регистрами CS:IP), не меняя сам заголовок. После внедрения блока команд в тело файла скопируем первые байты в заранее предусмотренный буфер, а вместо них впишем JMP или CALL с адресом модуля. По завершении его работы выполним сохраненные в буфере команды EXE-файла и передадим управление ему самому (на адрес из заголовка файла с учетом уже выполненных команд).

Если же недалеко от начала EXE-файла встретится собственный JMP или CALL с атрибутом far , то достаточно изменить адрес перехода у существующей команды (запомнив первоначальное значение) на адрес встроенного модуля. Удостовериться в том, что обнаруженный вами байт ( EAh или 9Ah ) действительно является первым байтом команды JMP или CALL с аттрибутом FAR можно используя таблицу перемещения: один из ее элементов должен указывать на адрес на 3 больший, чем адрес найденного байта (это сегментная часть адреса в команде).

Изменение номера прерывания в двухбайтной команде INT является самым простым из всех перечисленных способов перехвата управления. Метод не требует внедрения своего модуля в тело "чужого" файла. Достаточно лишь изготовить резидентный драйвер, отрабатывающий любое свободное прерывание DOS. А в EXE-файле ищем первое попавшееся прерывание и заменяем его тем, на котором "висит" наш драйвер. Естественно, что он должен обрабатывать и функцию исправленной команды INT в ЕХЕ-файле.

ДИНАМИЧЕСКАЯ КОРРЕКТИРОВКА ПРОГРАММЫ.

Допустим, надо отстранить резидентную задачу от обработки какого-либо прерывания. В этом случае необходимо выяснить, какая из загруженных в ОЗУ программ получает, словно эстафетную палочку, обработку данного прерывания.

Доступ к диску осуществляется, в основном, через 13h и 21h прерывания. Системы защиты обычно "забирают" их на себя и проверяют, разрешен ли доступ по ним. Если разрешен, то остальной процесс возвращается обратно к операционной системе. Порой, чтобы снять защиту, достаточно восстановить переустановленный вектор прерывания, направив его на DOS. А найти старый адрес поможет пошаговый режим (трассировка) отладчика. Но как определить, что "процесс дошел" именно до защитного механизма? Это можно сделать автоматически. Текст такой программы (на языке Си) находится на дискете в директории FTRACE.

Заметим, что трассировкой пользуются не только отладчики, но и вирусы. Метод их работы демонстрируется программой RV (файлы rv.c, ftrace.asm, ftrace.h). Кстати, "вирусный" подход можно использовать и для борьбы с вирусами же. Практика показала его эффективность: например, приведенная на дискете программа protect.asm мешает "хорошо себя чувствовать" некоторым вирусам, но и, правда, некоторым антивирусам тоже.

8. КАК ОЧИСТИТЬ ПРОГРАММУ ОТ ВИРУСОВ И
ПРИСТЫКОВАННЫХ ЗАЩИТ

В прерыдущей главе описано, как внедрить защитный механизм в тело программы. В этой, напротив, расскажем о способе его удаления с помощью программы EXEB, имеющейся на дискете.

НАЗНАЧЕНИЕ

Программа EXEB.EXE предназначена для анализа исполняемых модулей и удаления из них пристыковочных частей - вирусов, защит и т.п. Она корректно работает на ПЭВМ типа IBM PC/XT/AT в среде MS DOS версии 3.1 и выше.

СОДЕРЖИМОЕ ДИСКЕТЫ И ПОРЯДОК УСТАНОВКИ

Поставляемая дискета содержит следующие файлы:

README - описание;

EXEB.EXE - основная программа;

CHSIZE - утилита для уменьшения размера результирующей задачи.

Перед началом работы необходимо скопировать дискету на жесткий диск в любой директорий.

Формат команды запуска:

EXEB [!] <IntNumber> <FuncNumber> <Counter> <TaskName> [<CommandLine>]

где:

! - признак "холостого" срабатывания;

<IntNumber> ::= номер перехватываемого прерывания;

<FuncNumber> ::= номер функции (AH) указанного прерывания;

<Counter> ::= счетчик появлений функции FuncNumber;

<TaskName> ::= имя исследуемой задачи;

<CommandLine>::= аргументы командной строки исследуемой задачи.

Примечание:

В командной строке в качестве аргумента FuncNumber разрешен символ "*".

Числовые аргументы задаются в 16-ричной системе счисления.

Например, "EXEB 21 30 1 a.exe" - означает: перенести код исследуемой задачи a.exe в результирующий EXE-файл при первом обращении к 30h функции 21h прерывания после запуска a.exe.

Аргументы желательно выбирать таким образом, чтобы они соответствовали первому после пристыкованного блока прерыванию в теле исследуемой задачи.

Если программа была создана компиляторами с языков высокого уровня (С, PASCAL, BASIC и т.п.), то рекомендуются следующие значения аргументов:

  <IntNumber>   = 21                     <IntNumber>   = 21
  <FuncNumber>  = 30       или           <FuncNumber>  = 35
  <Counter>     = 1                      <Counter>     = 1.

EXEB позволяет исследовать исполняемый EXE-модуль на команды вызова прерываний (int). Их номера фиксируются программой EXEB, если в качестве аргумента FuncNumber использован символ "?". Например: при строке запуска программы "EXEB 10 ? 1 a.exe" в крайнем правом столбце экрана будут выcвечиваться текущие номера функций 10-го прерывания.

Первый аргумент командной строки "!" - признак "холостого" срабатывания - необязателен. Его функциональное назначение - выдача звукового сигнала в момент обнаружения указанной вами в командной строке ситуации (без реальной ее обработки программой EXEB, т.е. без создания результирующего EXE-файла).

Итогом работы EXEB является файл с именем TASK.EXE, который можно запускать на выполнение (в той же среде, в которой он был создан: версия DOS, конфигурация ПЭВМ).

ПРИНЦИПЫ РАБОТЫ

Будучи запущенной, EXEB захватывает указанное в командной строке прерывание, запускает исследуемую задачу и начинает отсчитывать обращения к указанной в командной строке функции захваченного прерывания. Когда счетчик обращений станет равен 0, EXEB переносит образ исследуемой задачи из оперативной памяти на диск. При этом первой исполняемой командой задачи станет вызов указанного в командной строке EXEB прерывания (int ??). Схематично последовательность работы EXEB представлена на рис. 7.1 - 7.3.

После запуска задача EXEB выдает на экран сообщение о готовности и ожидает нажатия любой клавиши. В этот момент пользователь при желании может вставить дискету в дисковод (при исследовании задачи, имеющей защиту по ключевой дискете).

ОСОБЕННОСТИ РАБОТЫ И НЕДОСТАТКИ

Результирующая задача TASK.EXE не всегда способна воспринять командную строку, указанную в аргументе <CommandLine> при ее создании.

TASK.EXE должна запускаться примерно в той же среде, где она была создана (объем свободной оперативной памяти). В случае какого-либо несоответствия на экран выдается сообщение об этом и TASK.EXE прекращает работу.

Так как EXEB "снимает" в файл TASK.EXE практически всю оперативную память, то его объем может быть очень большим. Для уменьшения размера TASK.EXE можно использовать утилиту CHSIZE, формат запуска которой вы можете выяснить запустив ее без аргументов.


СХЕМА РАБОТЫ ПРОГРАММЫ EXEB.EXE

рис.7.1 - 7.3

9. ПРОВЕРКА УСВОЕННОГО

Если вы внимательно прочитали весь предшествующий материал, то справиться с двумя головоломками будет несложно. Если же задания оказались вам не под силу, вновь проштудируйте статьи.

ГОЛОВОЛОМКА 1

На рис. 8.1 приведена программа, которая не работает под отладчиком в пошаговом режиме. Проверьте это, оттранслировав и запустив ее, например, под Turbo Debugger. Нажимая клавишу F8 (без захода в п/п), благополучно доберетесь до ее конца. Если же попробуете пройти программу в потактовом режиме (клавиша F7), с заходом в подпрограмму "DEL", то после выполнения оператора STOSW продолжение будет невозможно. Почему?

ГОЛОВОЛОМКА 2

Программа на рис. 8.2 также не работает в пошаговом режиме, но причина здесь иная. В чем тут дело?

cseg        segment para public 'code'                     
         assume cs:cseg                             
 exam        proc                                   
 start:                                             
         jmp        frwd                            
 del:                                               
                 pushf                              
                 cld                                
                 mov        ax,cs                   
                 mov        es,ax                   
                 rep        stosw                   
                 popf                               
                 ret                                
 frwd:                                              
         push        cs                             
         pop        ds                              
         mov        cx,12                           
         mov        di,offset start                 
         call        del                            
         mov        dx,offset msg                   
         mov        ah,9                            
         int        21h                             
         mov        ax,4c00h                        
         int        21h                             
 msg        db 'Hellow, boys!',0ah,0dh,'$'          
 exam        endp                                   
 cseg        ends                                   
         end        start
рис. 8.1 ГОЛОВОЛОМКА 1


TEXT:       segment byte public 'CODE'             
         assume cs:TEXT                             
         org 100h                                   
                                                    
 start:        mov        dx,offset prv             
         mov        ah,9                            
         int        21h                             
         db        2eh                              
         pushf                                      
         pop        ax                              
         sahf                                       
         mov        ah,9                            
         jb        Glk                              
         mov        dx,offset mes1                  
         int        21h                             
         mov        ax,4c00h                        
         int        21h                             
 Glk:                                               
         mov        dx,offset mes2                  
         int        21h                             
         mov        ax,4c01h                        
         int        21h                             
                                                    
 prv        label byte                              
         db 'dbtest',0ah,0dh,024h                   
                                                    
 mes1        label byte                             
         db 'Ok',0ah,0dh,24h                        
                                                    
 mes2        label byte                             
         db 'Trace',0ah,0dh,24h                     
                                                    
 TEXT        ends                                   
         end start
рис. 8.2 ГОЛОВОЛОМКА 2


10. АНОНС ВМЕСТО ЗАКЛЮЧЕНИЯ

Второй номер компьютерного приложения к журналу "Техника-молодежи" продолжит тему защиты информации. В нем будут даны ответы на некоторые вопросы по вирусологии, возникающие у неискушенных пользователей, состоится знакомство с программами-отладчиками и детально описаны способы защиты исполняемых модулей от исследования:

- вирусы и их функции;

- отладчики: состояние, перспективы; как "доработать" имеющийся отладчик;

- библиотека подпрограмм для защиты исполняемого кода от исследования;

- распределенные программные модули; генерация исполняемого кода;

- программный замок с псевдослучайным ключом;

- DLOCK ver 3.0;

- рекомендации по защите программ для ПЭВМ типа "Enterprisse" и "Spectrum" ("Синклер");

- квалификационная тест-программа.

Дискета, как всегда, содержит исполняемые модули и исходные тексты программ на Ассемблере, Си, Бейсике.

Подписаться на оптовую поставку компьютерного приложения можно в редакции журнала "Техника-молодежи" (125015, Москва, Новодмитровская ул., д. 5а, тел. 285-16-87, 285-89-80), приобрести единичные экземпляры - там же или у наших диллеров (у которых Вы купили первый выпуск).

Приложение 1
СЛОВАРЬ ТЕРМИНОВ

Аномалии МП - специфические особенности выполнения некоторых команд микропроцессора.

Байт - единица информации, в системе MS DOS байт может принимать значения кодов от 0 до 255, 2 байта составляют машинное слово (значение от 0 до 65536).

Блок (подпрограмма, процедура) - часть программы (хранящаяся на диске внутри .EXE файла), имеющая собственный набор команд и данных, и предназначенная для выполнения некоторых действий с последующей передачей управления тому блоку основной программы программы, который ее вызвал.

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

Дисперсия - мера рассеяния значений случайной величины около ее математического ожидания.

Драйвер - (англ. "водитель") резидентная программа, постоянно находящаяся в оперативной памяти и активизирующаяся от соответствующего прерывания, обработка которого за ней закреплена. В отличие от других резидентных программ, драйвер, как правило, создается для сопровождения одного устройства или поддержки одной программы, формируя необходимую для их нормальной работы среду в оперативной памяти.

Заголовок EXE-файла - начальная часть файла, в которой, в частности, содержится информация о стартовом значении регистров МП, размере всего файла, таблица перемещения и т.д.

Защитный механизм - часть исполняемого модуля, реализующая защитные функций: идентификацию пользователя, компьютера, магнитного носителя, защиту программы от исследования и т.п.

Идентификация - сопоставление предъявленных характеристик с эталонными.

Исполняемый модуль - программа или ее законченная часть (хранящаяся на диске отдельно), имеющая набор команд и данных, имя и предназначенная для загрузки в оперативную память ПЭВМ с последующуй передачей ему управления.

Исходный текст (исходник) - текст программы на одном из языков программирования и введенный в ПЭВМ непосредственно программистом (до какой-либо обработки его компьютером).

Кластер - минимальная единица дисковой памяти, выделяемая DOS-ом для хранения файла.

Ключевая фраза - (она же - парольная) последовательность символов, вводимая пользователем с клавиатуры для его идентификации.

Конвейер шины данных - аппаратно реализованная память ПЭВМ (обычно 4 - 6 байт), предназначенная для хранения очереди процессорных команд, ожидающих выполнения.

Контроллер - аппаратное устройство, реализующее обмен информации между ПЭВМ и периферийным оборудованием.

Контрольная точка - команда, после или до выполнения которой может быть зафиксировано состояние вычислительного процесса.

Листинг - текст программы написанный на одном из языков программирования, в котором, как правило, указана информация по выделенным для программы ресурсам компьютера (распределение памяти и др.) и приведены коды команд. В отличие от исходных текстов, которые вводит программист, листинг конечный продукт специальных программ (трансляторов, компиляторов, дизассемблеров и т.д.).

Математическое ожидание - характеристика случайной величины, ее определение связано с понятием о среднем значении множества (область центра математического множества).

МП - микропроцессор.

НСК - несанкционированное копирование.

НСД - несанкционированный доступ.

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

ПО - программное обеспечение.

Пошаговый режим - процесс выполнения программы по одной команде. После выполнения каждого шага управление возвращается программе, осуществляющей пошаговый режим (для возможности просмотра состояния ОЗУ и содержимого регистров МП).

Прерывание - программно или аппаратно инициированная передача управления по адресу, который находится в таблице векторов прерываний:

- аппаратное - инициируется контроллерами периферийного оборудования;

- программное - инициируется программой;

- трассировочное - аппаратное прерывание по вектору 1, выполняемое после каждой команды процессора, если флаг трассировки TF слова состояния процессора установлен;

- 21h - программное прерывание по вектору 21h, реализующее все основные функции DOS (файловые операции, управление памятью, справочная информация и т.д.);

- 13h - программное прерывание по вектору 13h, реализующее все основные операции по работе с диском;

- функции - выполняемые тем или иным прерыванием в зависимости от значений входных аргументов.

Пристыкованный блок - блок программы (модуль), который работает только один раз, как правило, сразу после запуска программы, и после передачи управления основной задаче (к которой он пристыкован) в дальнейшем вычислительном процессе не участвует.

Псевдослучайная последовательность - последовательность чисел, подчиняющаяся заданному закону распределения.

Резидентная программа - программа, постоянно находящаяся в оперативной памяти и активизирующаяся от соответствующего прерывания, обработка которого за ней закреплена.

Самомодифицирующийся модуль - исполняемый блок программы, изменяющий собственные команды в процессе выполнения.

Сегмент - страница оперативной памяти (блок ОЗУ), отведенная либо для кодов программы (кодовый сегмент), либо под стек (стековый), либо под данные (сегмент данных).

Сегментные: регистры - аппаратные регистры микропроцессора, предназначенные для хранения адресов соответствующих сегментов: CS - кодового, DS - данных, SS - стека;

пересылки - пересылки данных из сегмента в сегмент, в которых участвуют сегментные регистры.

Стек - часть оперативной памяти, выделяемая программе для хранения промежуточных результатов вычислений и данных.

Таблица перемещения - часть заголовка EXE-файла, содержащая адреса команд и данных в его теле, относительно начала файла на диске. После выделения DOS-ом свободных сегментов для загрузки в ОЗУ, операционная система, пользуясь таблицей перемещений, пересчитает относительные адреса на абсолютные (те, на которых программа реально будет располагаться в оперативной памяти).

Точка останова - адрес команды, перед выполнением которой управление передается отладчику.

Трассировка - процесс пошагового выполнения программы под отладчиком.

Утилита - программа, дополняющая операционную систему, выполняющая одну из функций обслуживания компьютера или его периферии.

Элемент оглавления - структура, описывающая дисковый файл.

Эмулятор - устройство (программа), позволяющее анализировать результаты выполнения каждой команды исследуемой программы без реальной передачи ей управления.

BIOS - Base Input Output System (базовая система ввода/вывода).

CMOS - энергонезависимая память ПЭВМ, имеет встроенные часы реального времени с календарем, содержит информацию о конфигурации машины.

COM-файл - исполняемый модуль, содержащий только бинарный образ задачи без какой-либо управляющей информации; этот тип программ всегда загружается в ОЗУ по одним и тем же адресам (указанным при написании программы), величина COM-файла не может превышать размер одного сегмента (64 КБ).

EXE-файл - программный файл (коды модуля, программы), хранящийся на диске, имеющий заголовок и таблицу перемещения. После загрузки модуля в оперативную память, DOS вводит в регистры МП начальные значения (из заголовка) и настраивает программу на выделенные сегменты памяти.

FAT - системная таблица диска, указывающая физическое раположение файлов и свободную область на диске.

SP (указатель вершины стека) - аппаратный регистр МП, содержащий смещение текущего адреса стека относительно начала стекового сегмента (адрес в регистре SS).



Hosted by uCoz