Защита данных от несанкционированного доступа


            Министерство Образования и Науки Республики Беларусь
           Минский Государственный Высший Радиотехнический Колледж



                Защита данных от несанкционированного доступа


                            Пояснительная записка
                       к курсовому проекту по предмету
                          “Языки программирования”

                               КП 46.41010.301



      Руководитель проекта                                     Потапенко  Н.
 И

      Учащийся                                                 Еганов Максим

                                    1996
                                 Содержание.

      Введение    .    .     .    .     .     .    .     .     .    .      .
 3
      1.  Постановка задачи  .    .     .     .    .     .     .    .      .
 4
      1. 1. Организационно-экономическая сущность задачи .     .    .      .
 4
      1. 2. Входные данные   .    .     .     .    .     .     .    .      .
 6
      1. 3. Постоянная информация .     .     .    .     .     .    .      .
 6
      1. 4. Выходная данные  .    .     .     .    .     .     .    .      .
 6
      2. Вычислительная система   .     .     .    .     .     .    .      .
 7
      2. 1. Операционная система  .     .     .    .     .     .    .      .
 7
      2. 2. Технические средства реализации задачи .     .     .    .      .
 .  8
      2. 3. Программные средства  .     .     .    .     .     .    .      .
 8
      3. Алгоритм задачи     .    .     .     .    .     .     .    .      .
 10
      4. Описание программы  .    .     .     .    .     .     .    .      .
 14
      5. Описание применения программы  .     .    .     .     .    . 16
      6. Заключение    .     .    .     .     .    .     .     .    .      .
 17
      Приложение 1. Листинг программы   .     .    .     .     .    .      .
 18
      Приложение 2. Листинг библиотек   .     .    .     .     .    .      .
 39
      Приложение 3. Пример работы программы   .    .     .     .    .      .
 45
      Список литературы      .    .     .     .    .     .     .    .      .
 47



                             КП 46.41010.301 ПЗ
                                1. Введение.

      Появившиеся в начале 80-ых персональные ЭВМ (ПЭВМ или ПК) прочно вошли
 во все сферы человеческой деятельности. Вместе с  ними  у  эксплуатирующих
 ПЭВМ организаций и ведомств возникли и многочисленные  проблемы.  Одна  из
 них — защита информации. Согласно статистическим данным более 80% компаний
 и агентств несут финансовые убытки из-за нарушения безопасности данных.
      Проблема  защиты  информации  представляет  собой  совокупность  тесно
 связанных проблем в областях  права,  организации  управления,  разработки
 технических средств, программирования и математики.  Одна  из  центральных
 задач проектирования систем защиты состоит  в  рациональном  распределении
 имеющихся ресурсов.
      Характерная особенность использования ПЭВМ в нашей стране заключатся в
 том, что  доступ  к  ним  имеют  многие  пользователи.  В  связи  с  таким
 "многопользовательским"   режимом    работы    возникает    целый    набор
 взаимосвязанных вопросов по защите информации, хранящейся в ПЭВМ.
      При создании и использовании ПЭВМ возникает целый ряд  взаимосвязанных
 теоретических и практических проблем. В коммерческих  и  военных  областях
 одной из основных является проблема защиты информации. Так можно  выделить
 следующие  объективные  причины,  определяющие  важность  проблемы  защиты
 информации:
.  высокие темпы роста парка ПЭВМ, находящихся в эксплуатации;
.   широкое  применение  ПЭВМ  в   самых   различных   сферах   человеческой
  деятельности;
.  высокая степень концентрации информации в ПЭВМ;
.  совершенствование способов доступа пользователей к ресурсам ПЭВМ;
.  усложнение вычислительного процесса в ПЭВМ.
      Усложнение методов и средств организации машинной обработки информации
 приводят к тому, что  информация  становится  все  более  уязвимой.  Этому
 способствуют   такие   факторы,   как   постоянно   возрастающие    объемы
 обрабатываемых данных, накопление и хранение данных в ограниченных местах,
 постоянное расширение круга пользователей, имеющих доступ как  к  ресурсам
 ПЭВМ, так и к программам и данным, хранящихся в  них,  усложнение  режимов
 эксплуатации вычислительных систем и т. п. [6]

                             КП 46.41010.301 ПЗ
                            1. Постановка задачи
             1. 1. Организационно-экономическая сущность задачи

      Защита информации в процессе ее сбора, хранения и обработки  принимает
 исключительно важное значение. Под защитой  информации  принято  принимать
 совокупность  мероприятий,  методов  и  средств,  обеспечивающих   решение
 следующих задач:
      - проверка целостности информации;
      - исключение несанкционированного доступа к  защищаемым  программам  и
        данным;
      - исключение  несанкционированного  использования  хранящихся  в  ПЭВМ
        программ (т. е. защита программ от копирования).
      Использование  ПЭВМ  в  военной,  коммерческой   и   других   областях
 человеческой деятельности порождает  ряд  специфических  проблем,  которые
 необходимо  решить  для  защиты  обрабатываемой  и   хранящейся   в   ПЭВМ
 информации. Одной из них является классификация возможных  каналов  утечки
 информации.  Под  возможным   каналом   утечки   подразумевается   способ,
 позволяющий нарушителю получить доступ к  обрабатываемой  и  хранящейся  в
 ПЭВМ информации [7].
      Классификацию возможных  каналов  утечки  информации  исходя  из  типа
 средства, являющегося основным  при  получении  информации  по  возможному
 каналу утечки. Следовательно, можно выделить три  типа  средств:  человек,
 аппаратура, программа. Применительно к  ПЭВМ  группу  каналов,  в  которых
 основным  средством  является  человек,  составляют   следующие   основные
 возможные каналы утечки:
      .  хищение  носителей  информации  (дискет;  лазерных,  магнитных   и
        магнитооптических дисков и т. д.);
      . чтение информации с экрана посторонним лицом (во время  отображения
        информации на экране  законным  пользователем  или  при  отсутствии
        законного пользователя на рабочем месте);
      . чтение информации из оставленных без присмотра распечаток программ.
      В группе каналов, в которых основным  средством  является  аппаратура,
 можно выделить следующие основные каналы утечки :
      . подключение к устройствам ПЭВМ специально  разработанных  аппаратных
        средств,
                             КП 46.41010.301 ПЗ
      обеспечивающих доступ к информации;
      .  использование  специальных  технических   средств   для   перехвата
        электромагнитных излучений технических средств ПЭВМ.
      В группе каналов, в которых основным  средством   является  программа,
 можно выделить следующие основные каналы утечки :
      . несанкционированный доступ программы к информации;
      . расшифровка программой зашифрованной информации;
      . копирование программой информации с носителей.
      В данной работе нас интересует последняя группа поэтому система защиты
 данных от  несанкционированного  доступа  должна  обеспечивать  выполнение
 следующих функций:
      . идентификация ресурсов, т. е. присвоение ресурсам идентификаторов  —
        уникальных признаков, по которым  в  дальнейшем  система  производит
        аутентификацию;
      .  аутентификация  защищаемых  ресурсов,   т.   е.   установление   их
        подлинности на основе сравнения с эталонными идентификаторами;
      . разграничение  доступа  пользователей  по  операциям  над  ресурсами
        (программы, данные), защищаемыми с помощью программных средств;
      . администрирование:
      = определение прав доступа к защищаемым ресурсам,
      = установка системы защиты на ПЭВМ ,
      = снятие системы защиты с ПЭВМ,
      . контроль целостности и работоспособности систем защиты.
      Во время создания системы защиты  можно  выделить  следующие  основные
 принципы, которых следует придерживаться при проектировании:
     1. Простота механизма защиты. Этот принцип общеизвестен  но  не  всегда
        глубоко осознается. Действительно, некоторые ошибки, не выявленные в
        ходе проектирования и эксплуатации, позволяют обнаружить  неучтенные
        пути доступа. Необходимо тщательное  тестирование  программного  или
        аппаратного средства  защиты,  однако  на  практике  такая  проверка
        возможна только для простых и компактных схем.
     2. Отсутствие доступа. В механизме защиты в нормальных условиях  доступ
        должен  отсутствовать,  и  для  работы  системы  защиты   необходимы
        условия,  при  которых  доступ  становится  возможным.  Кроме  того,
        считается, что запрет доступа при
                             КП 46.41010.301 ПЗ
      отсутствии особых указаний  обеспечивает  высокую  степень  надежности
        механизма защиты.
     1. Механизм защиты можно  не  засекречивать,  т.  е.  не  имеет  смысла
        засекречивать детали реализации систем защиты,  предназначенной  для
        широкого пользования.
     2.  Психологическая  привлекательность.  Система  защиты  должна   быть
        простой в эксплуатации [6].
      Исходя   из   этого,   требуется   разработать   систему   защиты   от
 несанкционированного  доступа,  которая  должна  обеспечивать   выполнение
 следующих функций:
      . аутентификация пользователя по паролю и по ключевой дискете;
      . шифрование выбранных файлов;
      . установка на программы защиты от несанкционированного запуска;
      . реакция на несанкционированный доступ.

                          1. 2. Входная информация

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

                         1. 3. Постоянная информация

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

                          1. 4. Выходная информация

      Выходные данные — зашифрованные файлы и защищенные программы.


                             КП 46.41010.301 ПЗ
                          2. Вычислительная система
                         2. 1. Операционная система

      Программа “Защита  данных  от  НСД”  разрабатывалась  под  управлением
 операционной системы   MS-DOS 6.22. Предполагается,  что  программа  будет
 работать без сбоев с MS-DOS и PC-DOS версий не ниже 5.0.
      Операционная  система  (ОС)  является  неотъемлемой  частью  ПЭВМ.  ОС
 обеспечивает управление всеми аппаратными компонентами и поддержку  работы
 программ пользователя,  предоставляя  ему  возможность  общего  управления
 машиной.
      К основным достоинствам MS DOS относятся:
      . возможность организации многоуровневых каталогов;
      .  возможность  подключения  пользователем  дополнительных   драйверов
        внешних устройств;
      .  возможность работы со всеми последовательными  устройствами  как  с
        файлами;
      . развитый командный язык;
      . возможность запуска фоновых задач одновременно с диалоговой  работой
        пользователя и др.
      Важнейшей особенностью MS DOS является модульность, что позволяет  при
 необходимости  расширения  функций  системы  модифицировать  отдельные  ее
 модули. DOS состоит из следующих основных модулей:
      = базовая система ввода/вывода (BIOS);
      = блок начальной загрузки (Boot Record);
      = модуль расширения базовой системы ввода/вывода(___BIO.COM);
      = модуль обработки прерываний (___DOS.COM);
      = командный процессор (COMMAND.COM);
      = утилиты DOS.
       Достоинством DOS является то, что любая программа может  играть  роль
 сервисной, поскольку для ее запуска достаточно указать лишь имя  файла,  в
 котором она содержится. Следовательно, с точки зрения  пользователя  такие
 программы  не  отличаются  от  встроенных  команд  DOS.  Программа   может
 воспринимать параметры, задаваемые в командной строке. Храниться она может
 в любом каталоге на любом диске. Указанное свойство  делает  ДОС  открытой
 для расширения.  Неизменное  ядро  системы  составляют  лишь  BIOS  и  три
 основных моду- ля: BIO.COM, DOS.COM и COMMAND.COM Общий объем  оперативной
 памяти, занимаемой этими модулями, составляет до 60 Кбайт.


                             КП 46.41010.301 ПЗ
                2. 2. Технические средства реализации задачи

      Программа работает на компьютерах  клона  IBM,  начиная  с  процессора
 Intel 80-286.  Требуемый  объем  оперативной  памяти  —  минимум  1,5  Mb.
 Минимальные  требования  к  видеоаппаратуре   —  карта  VGA   и   256   Kb
 видеопамяти.

                2. 3. Программные средства реализации задачи

      Программа “Защита данных от несанкционированного доступа”  разработана
 в среде Borland Pascal 7.0 (Borland International ©, 1992). Пакет  Borland
 Pascal 7.0 учитывает новейшие достижения  в  программировании  и  практике
 создания программ и включает в себя три режима работы:
      . обычный режим операционной системы MS-DOS
      . защищенный режим MS-DOS
      . режим Windows.
      Пакет Borland Pascal включает в себя как язык программирования —  одно
 из  расширений  языка  Паскаль  для  ПЭВМ  клонов  IBM,   так   и   среду,
 предназначенную для написания, отладки и запуска программ.
      Язык  характеризуется  расширенными  возможностями  по  сравнению   со
 стандартом, хорошо развитой библиотекой модулей, позволяющих  использовать
 возможности  операционной   системы,   создавать   оверлейные   структуры,
 организовывать ввод-вывод, формировать графические изображения и т. д.
      Среда   программирования   позволяет   создавать   тексты    программ,
 компилировать их, находить ошибки и оперативно их исправлять,  компоновать
 программы из отдельных частей, включая стандартные  модули,  отлаживать  и
 выполнять отлаженную программу.  Пакет  предоставляет  пользователю  также
 большой объем справочной информации.
      Версия 7.0 также, как  и  предыдущая,  позволяет  применять  объектно-
 ориентированное программирование, обладает встроенным  ассемблером,  имеет
 инструментальное средство создания интерактивных программ — Turbo  Vision,
 но появился ряд характерных особенностей:
      - выделение цветом различных элементов программы;
                             КП 46.41010.301 ПЗ
      -  ряд  дополнительных  расширений  языка,  таких,  как  использование
        открытых массивов,  параметров-констант,  типизированного  адресного
        оператора @ и т. д.;
      - расширенные возможности объектно-ориентированного программирования;
      - усовершенствованные программы Turbo Vision [2].
      При написании  программы  также  использовался  интегрированный  пакет
 Turbo Vision 2.0. При создании прикладной  программы  программист  большие
 усилия затрачивает  на  организацию  ввода-вывода  информации,  т.  е.  на
 формирование интерфейса. Они  соизмеримы  с  усилиями,  затрачиваемыми  на
 программирование  основного  алгоритма  программы,  по  которому  решается
 конкретная  задача.  Работа,  связанная   с   организацией   ввода-вывода,
 повторяется  от  программы  к  программе,  требует  выполнения  однотипных
 операций, отвлекает внимание программиста от выполнения основной задачи.
      Прекрасным средством упрощения работы по организации ввода-вывода, его
 унификации  с   учетом   требований   к   интерфейсу   программ   является
 разработанный  фирмой  Borland  International  пакет  Turbo  Vision   2.0,
 представляющий объектно-ориентированную  библиотеку  средств  формирования
 пользовательского интерфейса. Кстати, интерфейс самого Borland Pascal  7.0
 (и Turbo Pascal 7.0 тоже) построен на стандартных  объектах  Turbo  Vision
 2.0.
      Структуру  передачи  информации  в  достаточно  общем   случае   можно
 представить в виде, изображенном на рис. 1.

                           Решение основной задачи



             Организация  диалога                Непосредственная   передача
 данных



                             Внешние устройства


      Рис.1. Структура программы с учетом организации ввода-вывода.


                             КП 46.41010.301 ПЗ
      Согласно этому рисунку программу можно  представить  как  совокупность
 двух частей: часть программы, обеспечивающая решение основной программы, и
 часть, обеспечивающая организацию ввода-вывода  с  внешних  устройств  (на
 внешние устройства), — так  называемый  интерфейс  программы.  В  основную
 часть (из основной части) информация может передаваться двумя способами  —
 непосредственная передача информации (например, программа формирует какие-
 то данные и размещает их в конкретном файле на магнитном диске) и передача
 информации с помощью организации диалога (например, после формирования тех
 же данных происходит уточнение, в какой конкретно файл  следует  поместить
 сформированную информацию). Способ,  основанный  на  организации  диалога,
 является более универсальным и именно для организации диалога предназначен
  в первую очередь пакет Turbo Vision.
      В  программах,  работающих   в   текстовом   режиме,   диалог   обычно
 организуется с  помощью  трех  средств:  меню,  диалоговых  окон  и  строк
 состояния [3].
      Также  при  создании  программы  использовался  ассемблер  —  машинно-
 ориентированный язык. На ассемблере написаны  основные  подпрограммы,  где
 требуется высокое быстродействие и минимальный размер программного кода.

                             3. Алгоритм задачи

      Программу условно можно разделить на несколько частей:
     1) Инсталляционный модуль.
     2) Оболочка программы (написана с использованием Turbo Vision 2.0).
     3) Криптографическая защита (Borland Pascal 7.0).
     4) Защита программ паролем (TASM 3.0).
     5) Защита программ с помощью ключевой дискеты (TASM 3.0).
     6) Блокировка винчестера (TASM 3.0).

                         3. 1 Инсталляционный модуль

      Модуль  инсталляции  будет  устанавливать  программу  на  винчестер  в
 определенный каталог, а также осуществлять привязку программы к уникальным
 идентификаторам BIOS.
                             КП 46.41010.301 ПЗ
                          3. 2. Оболочка программы

      При создании  интерактивного  пользовательского  интерфейса  (оболочки
 программы)  использовались  стандартные  объекты  пакета   Turbo   Vision.
 Горизонтальное  двухуровневое  меню,  строка  состояния,   рабочее   поле,
 диалоговые  окна,  информационные  сообщения  и  сообщения   об   ошибках,
 поддержка “мыши” — вот некоторые атрибуты оболочки.

                       3. 2. Криптографическая защита

      Перед описанием алгоритма следует ввести некоторые термины.
      Зашифрованием данных называется процесс преобразования открытых данных
 в зашифрованные  с  помощью  шифра,  а  расшифрованием  данных  —  процесс
 преобразования закрытых данных в открытые с помощью шифра.
      Шифрованием называется процесс зашифрования или расшифрования данных.
      Дешифрованием будем называть процесс преобразования закрытых данных  в
 открытые при неизвестном ключе и, возможно, неизвестном алгоритме.
      Криптографическая   защита   —   это   защита   данных    с    помощью
 криптографического преобразования, под которым  понимается  преобразование
 данных шифрованием.
      Уравнение зашифрования — соотношение, описывающее процесс  образования
 зашифрованных данных  из  открытых  данных  в  результате  преобразований,
 заданных алгоритмом криптографического преобразования.
      Уравнение расшифрования — соотношение, описывающее процесс образования
 открытых данных  из  зашифрованных  данных  в  результате  преобразований,
 заданных алгоритмом криптографического преобразования.
      Под шифром понимается совокупность обратимых преобразований  множества
 открытых данных на множество  зашифрованных  данных,  заданных  алгоритмом
 криптографического преобразования.
      Криптостойкостью называется  характеристика  шифра,  определяющая  его
 стойкость к дешифрованию. Обычно эта характеристика определяется  периодом
 времени, необходимым для дешифрования [6].
      Принцип зашифрования заключается в генерации  гаммы  шифра  с  помощью
 датчика псевдослучайных чисел  (ПСЧ)  и  наложением  полученной  гаммы  на
 открытые данные с
                             КП 46.41010.301 ПЗ
 помощью логической операции “исключающее ИЛИ” (т. е. обратимым образом).
      Процесс расшифрования данных  сводится  к  повторной  генерации  гаммы
 шифра при известном ключе и наложению такой гаммы на зашифрованные данные.
 Полученный зашифрованный текст является достаточно трудным для раскрытия в
 том  случае,  когда  гамма  шифра  не   содержит   повторяющихся   битовых
 последовательностей. По сути дела гамма шифра должна изменяться  случайным
 образом  для  каждого  шифруемого  слова.  Фактически  если  период  гаммы
 превышает длину всего зашифрованного текста  и  неизвестна  никакая  часть
 исходного текста, то шифр можно раскрыть только прямым
 перебором (подбором ключа). В  этом  случае  криптостойкость  определяется
 размером ключа.
      Чтобы   получить   линейные   последовательности   элементов    гаммы,
 используются датчики ПСЧ. К настоящему  времени  на  основе  теории  групп
 разработано несколько типов таких датчиков.
      В своей программе я использовал так называемый конгруэнтный  генератор
 ПСЧ — наиболее доступный и эффективный. Для этого класса  генераторов  ПСЧ
 можно сделать математически строгое заключение о  том,  какими  свойствами
 обладают выходные сигналы этих генераторов с точки зрения периодичности  и
 случайности.
      Данный    линейный    конгруэнтный     датчик     ПСЧ     вырабатывает
 последовательности псевдослучайных чисел T(i), описываемые соотношением
      [pic]                  (1)
 T(0) — исходная величина, выбранная в качестве порождающего числа.
      Этот  датчик  ПСЧ  генерирует  псевдослучайные  числа  с  определенным
 периодом повторения, зависящим от выбранных значений A  и  C.  Значение  М
 обычно устанавливается равным 2b, где b — длина слова ЭВМ в битах.  Датчик
 имеет максимальный период М до того, как  генерируемая  последовательность
 чисел  начнет  повторяться.  Линейный  конгруэнтный   датчик   ПСЧ   имеет
 максимальную длину М тогда и только тогда, когда  A  mod  4  =  1  и  С  —
 нечетное. В своей программе я положил А =  5,  С  =  27,  Т(0)  —  пароль,
 вводимый пользователем.
      С полученной последовательностью Т(i) поступают следующим образом:
            F(i) = T(i) xor D(i)                                    (2)
      Где  в  (2)  D(i)  —  последовательность  открытых  данных,   F(i)   —
 последовательность
                             КП 46.41010.301 ПЗ
 зашифрованных данных [4].
      Также  при  разработке  алгоритма  шифрования  использовался  алгоритм
 американского  федерального  стандарта  на  шифрование   данных   —   Data
 Encryption Standard (DES).
      При зашифровании  входные  данные  шифруются  по  формуле  (2),  далее
 обрабатываются блоками по 64 слова (word).  Эта  обработка  заключается  в
 следующем: :4 слова переставляются в соответствии с таблицей, изображенной
 на рис. 2:
|40     |8      |48     |16     |56     | 24    |64     |32     |
|39     |7      |47     |15     |55     |23     |63     |31     |
|38     |6      |46     |14     |54     |22     |62     |30     |
|37     |5      |45     |13     |53     |21     |61     |29     |
|36     |4      |44     |12     |52     |20     |60     |28     |
|35     |3      |43     |11     |51     |19     |59     |27     |
|34     |2      |42     |10     |50     |18     |58     |26     |
|33     |1      |41     |9      |49     |17     |57     |25     |


      Рис. 2. Перестановка после зашифрования.

      Как видно из  данной  таблицы,  слово  40  входной  последовательности
 становится 1-ым, слово 8 — 2-ым и т. д.
      Процесс расшифрования данных является инверсным относительно  процесса
 зашифрования.  Т.  е.  данные  сначала  переставляются  в  соответствии  с
 таблицей, изображенной на рис. 3, а затем преобразуются  по  формуле  (2).
 Как легко видеть, данная перестановка является  обратной  по  отношению  к
 начальной.
|58     |50     |42     |34     |26     |18     |10     |2      |
|60     |52     |44     |36     |28     |20     |12     |4      |
|62     |54     |46     |38     |30     |22     |14     |6      |
|64     |56     |48     |40     |32     |24     |16     |8      |
|57     |49     |41     |33     |25     |17     |9      |1      |
|59     |51     |43     |35     |27     |19     |11     |3      |
|61     |53     |45     |37     |29     |21     |13     |5      |
|63     |55     |47     |39     |31     |23     |15     |7      |


      Рис. 3. Перестановка перед расшифрованием
                             КП 46.41010.301 ПЗ
                            4. Описание программы

      При   написании   программы   использовались   следующие   стандартные
 библиотеки Borland Pascal 7.0 и Turbo Vision 2.0:
      . Модуль Objects.  Модуль  Objects   содержит   основные   определения
        объектов Turbo Vision, включая базовый объект иерархии Turbo  Vision
        TObject, а также все невидимые  элементы   Turbo   Vision:   потоки,
        коллекции  и ресурсы.
      .  Модуль  App.  Модуль  App   (предоставлен  в    исходных     кодах)
        обеспечивает элементы оболочки  Turbo   Vision.   4   очень   мощных
        объектных типа определены в App,   включая  объекты  TApplication  и
        TProgram, которые служат в   качестве   программ   Turbo   Vision  и
        объект панели экрана, который  управляет  большинством  элементов  в
        оконных программах.
      . Модуль Views. Модуль Views содержит основные компоненты      видимых
        элементов и полезные компоненты более сложных групп, таких как рамки
        окон  и  полосы  скроллинга.  Более   сложные    видимые    элементы
        находятся  в модулях Dialogs и TextView.
      . Модуль Dialogs.  Модуль  Dialogs  определяет  большинство  элементов
        наиболее  часто  используемых  при    создании   диалоговых    окон.
        Этот  модуль  включает   сами  диалоговые  окна  (которые   являются
        специализированными окнами) и различные элементы  управления,  такие
        как кнопки, метки, зависимые и независимые кнопки,  строки  ввода  и
        списки истории.
      . Модуль Menus. Модуль Menus  обеспечивает все объекты и процедуры для
        системы меню  Turbo  Vision,  включая  выпадающие  меню  и  активные
        элементы строки статуса.
      . Модуль  Drivers.  Модуль  Drivers  содержит  все  специализированные
        драйверы  Turbo  Vision,  включая  драйверы  мышки   и   клавиатуры,
        поддержку экрана и систему обработки ошибок с монитором событий  для
        программ, управляемых событиями.
      . Модуль Memory. Модуль  Memory  содержит  процедуры  монитора  памяти
        Turbo Vision, которые обеспечивают функции управления кучей.
      .  Модуль  CRT.  Модуль   CRT   содержит   константы,   переменные   и
        подпрограммы, предназначенные для работы с консолью.  В  отличие  от
        стандартного ввода-вывода,
                             КП 46.41010.301 ПЗ
        когда он осуществляется  через  операционную  систему,  подпрограммы
        этого модуля работают с BIOS и непосредственно с видеопамятью.
      .  Модуль  DOS.  Модуль   DOS   позволяет   использовать   возможности
        операционной системы MS-DOS, не предусмотренные  в  стандарте  языка
        Паскаль, и содержит типы, константы,  переменные  и  для  реализации
        этих дополнительных возможностей.
      Кроме вышеперечисленных  стандартных  модулей  был  разработан  модуль
 SetConf, в котором находится функция привязки программы к BIOS компьютера,
 т. е. защита от копирования.
      При  запуске  программы  в  первую  очередь  проверяется   целостность
 системы; т. е. наличие всех файлов системы, соответствуют ли  их  имена  и
 размеры таблице. Далее  происходит  инициализация:  проверяются  параметры
 BIOS. Если какой либо файл системы  был  изменен  или  параметры  BIOS  не
 соответствуют установленным в программе, система работать  не  будет.  Для
 входа в систему необходимо ввести пароль. Эти  проверки  осуществляются  в
 конструкторе Init объекта  TMyApp.  Этот  же  объект  инициализирует  меню
 (TMyApp.InitMenu), строку состояния (TMyApp.InitStatusLine), рабочее  поле
 (TMyApp.InitDeskTop),   устанавливает   специальную    цветовую    палитру
 (TMyApp.GetPalette). Обработка событий (нажатие клавиш клавиатуры,  работа
 с “мышью”) осуществляется в методе HandleEvent объекта TMyApp. При  выборе
 какого-либо пункта меню управление передается соответствующему объекту или
 вызывается нужная подпрограмма.
      В программе используются следующие процедуры, функции и объекты:
     1. Shifr (процедура). Зашифрование файлов любого типа. Сначала получаем
        пароль от пользователя,  затем  создаем  файл  зашифрованных  данных
        (*.M&A). Исходный файл считывается блоками по 64 word, кодируется  с
        помощью  генератора  ПСЧ,  затем  переставляется  в  соответствии  с
        таблицей, изображенной  на  рис.  2.  Полученную  последовательность
        записываем в файл с расширением *.M&A и т. д.
     2. DeShifr (процедура). Расшифрование файлов, зашифрованных  процедурой
        Shifr.
     3. Plus (процедура). Установка защиты паролем или по  ключевой  дискете
        на программы.
     4. Block (процедура). Защита винчестера от записи.
     5. Passwords (процедура). Изменение пароля входа в  программу.  Сначала
        запрашивает старый пароль, затем два раза новый.
     6. TOptions ( объект, потомок объекта TDialog). Выводит диалоговое окно
        изменения
                             КП 46.41010.301 ПЗ
      настроек шифрования файлов: удалять  или  не  удалять  исходный  файл,
        высвечивать или не высвечивать индикатор процесса шифрования.
     7. CheckExec (процедура). Обрабатывает ошибки DOS.

                      5. Описание применения программы

      Программа предназначена  для  защиты  данных  от  несанкционированного
 доступа; в ней реализованы следующие функции:
      . шифрование файлов;
      . защита паролем исполняемых файлов;
      . защита исполняемых файлов с помощью ключевой дискеты;
      . отслеживание и реакция на ошибки;
      . изменение паролей;
      . привязка к BIOS.
      Установка   системы   происходит   с   ключевой   дискеты   программой
 INSTALL.EXE, которая проверяет не была ли установлена система ранее;  если
 нет, то создает на винчестере каталог C:\SUB ROSA и копирует в него  файлы
 системы  (Sub  Rosa.exe,   Block,   KeyDisk,   Plus,   Passw,   Setup.res,
 System.res).
      При запуске программы Sub Rosa.exe сначала  проверяется  наличие  всех
 файлов системы. Если хотя бы один файл  изменен  или  удален,  то  система
 работать не будет. Для работы с программой необходимо ввести пароль.
      В верхней части экрана находится полоска меню, состоящая из  следующих
 пунктов:
     1. “Файлы”:
      — “Выбрать” (выбор файла для работы);
      — “Сменить каталог” (смена текущего каталога);
      — “Выход в DOS” (временный выход в DOS);
      — “Завершение” (завершение работы с программой);
     2. “Защита”:
      — “Установить пароль” (защита EXE- и COM-файлов паролем);
      — “Блокировать винчестер” (запрет записи любых данных на винчестер);

                             КП 46.41010.301 ПЗ
     3. “Ключевая дискета”:
      — “Добавить проверку по ключу” (защита EXE- и COM-файлов с помощью
            ключевой дискеты);
4. “Криптография”:
      — “Зашифровать файл данных” (зашифрование выбранного файла);
      — “Расшифровать файл данных” (расшифрование выбранного файла);
5. “Настройки”:
      — “Криптография” (изменение настроек криптографии);
      — “Пароли” (изменение пароля входа в систему);
6. “О Программе” (информация о программе).
      Во всех случаях ,  кроме  блокировки  винчестера,  сначала  необходимо
 выбрать файл для работы. Для установки  защиты  паролем  или  по  ключевой
 дискете выбирается EXE- или COM-файл, для шифрования — файл любого типа.

                                6. Заключение

      В заключении проведем анализ некоторых систем защиты  от  копирования.
 Следует отметить, что этот анализ не является исчерпывающим, так  как  эти
 системы  постоянно  развиваются,  а  также  не   всегда   можно   получить
 исчерпывающее описание алгоритмов — разработчики не  стремятся  раскрывать
 принципы их построения.
      RANK — пакет защиты от НСД.  Этот  пакет  реализует  функцию  контроля
 доступа к EXE- и COM-файлам. Следует отметить,  что  анализ  разграничения
 доступа к программам ставит под серьезное сомнение возможность  реализации
 такой функции без дополнительных мероприятий.
      LATCH  —  комплекс  программ  защиты  ПЭВМ  от  НСД.   Этот   комплекс
 обеспечивает  безопасность  данных  ,  хранящихся   на   винчестере.   При
 несанкционированном   доступе   происходит   “зависание”   ПЭВМ   или   не
 обнаруживается НЖМД.
      Тезис о невозможности обнаружения НЖМД  вызывает  серьезные  сомнения:
 например, для контроллеров SCSI  не  требуется  определение  типа  НЖМД  в
 памяти CMOS, так как параметры винчестера могут  быть  считаны  с  помощью
 команды контроллера.



                                Приложение 1
                              Листинг программы



 {**************************************************************************
 **}
 {**************************************************************************
 **}
 {**
 **}
 {**                          КП      "ЗАЩИТА      ДАННЫХ      ОТ      НСД"
 **}
 {**         Выполнили учащиеся гр.46491 ЕГАНОВ  МАКСИМ  и  ЮЗЕФОВИЧ  АРТЕМ
 **}
 {**                                                                   1996
 **}
 {**
 **}
 {**************************************************************************
 **}
 {**************************************************************************
 **}
 {$M 10240, 0,20480} {Распределение памяти}
 Program Sub_Rosa;
 Uses
   App, Dialogs, Drivers, Menus, MsgBox, Objects,
   Validate, Views, Memory, StdDlg, Editors, {Модули Turbo Vision, далее  -
 TV}
   CRT, DOS, {Стандартные модули}
   SetConf; {Модуль функции привязки к BIOS}
 Var
   MyRes                : TResourceFile; {Переменная файла ресурсов, TV}
    FName,  MainDir,  DName:  string;  {Переменные  работы  с   файлами   и
 каталогами}
   MainPass, Pass       : string; {Переменные паролей}
   Pos                  : string[3];
   FilePass             : file of char; {Переменная файла паролей}
   OptFile, OptInd      : word; {Переменные опций}
   Int09_Save           : pointer; {Переменная адреса 09h прерывания}

 Const {Константы кодов команд, TV}
   cmAboutBox  =  700; {Окно "О Программе"}
   cmCode      = 1001; {Кодировать файл}
   cmDeCode    = 1002; {Декодировать файл}
   cmSetPass   = 1005; {Установить пароль на вход в систему}
   cmLockDisk  = 1006; {Запретить доступ к винчестеру}
   cmOptions   = 1007; {Опции криптографии}
   cmKeyDisk   = 1008; {Ключевая дискета}
   cmPasswords = 1009; {Пароль на исполняемый файл}
   cmChangePass= 1010; {Сменить пароль на вход в систему}

   SetPass     = 'passw.com';
   KeyDisk     = 'keydisk.com';

   RMenuBar: TStreamRec = (            {Запись для работы с потоком, TV}
     ObjType: 2000;
     VmtLink: Ofs(TypeOf(TMenuBar)^);
     Load: @TMenuBar.Load;
     Store: @TMenuBar.Store);

 Type

   {Установка опций криптографии}
   POptions = ^TOptions;
   TOptions = object(TDialog)
     constructor Init;
   end;

   {Объект для работы с текстом}
   PMyStaticText = ^TMyStaticText;
   TMyStaticText = object(TStaticText)
     function GetPalette: PPalette; virtual; {Переопределение палитры}
   end;

   {Объекты для работы с файлами и каталогами}
   PMyFDialog = ^TMyFDialog;
   TMyFDialog = object(TFileDialog)
     function GetPalette: PPalette; virtual;
   end;

   PMyFileDialog = ^TMyFileDialog;
   TMyFileDialog = object(TMyFDialog)
     constructor Init(AWildCard: tWildStr; const ATitle,
     InputName: string; AOptions: Word; HistoryId: Byte);
   end;

   PDirDialog = ^TDirDialog;
   TDirDialog = object(TChDirDialog)
     function GetPalette: PPalette; virtual;
   end;

   PMyChDirDialog = ^TMyChDirDialog;
   TMyChDirDialog = object(TDirDialog)
     constructor Init(AOptions: Word; HistoryId: Word);
     procedure SetUpDialog;
     function Valid(Command: Word): Boolean; virtual;
   end;


   {Установка основного фона программы}
   PMyBackground = ^TMyBackground;
   TMyBackground = object(TBackground)
     Text: TTitleStr;
     constructor Init(var Bounds: TRect; AText: TTitleStr);
     procedure Draw; virtual;
   end;

   PMyDesktop = ^TMyDesktop;
   TMyDesktop = object(TDesktop)
     procedure InitBackground; virtual;
   end;

   {Объект "О Программе"}
   PAboutBox = ^TAboutBox;
   TAboutBox = object(TDialog)
     constructor Init;
   end;

   {Основной объект}
   PMyApp = ^TMyApp;
   TMyApp = object(TApplication)
     constructor Init; {инициализация}
     destructor  Done; virtual; {завершение работы}
      procedure    HandleEvent(var  Event:  TEvent);  virtual;   {обработка
 событий}
     procedure   InitMenuBar; virtual; {инициализация меню}
     procedure   InitDeskTop; virtual; {инициализация рабочего поля}
     procedure   InitStatusLine; virtual; {инициализация строки состояния}
     procedure   FileOpen(WildCard: PathStr); {окно для работы с файлами}
     function     GetPalette:  PPalette;  virtual;  {изменение  стандартной
 палитры}
   end;


 { Русифицированная функция формирования сообщения }
 function MyMessageBoxRect(var R: TRect;
            const Msg: string; Params: pointer;
            AOptions: word): word;
 const
   ButtonName: array[0..3] of string[6] = ('Ага', 'Нека', 'Ага', 'Нека');
   Commands: array[0..3] of Word = (cmYes, cmNo, cmOK, cmCancel);
   Titles: array[0..3] of string[11] =
     ('Предупреждение', 'Ошибка', 'Информация', 'Подтверждение');
 var
   I, X   : integer;
   Dialog : PDialog;
   Control: PView;
   S      : string;

 begin
   Dialog:= New(PDialog, Init(R, Titles[AOptions and $3]));
   with Dialog^ do
     begin
       Options:= Options or ofCentered;

       R.Assign(3, 2, Size.X - 2, Size.Y - 3);
       FormatStr(S, Msg, Params^);
       Insert(New(PStaticText, Init(R, S)));
       X:= -2;
       R.Assign(0, 0, 10, 2);
       for I:= 0 to 3 do
         if AOptions and ($0100 shl I) <> 0 then
           Inc(X, R.B.X - R.A.X + 2);
       X:= (Size.X - X) shr 1;
       for I:= 0 to 3 do
         if AOptions and ($0100 shl I) <> 0 then
           begin
             Control:= New(PButton, Init(
                  R, ButtonName[I], Commands[i], bfNormal));
             Insert(Control);
             Control^.MoveTo(X, Size.Y - 3);
             Inc(X, Control^.Size.X + 2);
           end;
       SelectNext(False);
     end;

   if AOptions and mfInsertInApp = 0 then
     MyMessageBoxRect:= DeskTop^.ExecView(Dialog)
   else
     MyMessageBoxRect:= Application^.ExecView(Dialog);
   Dispose(Dialog, Done);
 end;

 { Русифицированная функция формирования сообщения
                 стандартного размера }
 function MyMessageBox(const Msg: String;
            Params: Pointer; AOptions: Word): Word;
 var
   R: TRect;
 begin
   R.Assign(0, 0, 40, 9);
   MyMessageBox:= MyMessageBoxRect(R, Msg, Params, AOptions);
 end;

 function GetCurDir: DirStr;
 var
   CurDir: DirStr;
 begin
   GetDir(0, CurDir);
   if Length(CurDir) > 3 then
     begin
       Inc(CurDir[0]);
       CurDir[Length(CurDir)]:= '\';
     end;
   GetCurDir:= CurDir;
 end;

 {Процедура инициализации окна работы с файлами}
 procedure TMyApp.FileOpen(WildCard: PathStr);
 var
   FileName: FNameStr;
 begin
   FileName:= '*.*';
   if ExecuteDialog(New(PMyFileDialog, Init(
     WildCard, 'Открыть файл', 'Имя', fdOpenButton,
     100)), @FileName) <> cmCancel then FName:=FileName;
     {открыть файл, потом...}
 end;

 {**************************************************************************
 **}
 {*----------============= К Р И П Т О Г Р А Ф И Я ================---------
 -*}
 {**************************************************************************
 **}

 {Шифрование файлов}
 procedure Shifr(InputFileName: string);
 const
   A = 5;     {Константы для}
   C = 27;    {генератора}
   M = 65536; {псевдослучайных чисел, далее - ПСЧ}

 var
   TempFile                : file of byte;
   InpF, OutF              : file of word; {файлы на входе и выходе}
   Password, Password1     : string; {переменные для работы с паролями}
   OutputFileName, Exten   : string; {переменные имен файлов}
   I, J, K, tmp            : byte; {переменные кодирования}
   Temp, SCode, TByte, Code: word;
   Position                : LongInt; {переменные данных о процессе}
   NowPos                  : real;
   TPassword               : array [1..255] of word;
   MasByte, Mas, MasEnd, PS: array [1..64] of word; {массивы перестановок}
   T                       : array [0..64] of word;
   DirInfo, DirInfo1       : SearchRec; {данные о файле}
 begin
   if length(FName) > 3 then {Файл выбран?}
     begin
       {Получить пароль}
       Password := '';
       Password1 := '';
       InputBox('П А Р О Л Ь', '        Введите пароль:', Password, 255);
       InputBox('П А Р О Л Ь', 'Введите пароль еще раз:', Password1, 255);
       if (Password = Password1) and (length(Password)<>0) then

         begin
           {Преобразовать файл}
           FindFirst(InputFileName, AnyFile, DirInfo);
           if DOSError = 0 then
             begin
               if DirInfo.Size mod 2 = 1 then
                 begin
                   assign(TempFile, InputFileName);
                   reset(TempFile);
                   while not EOF(TempFile) do read(TempFile, tmp);
                   tmp := 255;
                   write(TempFile, tmp);
                   close(TempFile);
                 end;
               {Преобразовать имя файла}
               Position := 0;
               assign(InpF, InputFileName);
               reset(InpF);
               for i := length(InputFileName) downto 1 do
                 if InputFileName[i] = '.' then
                   begin
                     OutputFileName := copy(InputFileName, 1, i) + 'M&A';
                     break;
                   end;
               assign(OutF, OutputFileName);
               rewrite(OutF);
               for i:= 0 to length(InputFileName) do
                 if InputFileName[length(InputFileName) - i] = '.' then
                   case i of
                     0: Exten := chr(0) + chr(0) + chr(0);
                     1: Exten := copy(FName, length(FName)-2, i) + chr(0) +
 chr(0);
                     2: Exten := copy(FName, length(FName)-2, i) + chr(0)
                     else Exten := copy(FName, length(FName)-2, 3)
                   end;
               for i := 1 to 3 do
                 begin
                   Temp := ord(Exten[i]);
                   Write(OutF, Temp);
                 end;
               {Начать шифрование}
               k := 1;
               repeat
                 begin
                   {Считать из исходного файла блок размером 64*word}
                   for i:=1 to 64 do
                     If EOF(InpF) then  MasByte[i]  :=  0  else  Read(InpF,
 MasByte[i]);
                   Mas := MasByte;
                   T[0] := ord(Password[k]);
                   if k < length(Password) then inc(k) else k := 1;
                   for i:= 1 to 64 do
                     begin
                       {Получить текущую позицию процесса}
                       NowPos := 100*Position/DirInfo.Size;
                       inc(Position, 2);
                       if NowPos > 100 then NowPos := 100;
                       Str(Round(NowPos):3, Pos);
                       if OptInd = 0 then
                         begin
                           GoToXY(77, 1);
                           Write(Pos + '%');
                         end;
                       {Шифровать с помощью ПСЧ}
                       Code:=Mas[i];
                       T[i] := (A * T[i-1] + C) mod M;
                       Code:=T[i] xor Code;
                       Mas[i] := Code;
                     end;

                   for i:=1 to 8 do { Конечная перестановка }
                     for j:=1 to 8 do
                       case i of
                         1: MasEnd[8*(j-1)+i] := Mas[41-j];
                         2: MasEnd[8*(j-1)+i] := Mas[09-j];
                         3: MasEnd[8*(j-1)+i] := Mas[49-j];
                         4: MasEnd[8*(j-1)+i] := Mas[17-j];
                         5: MasEnd[8*(j-1)+i] := Mas[57-j];
                         6: MasEnd[8*(j-1)+i] := Mas[25-j];
                         7: MasEnd[8*(j-1)+i] := Mas[65-j];
                         8: MasEnd[8*(j-1)+i] := Mas[33-j]
                       end;
               for i:= 1 to 64 do Write(OutF, MasEnd[i]);
             end;
           until eof(InpF);
           MyMessageBox('Файл '+ InputFileName + '  зашифрован с именем ' +
                        OutputFileName, nil, mfInformation+mfOkButton);
           Close(InpF);
           if OptFile = 1 then Erase(InpF);
           Close(OutF);
         end
           else  MyMessageBox('Файл '+ InputFileName + ' не существует!',
                    nil, mfInformation+mfOkButton);

         end
       else MyMessageBox('      Ошибка ввода пароля!!!', nil,
                         mfError+mfOkButton);
     end
      else    MyMessageBox('             Файл    не    выбран!!!',     nil,
 mfError+mfOkButton);
 end;


 procedure DeShifr(InputFileName: String);
 const
   A = 5;
   C = 27;
   M = 65536;

 var
   InpF, OutF                   : file of word;
   Password, OutputFileName     : string;
   Password1                    : string;
   Exten                        : string[3];
   SCode, Temp, Ext, TByte, Code: word;
   I, J, K                      : byte;
   Position                     : LongInt;
   NowPos                       : real;
   TPassword                    : array [1..255] of word;
   MasByte, Mas, MasEnd, PS     : array [1..64] of word;
   T                            : array [0..64] of word;
   DirInfo                      : SearchRec;

 begin
   if (length(InputFileName) > 3) and
     (copy(InputFileName, length(InputFileName)-2, 3) = 'M&A') then
     begin
       Password := '';
       Password1 := '';
       InputBox('П А Р О Л Ь', '        Введите пароль:', Password, 255);
       InputBox('П А Р О Л Ь', 'Введите пароль еще раз:', Password1, 255);
       if (Password = Password1) and (length(Password)<>0) then
         begin
           FindFirst(InputFileName, AnyFile, DirInfo);
           if DOSError = 0 then
             begin
           Assign(InpF, InputFileName);
           Reset(InpF);
           Position := 0;
           Exten := '';
           for i:= 1 to 3 do
             begin
               Read(InpF, Temp);
               Exten := Exten + chr(Temp);
             end;
           for i := length(InputFileName) downto 1 do
             if InputFileName[i] = '.' then
               begin
                 OutputFileName := copy(InputFileName, 1, i) + Exten;
                 break;
               end;
           Assign(OutF, OutputFileName);
           Rewrite(OutF);
               for     i     :=     1      to      length(Password)      do
 TPassword[i]:=ord(Password[i]);
           k := 1;
           repeat
             begin
               for i:=1 to 64 do Read(InpF, MasByte[i]);
               for i:=1 to 8 do { начальная перестановка }
                 for j:=1 to 8 do
                   case i of
                     1: Mas[8*(i-1)+j]:=MasByte[66-8*j];
                     2: Mas[8*(i-1)+j]:=MasByte[68-8*j];
                     3: Mas[8*(i-1)+j]:=MasByte[70-8*j];
                     4: Mas[8*(i-1)+j]:=MasByte[72-8*j];
                     5: Mas[8*(i-1)+j]:=MasByte[65-8*j];
                     6: Mas[8*(i-1)+j]:=MasByte[67-8*j];
                     7: Mas[8*(i-1)+j]:=MasByte[69-8*j];
                     8: Mas[8*(i-1)+j]:=MasByte[71-8*j]
                   end;
               T[0] := ord(Password[k]);
               if k < length(Password) then inc(k) else k := 1;
               for i:= 1 to 64 do
                 begin
                   NowPos := 100*Position/DirInfo.Size;
                   inc(Position, 2);
                   If NowPos > 100 then NowPos := 100;
                   Str(Round(NowPos):3, Pos);
                   if OptInd = 0 then
                     begin
                       GoToXY(77, 1);
                       Write(Pos + '%');
                     end;
                   T[i] := (A * T[i-1] + C) mod M;

                   Code:=Mas[i];
                   Code:=T[i] xor Code;
                   Mas[i] := Code;
                 end;
               MasEnd := Mas;
               for i := 1 to 64 do Write(OutF, MasEnd[i]);
             end;
           until eof(InpF);
               GotoXY(77, 1);
               write('100%');
               MyMessageBox('Файл '+ InputFileName + ' расшифрован в ' +
                        OutputFileName, nil, mfInformation+mfOkButton);
           Close(InpF);
           if OptFile = 1 then Erase(InpF);
           Close(OutF);
         end
           else  MyMessageBox('Файл '+ InputFileName + ' не существует!',
                    nil, mfInformation+mfOkButton);

         end
       else MyMessageBox('      Ошибка ввода пароля!!!', nil,
                         mfError+mfOkButton);
     end
   else MyMessageBox('          Файл не выбран!!!', nil,
                     mfError+mfOkButton);
 end;


 {Опции криптографии}
 constructor TOptions.Init;
 var
   R    : TRect;
   Q, Q1: PView;
   Butt : TRadioButtons;
 begin
   R.Assign(0, 0, 60, 11);
   inherited Init(R, 'Криптография');
   Options := Options or ofCentered;

   R.Assign(10, 8, 20, 10);
   Insert(New(PButton, Init(R, '~А~га', cmOK, bfDefault)));


   R.Assign(40, 8, 50, 10);
   Insert(New(PButton, Init(R, '~Н~ека', cmCancel, bfNormal)));

   R.Assign(2, 2, 25, 3);
   Insert(New(PLabel, Init(R, 'Исходный файл:', Q)));

   R.Assign(5, 4, 21, 6);
   Q:=New(PRadioButtons, Init(R,
     NewSItem('~Н~е удалять',
     NewSItem('~У~далять', nil))));
   Insert(Q);

   R.Assign(27, 2, 45, 3);
   Insert(New(PLabel, Init(R, 'Индикатор:', Q1)));

   R.Assign(30, 4, 50, 6);
   Q1:=New(PRadioButtons, Init(R,
     NewSItem('~В~ысвечивать',
     NewSItem('~Н~е высвечивать', nil))));
 Insert(Q1);
 end;

 {Изменение пароля на вход в систему}
 procedure Passwords;
 var
   Ps, Ps1: string;
   I      : byte;
   tmp    : char;
 begin
   Ps := '';
   Ps1 := '';
   InputBox('П А Р О Л Ь', 'Введите пароль:', Ps, 255);
   for i:= 1 to length(Ps) do Ps[i] :=chr(ord(Ps[i]) xor 27);
   if Ps <> Pass then
     begin
       MyMessageBox('        Неверный пароль!!!', nil, mfError+mfOkButton);
       ClrScr;
       writeln('Несанкционированный доступ!');
       Halt;
     end;
   InputBox('И З М Е Н Е Н И Е   П А Р О Л Я',
      'Введите новый пароль:', Ps, 255);
   InputBox('И З М Е Н Е Н И Е   П А Р О Л Я',
      '      Повторите ввод:', Ps1, 255);
   if (Ps = Ps1) and (Ps <> '') then
     begin
       Assign(FilePass, 'system.res');
       Rewrite(FilePass);
       for i := 1 to length(PS) do
         begin
           tmp := chr(ord(Ps[i]) xor 27);
           Write(FilePass, tmp);
         end;
       Close(FilePass);
     end
      else    MyMessageBox('         Ошибка    ввода    пароля!!!',    nil,
 mfError+mfOkButton);

 end;

 {Обработка ошибок}
 procedure CheckExec;
 var
   St: string;
 begin
   Str(DOSError, St);
   case DOSError of
      2: MyMessageBox('          Ошибка DOS  № ' +
           St + '         "Файл не найден"',
           nil, mfError + mfOkButton);
      3: MyMessageBox('          Ошибка DOS  № ' +
           St + '      "Путь не найден"',
           nil, mfError + mfOkButton);
      5: MyMessageBox('          Ошибка DOS  № ' +
           St + '"Неверный код доступа к файлу"',
           nil, mfError + mfOkButton);
      6: MyMessageBox('          Ошибка DOS  № ' +
           St + '"Неверный код системного обработчика файла"',
           nil, mfError + mfOkButton);
      8: MyMessageBox('          Ошибка DOS  № ' +
           St + '         "Недостаточно памяти"',
           nil, mfError + mfOkButton);
     10: MyMessageBox('          Ошибка DOS  № ' +
           St + '            "Неверная среда"',
           nil, mfError + mfOkButton);
     11: MyMessageBox('          Ошибка DOS  № ' +
           St + '       "Неправильный формат"',
           nil, mfError + mfOkButton);
     18: MyMessageBox('          Ошибка DOS  № ' +
           St + '"Нет свободных обработчиков для файлов"',
           nil, mfError + mfOkButton);
   end;
 end;

 procedure MakeComFile(k: byte);
 const
     S      :   array   [1..4]   of    string    =    ('c:\sub_rosa\plus.',
 'c:\sub_rosa\passw.',
                                                      'c:\sub_rosa\block.',
 'c:\sub_rosa\keydisk.');
   Size : array [1..4] of word = (1068, 204, 617, 2118);
   Inden: array [1..4, 1..3] of byte = ((ord('ы'), 26      , ord('Р')),
                                        (ord('ы'), 39      , ord('Р')),
                                        (ord('щ'), ord('Й'), ord('[pic]')),
                                        (ord('щ'), ord('А'), ord('')));
 var
   I, Tmp           : byte;
   F                : array [1..4, 1..2] of file ;
   M                : array [1..2200] of byte ;
 NumRead, NumWritten: Word;

 begin
   assign(F[k, 1], S[k]); reset(F[k, 1], 1);
   assign(F[k, 2], S[k]+'com'); rewrite(F[k, 2], 1);
   for i := 1 to 3 do
     begin
       BlockRead(F[k, 1], tmp, 1, NumRead);
       BlockWrite(F[k, 2], Inden[k, i], 1, NumWritten);
     end;
   BlockRead(F[k, 1], M, Size[k]-3, NumRead);
   BlockWrite(F[k, 2], M, Size[k]-3, NumWritten);
   close(F[k, 1]); close(F[k, 2]);
 end;

 procedure DelComFile(k: byte);
 const
 {  S: array [1..4] of string =
      ('plus.com', 'passw.com', 'block.com', 'keydisk.com');}
 S    : array [1..4] of string = ('c:\sub_rosa\plus.com',
                                  'c:\sub_rosa\passw.com',
                                  'c:\sub_rosa\block.com',
                                  'c:\sub_rosa\keydisk.com');
 var
   F: array [1..4] of file;
 begin
   Assign(F[k], S[k]);
   Erase(F[k]);
 end;

 {**************************************************************************
 **}
 {*----------=========== Д О П И С А Т Ь   К   Ф А Й Л У ==========---------
 -*}
 {**************************************************************************
 **}
 procedure Plus(WhatDo: string);
 var
   FileStr, Err: string;
   CmdLine     : string;
   I           : byte;
   FileName    : FNameStr;
   Regs        : Registers;
 begin
   {Проверка условий}
   if Length(FName) > 3 then
     begin
       if (copy(FName, length(FName)-2, 3) = 'EXE') or
         (copy(FName, length(FName)-2, 3) = 'COM')
         then
           begin
             {Преобразование имени файла}
             for i:= length(fname) downto 1 do
               if fname[i] = '\' then
                 begin
                   CmdLine := copy(FName, i+1, length(FName) - i);
                   break;
                 end;
             for i := 1 to length(CmdLine) do
               if CmdLine[i] in ['A'..'Z'] then
                 CmdLine[i] := chr(ord(CmdLine[i]) + 32);
             for i := 1 to length(MainDir) do
               if MainDir[i] in ['A'..'Z'] then
                 MainDir[i] := chr(ord(MainDir[i]) + 32);
             MakeComFile(1);
             If WhatDo = SetPass then MakeComFile(2);
             If WhatDo = KeyDisk then MakeComFile(4);
             {Выполнить дописывание}
             SwapVectors;
             Exec( MainDir + 'plus.com  ',  CmdLine  +  '  '  +  MainDir  +
 WhatDo);
             SwapVectors;
             DelComFile(1);
             If WhatDo = SetPass then DelComFile(2);
             If WhatDo = KeyDisk then DelComFile(4);
             {Обработчик ошибок}
             if DosError <> 0 then
               CheckExec
             else
               begin
                 regs.ah := $4D;
                 with regs do
                 msdos(regs);
                 case Regs.AH of
                    0 : MyMessageBox(' Файл ' + FName + ' защищен.',
                          nil, mfInformation + mfOkButton);
                    1 : MyMessageBox('      Ctrl-C или Ctrl-Break.',
                          nil, mfError + mfOkButton);
                    2 : MyMessageBox('   Критическая ошибка устройства.',
                          nil, mfError + mfOkButton);
                    3 : MyMessageBox('        TSR - программа.',
                          nil, mfError + mfOkButton);
                 end;
               end;
           end
         else MyMessageBox('     Ошибка выбора файла !!! ',
                nil, mfError + mfOkButton);
     end
   else MyMessageBox('          Файл не выбран!!! ',
          nil, mfError + mfOkButton);
 end;

 {**************************************************************************
 **}
 {*----------===== Б Л О К И Р О В К А   В И Н Ч Е С Т Е Р А ======---------
 -*}
 {**************************************************************************
 **}
 procedure LockDisk;
 label
   end_;
 var
   Regs: registers;
   Err : string;
   Inst: byte;
 begin
   {Проверка наличи программы в памяти}
   asm
                 push    ax
                 push    dx
                 mov     Inst, 0
                 mov     ax,1059h
                 mov     dx,2517h
                 int     13h

                 cmp     ax,2517h
                 jne     End_
                 cmp     dx,1059h
                 jne     End_
                 mov     Inst, 1
     End_:       pop     dx
                 pop     ax
   end;
   if Inst = 0 then
     begin
       MakeComFile(3);
       {Установить защиту}
       SwapVectors;
       SetIntVec($09, Int09_Save);
       Exec(MainDir + 'block.com', '');
       GetIntVec($09, Int09_Save);
       SwapVectors;
       {Обраюотчик ошибок}
       if DosError <> 0 then
         CheckExec
       else
         begin
           regs.ah := $4D;
           with regs do
           msdos(regs);
           case Regs.AH of
              0 : MyMessageBox('     Ненормальное завершение.',
                    nil, mfError + mfOkButton);
              1 : MyMessageBox('      Ctrl-C или Ctrl-Break.',
                    nil, mfError + mfOkButton);
              2 : MyMessageBox('   Критическая ошибка устройства.',
                    nil, mfError + mfOkButton);
              3 : MyMessageBox('      Винчестер блокирован.',
                    nil, mfInformation + mfOkButton); { TSR }
           end;
         end;
     end
   else MyMessageBox('       Защита уже установлена.',
          nil, mfError + mfOkButton);
 end;


 {Изменить стандартную палитру}
 function TDirDialog.GetPalette: PPalette;
 const
   {Синяя палитра}
                               CMyCluster                                 =
 #64#65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80#81#82+
                    #83#84#85#86#87#88#89#90#91#92#93#94#95;
   P: string [32] = CMyCluster;
 begin
   GetPalette := @P;
 end;

 {Окно работы с каталогами}
 constructor TMyChDirDialog.Init(AOptions: Word; HistoryId: Word);
 var
   R        : TRect;
   ScrollBar: PScrollBar;
   CurDir   : DirStr;
 begin
   { Создание окна }
   R.Assign(16, 2, 64, 20);
   TDialog.Init(R, 'Изменить катлог');
   Options := Options or ofCentered;

   { Строка ввода имени каталога }
   R.Assign(3, 3, 30, 4);
   DirInput := New(PInputLine, Init(R, 68));
   Insert(DirInput);
   R.Assign(2, 2, 17, 3);
   Insert(New(PLabel, Init(
                 R, '~И~мя каталога', DirInput)));

   { Список каталогов }
   R.Assign(32, 6, 33, 16);
   ScrollBar := New(PScrollBar, Init(R));
   Insert(ScrollBar);
   R.Assign(3, 6, 32, 16);
   DirList := New(PDirListBox, Init(R, ScrollBar));
   Insert(DirList);
   R.Assign(2, 5, 19, 6);
   Insert(New(PLabel, Init(
                 R, '~Д~ерево каталогов', DirList)));

   { Формирование кнопок }
   R.Assign(35, 6, 45, 8);
   OkButton := New(PButton, Init(
         R, '~А~га', cmOK, bfDefault));
   Insert(OkButton);
   Inc(R.A.Y,3); Inc(R.B.Y,3);
   ChDirButton := New(PButton, Init(
         R, '~С~мена', cmChangeDir, bfNormal));
   Insert(ChDirButton);
   Inc(R.A.Y,3); Inc(R.B.Y,3);
   Insert(New(PButton, Init(
         R, '~Н~ека', cmCancel, bfNormal)));

   if AOptions and cdNoLoadDir = 0 then SetUpDialog;
   SelectNext(False);
 end;

 procedure TMyChDirDialog.SetUpDialog;
 var
   CurDir: DirStr;
 begin
   if DirList <> nil then
     begin
       CurDir := GetCurDir;
       DirList^.NewDirectory(CurDir);
       if (Length(CurDir) > 3) and (CurDir[Length(CurDir)] = '\') then
         CurDir := Copy(CurDir,1,Length(CurDir)-1);
       if DirInput <> nil then
         begin
           DirInput^.Data^ := CurDir;
           DirInput^.DrawView;
         end;
     end;
 end;

 function TMyChDirDialog.Valid(Command: Word): Boolean;
 var
   P: PathStr;
 begin
   Valid := True;
   if Command = cmOk then
     begin
       P := FExpand(DirInput^.Data^);
       if (Length(P) > 3) and (P[Length(P)] = '\') then
         Dec(P[0]);
       {$I-}
       ChDir(P);
       if IOResult <> 0 then
         begin
           MyMessageBox('      Неправильный каталог!',
             nil, mfError + mfOkButton);
           Valid := False;
         end;
       {$I+}
     end;
 end;


 {Инициализировать рабочее поле}
 constructor TMyBackground.Init(var Bounds: TRect; AText: TTitleStr);
 begin
   inherited Init(Bounds, ' ');
   Text := AText;
   while Length(Text) < SizeOf(TTitleStr) - 1 do
     Text := Text + AText;
 end;

 procedure TMyBackground.Draw;
 var
   DrawBuffer: TDrawBuffer;
 begin
   MoveStr(DrawBuffer, Text, GetColor(1));
   WriteLine(0, 0, Size.X, Size.Y, DrawBuffer);
 end;

 procedure TMyDesktop.InitBackground;
 var
   R: TRect;
 begin
   GetExtent(R);
   Background := New(PMyBackground, Init(R, '___'));
 end;

 {Изменить стандартную палитру}
 function TMyStaticText.GetPalette: PPalette;
 const
   {Синяя палитра}
                               CMyCluster                                 =
 #64#65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80#81#82+
                    #83#84#85#86#87#88#89#90#91#92#93#94#95;
   P: string [32] = CMyCluster;
 begin
   GetPalette := @P;
 end;


 {Окно "О Программе"}
 constructor TAboutBox.Init;
 var
   R: TRect;
 begin
   R.Assign(0, 0, 30, 16);
   inherited Init(R, 'О программе');
   Options := Options or ofCentered;

   R.Assign(10, 13, 20, 15);
   Insert(New(PButton, Init(R, '~А~га', cmOK, bfDefault)));

   R.Assign(11, 2, 19, 3);
   Insert(New(pMyStaticText, Init(R, 'Sub Rosa')));

   R.Assign(1, 4, 29, 5);
   Insert(New(pStaticText, Init(R, 'Система защиты данных от НСД')));

   R.Assign(5, 5, 29, 6);
   Insert(New(pStaticText, Init(R, 'выполнена  учащимися')));

   R.Assign(10, 6, 29, 7);
   Insert(New(pStaticText, Init(R, 'гр. 4641')));

   R.Assign(6, 7, 29, 8);
   Insert(New(pStaticText, Init(R, 'Егановым  Максимом')));

   R.Assign(14, 8, 22, 9);
   Insert(New(pStaticText, Init(R, 'и')));

   R.Assign(6, 9, 29, 10);
   Insert(New(pStaticText, Init(R, 'Юзефовичем Артемом')));

   R.Assign(6, 11, 29, 12);
   Insert(New(pStaticText, Init(R, 'МГВРК, Минск, 1996')));
 end;

 {Работа программы начинается здесь...}
 constructor TMyApp.Init;
 var
   ReturnVal, i                : Word;
   DirInfo, DirInfo1, DirInfo2 : SearchRec;
   DirInfo3, DirInfo4, DirInfo5: SearchRec;
   Pas                         : string;
   st                          : char;
 begin
   OptInd := 1;
   {Инициализировать файл ресурсов}
   MyRes.Init(New(PBufStream, Init('Setup.res', stOpen, 1024)));
   if MyRes.Stream^.Status <> stOK then
     begin
       Write('Нарушение целостности!');
       halt(1);
     end;
   RegisterType(RMenuBar);
   {Проверить целостность системы}
   MainDir := GetCurDir;
   FindFirst('plus',    AnyFile, DirInfo);
   FindFirst('passw',   AnyFile, DirInfo1);
   FindFirst('block',   AnyFile, DirInfo2);
   FindFirst('keydisk', AnyFile, DirInfo3);
   FindFirst('setup.res',   AnyFile, DirInfo4);
   if (DOSError = 0) and (DirInfo.Size = 1068) and  (DirInfo1.Size  =  204)
 and
      (DirInfo2.Size = 617) and (DirInfo3.Size = 2118) and
      (DirInfo4.Size = 522) then
     begin
       {Получить пароль}
       Assign(FilePass, 'system.res');
       Reset(FilePass);
       Pass := '';
       while not EOF(FilePass) do
         begin
           read(FilePass, st);
           Pass := Pass + st;
         end;
       Close(FilePass);
       {Инициализировать систему}
       TApplication.Init;
       Pas := '';
       ReturnVal := ExecuteDialog(New(PAboutBox, Init), nil);
       InputBox('П А Р О Л Ь', 'Введите пароль:', Pas, 255);
       for i:= 1 to length(Pas) do Pas[i] :=chr(ord(Pas[i]) xor 27);
       if Pas <> Pass then
         begin
               MyMessageBox('            Неверный     пароль!!!',      nil,
 mfError+mfOkButton);
           ClrScr;
           writeln('Несанкционированный доступ!');
           Halt;
         end;
     end
   else
     begin
       writeln('Нарушение целостности!');
       Halt;
     end;
 end;

 {Завершение работы}
 destructor TMyApp.Done;
 begin
   TApplication.Done;
   MyRes.Done;
 end;


 {Обработка событий}
 procedure TMyApp.HandleEvent(var Event: TEvent);
   procedure ChangeDir;
   var
     D: PMyChDirDialog;
   begin
     D:= New(PMyChDirDialog, Init(cdNormal, 101));
     ExecuteDialog(D, nil);
   end;

 var
   ReturnVal: Word;
   regs     : Registers;
   R        : TRect;
 begin
   inherited HandleEvent(Event);
   case Event.What of
     evCommand:
       begin
         case Event.Command of
           cmAboutBox  : ReturnVal :=
                           ExecuteDialog(New(PAboutBox, Init), nil);
           cmOpen      : FileOpen('*.*');
           cmChangeDir : ChangeDir;
           cmSetPass   : Plus(SetPass);
           cmKeyDisk   : Plus(KeyDisk);
           cmCode      : Shifr(FName);
           cmDeCode    : DeShifr(FName);
           cmLockDisk  : LockDisk;
           cmOptions   : ReturnVal :=
                           ExecuteDialog(New(POptions, Init), @OptFile);
           cmPasswords : Passwords
         end;
         ClearEvent(Event);
       end;
   end;
 end;

 {Инициализировать меню}
 procedure TMyApp.InitMenuBar;
 var
   R: TRect;
 begin
   {Получить меню из файла ресурсов по ключу "Config" - функция получения}
   {даты BIOS; модуль SetConf}
   MenuBar := PMenuBar(MyRes.Get(Config));
   if MenuBar = nil then
     begin
       Write(' Нелегальная копия!!!');
       halt(1);
     end;
 end;

 {Инициализировать рабочее поле}
 procedure TMyApp.InitDesktop;
 var
   R: TRect;
 begin
   GetExtent(R);
   R.Grow(0, -1);
   Desktop := New(PMyDesktop, Init(R));
 end;

 {Инициализировать строку состояния}
 procedure tMyApp.InitStatusLine;
 var
   R: tRect;
 begin
   GetExtent(R);
   R.A.Y:= R.B.Y - 1;
   StatusLine:= New(pStatusLine, Init(R,
   NewStatusDef(0, $FFFF,
     NewStatusKey('~F1~ О программе', kbF1, cmAboutBox,
     NewStatusKey('~F3~ Файл', kbF3, cmOpen,
     NewStatusKey('~F5~ Пароль', kbF10, cmMenu,
     NewStatusKey('~F9~ Настройки', kbF9, cmOptions,
     NewStatusKey('~F10~ Меню', kbF10, cmMenu,
     NewStatusKey('~Alt-X~ Выход', kbAltX, cmQuit,
     nil)))))),
   nil)));
 end;

 {Изменить основную палитру}
 function TMyApp.GetPalette: PPalette;
 const
   P: Array [apColor..apMonochrome] of string[Length(CAppColor)] =
        (CAppColor, CAppBlackWhite, CAppMonochrome);
 begin
   P[apColor, 50] := #$11; {1F}
   P[apColor, 51] := #$11; {2F}
   P[apColor,  1] := #$21; {71}
   GetPalette := @P[AppPalette];
 end;

 {Изменить палитру окна выбора файлов}
 function TMyFDialog.GetPalette: PPalette;
 const
   {Синяя палитра}
                               CMyCluster                                 =
 #64#65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80#81#82+
                    #83#84#85#86#87#88#89#90#91#92#93#94#95;
   P: string [32] = CMyCluster;
 begin
   GetPalette := @P;
 end;

 {Инициализировать окно выбора файлов}
 constructor TMyFileDialog.Init(AWildCard: tWildStr;
               const ATitle, InputName: string;
               AOptions: Word; HistoryId: Byte);
 var
   ScrollBar: PScrollBar;
   R        : TRect;
 begin
   { Создание окна диалога }
   R.Assign(15, 1, 64, 20);
   TDialog.Init(R, ATitle);
   Options:= Options or ofCentered;
   WildCard:= AWildCard;

   { Строка ввода имени файла }
   R.Assign(3, 3, 31, 4);
   FileName:= New(PFileInputLine, Init(R, 79));
   FileName^.Data^:= WildCard;
   Insert(FileName);
   R.Assign(2, 2, 6, 3);
   Insert(New(PLabel, Init(R, InputName, FileName)));
   R.Assign(31, 3, 34, 4);
   Insert(New(PHistory, Init(R, FileName, HistoryId)));

   { Линейка скроллинга и список файлов }
   R.Assign(3, 14, 34, 15);
   ScrollBar:= New(PScrollBar, Init(R));
   Insert(ScrollBar);
   R.Assign(3, 6, 34, 14);
   FileList:= New(PFileList, Init(R, ScrollBar));
   Insert(FileList);
   R.Assign(2, 5, 8, 6);
   Insert(New(PLabel, Init(R, 'Файлы', FileList)));

   { Задание кнопок }
   R.Assign(35, 3, 46, 5);
   if AOptions and fdOpenButton <> 0 then
     begin
       Insert(New(PButton, Init(
                 R, 'Открыть', cmFileOpen, bfDefault)));
       Inc(R.A.Y,3); Inc(R.B.Y,3);
     end;
   if AOptions and fdOkButton <> 0 then
     begin
       Insert(New(PButton, Init(
                 R, 'Ага', cmFileOpen, bfNormal)));
       Inc(R.A.Y,3); Inc(R.B.Y,3);
     end;
   if AOptions and fdReplaceButton <> 0 then
     begin
       Insert(New(PButton, Init(
                 R, 'Замена',cmFileReplace, bfNormal)));
       Inc(R.A.Y,3); Inc(R.B.Y,3);
     end;
   if AOptions and fdClearButton <> 0 then
     begin
       Insert(New(PButton, Init(
                 R, 'Удал.',cmFileClear, bfNormal)));
       Inc(R.A.Y,3); Inc(R.B.Y,3);
     end;
   Insert(New(PButton, Init(
                 R, 'Нека', cmCancel, bfNormal)));

   { Информационная панель с параметрами файла }
   R.Assign(1, 16, 48, 18);
   Insert(New(PFileInfoPane, Init(R)));

   SelectNext(False);

   { Загрузка каталога }
   if AOptions and fdNoLoadDir = 0 then
     begin
       FileList^.ReadDirectory(WildCard);
       Directory:= NewStr(GetCurDir);
     end;
 end;

 Var
   MyApp: TMyApp;  {Переменная основного объекта}

 Begin
   WriteLn('Система защиты данных от НСД. Версия 1.0 beta.'+
          +' 1996 МГВРК Еганов М. Ю., Юзефович А. Г.');
   GetIntVec($09,Int09_Save);
   MyApp.Init;
   MyApp.Run;
   MyApp.Done;
   SetIntVec($09, Int09_Save);
 End.



                                Приложение 2
                              Листинг библиотек



 {**************************************************************************
                                     *}
 {**************************************************************************
                                     *}
                                     {**
                                     **}
             {**                       КП "ЗАЩИТА ДАННЫХ ОТ НСД"
                                     **}
         {**                Выполнил учащийся гр.46491 ЕГАНОВ МАКСИМ
                                     **}
                   {**                               1996
                                     **}
                                     {**
                                     **}
               {**                      Программа инсталляции
                                     **}
 {**************************************************************************
                                     *}
 {**************************************************************************
                                     *}

 Program Install;

 Uses
   App, Dialogs, Drivers, Menus, MsgBox, Objects,
   Views, Memory, StdDlg, CRT, DOS, SetConf;

 Const {константы кодов команд}
   cmAboutBox  =  700;
   cmCode      = 1001;
   cmDeCode    = 1002;
   cmSetPass   = 1005;
   cmLockDisk  = 1006;
   cmOptions   = 1007;
   cmKeyDisk   = 1008;
   cmPasswords = 1009;

   RMenuBar: TStreamRec = (  {Запись для работы с потоком, TV}
     ObjType: 2000;
     VmtLink: Ofs(TypeOf(TMenuBar)^);
     Load: @TMenuBar.Load;
     Store: @TMenuBar.Store);

 Var
   Save23hInt : Pointer; {Переменные сохранения векторов прерываний}
   Save1bhInt : Pointer;
   MyApp      : TApplication;
   MyRes      : TResourceFile;
   MyStream   : PBufStream;

 {Формирование подменю "Файлы"}
 function MyStdFileMenuItems(Next: pMenuItem): pMenuItem;
 begin
   MyStdFileMenuItems:=
     NewItem('Выбрать...', 'F3', kbF3, cmOpen, hcOpen,
     NewItem('Сменить каталог...', '',
                 kbNoKey, cmChangeDir, hcChangeDir,
     NewLine(
     NewItem('Выход в ДОС', '', kbNoKey, cmDosShell, hcDosShell,
     NewItem('Завершение', 'Alt+X', kbAltX, cmQuit, hcExit,
     Next)))));
 end;

 {Формирование основного меню}
 procedure CreateMenuBar;
 var
   MenuBar: PMenuBar;
   R      : TRect;
 begin
   R.Assign(0, 0, 80, 1);
   MenuBar:= New(pMenuBar, Init(R, NewMenu(
     NewSubMenu('~Ф~айлы', hcNoContext, NewMenu(
       MyStdFileMenuItems(nil)),
     NewSubMenu('~З~ащита', hcNoContext, NewMenu(
        NewItem('~У~становить пароль', 'F5', kbF5, cmSetPass, 1005,
        NewItem('~Б~локировать винчестер', '', kbNoKey,  cmLockDisk,  1006,
 nil))),
     NewSubMenu('~К~лючевая дискета', hcNoContext, NewMenu(
        NewItem('~Д~обавить проверку по  ключу',  '',  kbNoKey,  cmKeyDisk,
 1008, nil)),
     NewSubMenu('~К~риптография', hcNoContext, NewMenu(
        NewItem('Зашифровать файл данных','', kbNoKey, cmCode, 1001,
        NewItem('Расшифровать файл  данных','',  kbNoKey,  cmDeCode,  1002,
 nil))),
     NewSubMenu('~Н~астройки', hcNoContext, NewMenu(
        NewItem('Криптография...','F9', kbF9, cmOptions, 1007,
        NewItem('Пароли...','F8', kbF8, cmPasswords, 1008, nil))),
     NewItem('~О~ программе', '', kbAltJ, cmAboutBox, 700, nil)))))))));
   MyRes.Put(MenuBar, Config);
   Dispose(MenuBar, Done);
 end;

 {Процедура управления формой курсора}
 procedure SetCursorSize(c_start,c_end:byte);
 var
    regs: registers;
 begin
   with regs do
     begin
       ah:=$01;
       ch:=c_start;
       cl:=c_end;
     end;
   intr($10,regs);
 end;

 {Процедура замены вектора преываний}
 {$F+}
 procedure My23hInt;Interrupt;
 begin
 end;
 {$F-}

 {Процедура копирования файлов}
 procedure CopyFyle(FromCopy: string);
 const
   TempLength = 1125.28;
 var
    ToCopy                       : string;
    Source, Target            : file;
    NumRead, NumWrite: word;
    buf                                : string;
    TempPos, Temp         : real;
 begin
   {Открыть файлы}
   ToCopy := 'c:';
   ToCopy := ToCopy + copy(FromCopy, 3, length(FromCopy) - 2);
   assign(Source, FromCopy);
   assign(Target, ToCopy);
   reset(Source, 1);
   rewrite(Target, 1);
   Temp := 0;

   {Копировать}
   repeat
     BlockRead(Source, Buf, Sizeof(Buf)-1, NumRead);
     if FromCopy = 'a:\sub_rosa\sub_rosa.exe' then
       begin
         TempPos := 100*Temp/TempLength;
         Temp := Temp + 2.5;
         GotoXY(17, 25);
         if (TempPos > 98) and (TempPos < 100) then write('100.0 %')
           else write(TempPos: 4: 1, ' %');
       end;
     {Обработчик ошибок}
     if (NumRead<>Sizeof(Buf)-1) and (not EOF(Source)) then
       begin
         WriteLn;
         WriteLn('Ошибка чтения с диска');
         SetIntVec($23, Save23hInt);
         SetIntVec($1b, Save1bhInt);
         halt;
       end;
     BlockWrite(Target,Buf,NumRead,NumWrite);
     If NumRead<>NumWrite then
       begin
         WriteLn;
         WriteLn('На диске не хватает места для записи');
         SetIntVec($23, Save23hInt);
         SetIntVec($1b, Save1bhInt);
         halt;
       end;
   until NumRead=0;
   close(Source);
   close(Target);
 end;

 Var
   Directory: string; {Куда копировать}

 Begin {Основная часть программы}
   GetIntVec($23, Save23hInt); {Подменить вектора прерываний 23h, 1bh}
   GetIntVec($1b, Save1bhInt); {Отключение Ctrl-C или Ctrl-Break}
   SetIntVec($23, @My23hInt);
   SetIntVec($1b, @My23hInt);
   SetCursorSize(32, 0);
   {$I-}
   Directory:='c:\sub_rosa'; {Создать каталог для установки}
   MkDir(Directory);
   if IOResult <> 0 then {Обработчик ошибок}
     begin
       WriteLn('Система уже была инсталлирована');
       SetIntVec($23, Save23hInt);
       SetIntVec($1b, Save1bhInt);
       halt;
     end;
   {$I+}
   {Создать файл ресурсов с привязкой к уникальным параметрам BIOS}
    MyStream  :=  New(PBufStream,  Init('c:\sub_rosa\Setup.res',  stCreate,
 2048));
   MyRes.Init(MyStream);
   RegisterType(RMenuBar);
   CreateMenuBar;
   MyRes.Done;
   {Копировать файлы}
   CopyFyle('a:\sub_rosa\block.');
   CopyFyle('a:\sub_rosa\keydisk.');
   CopyFyle('a:\sub_rosa\plus.');
   CopyFyle('a:\sub_rosa\passw.');
   CopyFyle('a:\sub_rosa\system.res');
   GotoXY(1, 25);
   Write('Инсталлировано');
   CopyFyle('a:\sub_rosa\sub_rosa.exe');
   WriteLn;
   WriteLn('Система готова к работе');
   ChDir('c:\sub_rosa');
   Mem[$40:$1a]:=Mem[$40:$1c];
   {Восстановить вектора прерываний}
   SetIntVec($23, Save23hInt);
   SetIntVec($1b, Save1bhInt);
 End.
 {**************************************************************************
                                     *}
 {**************************************************************************
                                     *}
                                     {**
                                     **}
            {**                        КП "ЗАЩИТА ДАННЫХ ОТ НСД"
                                     **}
          {**             Выполнил учащийся гр.46491 ЕГАНОВ МАКСИМ
                                     **}
                   {**                               1996
                                     **}
  {**                                                                   **}
              {**                       Модуль привязки к BIOS
                                     **}
 {**************************************************************************
                                     *}
 {**************************************************************************
                                     *}

 Unit SetConf;
 Interface
   function config: string; {Дата BIOS}

 Implementation
   {Получить дату BIOS}
   function config: string;
   var
     conf, s: String;
     Control: char absolute $F000:$FFF5;
     i      :byte;
   begin
     Move(Control, s[1], 8);
     s[0] := #8;
     for i := 1 to length(s) do conf[i] := chr(ord(s[i]) + 5*i);
     conf[0] := #8;
     config := conf;
   end;
 End.

 {**************************************************************************
 **}
 {**************************************************************************
 **}
 {**
 **}
 {**                          КП      "ЗАЩИТА      ДАННЫХ      ОТ      НСД"
 **}
 {**                 Выполнил    учащийся    гр.46491    ЮЗЕФОВИЧ     АРТЕМ
 **}
 {**                                                                   1996
 **}
 {**
 **}
 {**                                  Дописывание          к          файлу
 **}
 {**************************************************************************
 **}
 {**************************************************************************
 **}
 code      segment public
      assume cs: code, ds: code, es: code, ss: code
      org  80h         ;Хвост команды
 dta  label      byte
 com_siz   db    ?
 probel    db    ?
 com_par   db    ?
      org  100h
 start:
           jmp   test_par
 type_t    db    ?          ;Тип расширения target
 len_s     dw    ?          ;Длина source_file
 len_t_1   dw    ?          ;Длина target_file
 len_t_2   dw    ?          ;Длина target_file
 hand_1    dw    ?                              ;Обработка source_file
 hand_2    dw    ?                              ;Обработка target_file
 NameTarOff dw   ?                              ;Смещение имени target_file
 NameSouOff dw   ?                              ;Смещение имени source_file
 ext_a     db    'com', 'exe'     ;Допустимые расширения
 mbad_use  db    10, 13
 syn       db    10, 13

 TEST_PAR:
      lea  si, dta+1        ;Далее идет проверка
 l_0:                                              ;параметров в командной
           cmp   byte ptr [si], 0Dh  ;строке
      je   c_syn
      cmp  byte ptr [si], '?'
      je   c_h
      cmp  byte ptr [si], ' '
      jne  not_prob
      inc  si
      jmp  short l_0
 c_syn:
           int   20h
 c_h:
           int   20h
 use:
           int   20h
 not_prob:
           mov   NameTarOff, si   ;1-ый параметр правильный ?
 l_1:
           cmp   byte ptr [si], 0Dh
           je    c_b_1_m_2
           cmp   byte ptr [si], ' '
           je    c_b_1
           cmp   byte ptr [si], '.'
           je    d_t_1
           inc   si
           jmp   short l_1
 c_b_1_m_2:
           jmp   use        ;Недопустимое расширение
 c_b_1:                                            ;у target_file
      jmp  use
 D_T_1:                                           ;Анализ расширения
           inc   si
           call  det_type
           pop   ax
           mov   type_t, al
           cmp   ax, 2
           je    C_B_1
           add   si, 3
           lea   cx, dta
           add   cl, byte ptr dta
           adc   ch, 0
           cmp   cx, si
           jbe   C_M_2
           mov   byte ptr [si], 0
 l_2:                                                   ;2-ой      параметр
 правильный ?
           inc   si
           cmp   cx, si
           jb    c_m_2
           cmp   byte ptr [si], ' '
           je    l_2
           mov   NameSouOff, si
 l_3:
           cmp   byte ptr [si], '.'
           je    d_t_2
           inc   si
           cmp   cx, si
           jb    c_b_2
           jmp   l_3                    ;Отсутствует source_file
 c_m_2:
           jmp   use
 d_t_2:
           inc   si
           call  det_type
           pop   ax
           cmp   ax, 0
           je    test_end
 c_b_2:
           jmp   use
 test_end:
           add   si, 2
           cmp   cx, si
           jb    c_b_2
           mov   byte ptr [si+1], 0

 OPEN_F:                                             ;Открыть,   определить
 длину
           mov   ah, 3dh                     ;и прочитать в буфер файл
           mov   al, 2                       ;source_file
           mov   dx, NameSouOff
           int   21h
           jnc   yes_open
           int   20h
 yes_open:                                         ;Определить длину
           mov   bx, ax
           mov   hand_2, ax
           mov   ah, 42h
           xor   cx, cx
           xor   dx, dx
           mov   al, 2
           int   21h
           jnc   yes_p_1
 cn_mov_2:
           int   20h
 yes_p_1:
           mov   word ptr len_s, ax
           mov   ah, 42h
           xor   cx, cx
           xor   dx, dx
           mov   al, 0
           int   21h
           jc    cn_mov_2
           mov   ah, 3Fh
           lea   dx, buff
           mov   cx, word ptr len_s
           int   21h
           jnc   open_targ
           int   20h

 OPEN_TARG                  ;Открыть target_file
           mov   ah, 3Dh
           mov   al, 2
           mov   dx, NameTarOff
           int   21h
           jnc   det_len_1
           int   20h
 det_len_1:
           mov   hand_1, ax
           mov   bx, hand_1
           mov   ah, 42h
           xor   cx, cx
           xor   dx, dx
           mov   al, 2
           int   21h
           jnc   rest_len
           jmp   cn_mov_1
 rest_len:
           mov   len_t_1, dx
           mov   len_t_2, ax

 TO_PROC:                         ;Если target_file - COM,
           cmp   type_t, 0              ;то CALL WR2COM.
           je    c_com                  ;Если target_file - EXE,
           call  wr2exe                 ;то CALL WR2EXE.
           jmp   short CLOSE_F
 c_com:
           call  wr2com

 CLOSE_F:                                          ;Закрыть файлы
           mov   ah, 3Eh                ;source_file и target_file
           mov   bx, hand_1
           int   21h
           jnc   cl_2
           int   20h
 cl_2:
           mov   ah, 3Eh
           mov   bx, hand_2
           int   21h
           jnc   OK
           int   20h
 OK:
           mov   ah, 9
           int   20h


 det_type proc                               ;Подпрограммы
           mov   bp, sp
           push  ax
           push  cx
           push  di
           xor   ax, ax
           lea   di, ext_a
 loo_1:
           push  si
           push  di
           mov   cx, 3
           repe  cmpsb
           jne   end_loo_1
           pop   di
           pop   si
           mov   [bp+2], ax
           jmp   d_ret
 end_loo_1:
           inc   al
           pop   di
           add   di, 3
           pop   si
           cmp   al, 2
           jb    loo_1
           mov   [bp+2], ax
 d_ret:
           pop   di
           pop   cx
           pop   ax
           ret
 det_type endp

  wr2exe   proc
           push  ax
           push  bx
           push  cx
           push  dx
           push  si
           push  di
           jmp   st_2exe
      hdr  label byte
           dw    ?
 PartPag   dw    ?
 PageCnt dw      ?
           dw    ?
 HdrSize   dw    ?
           dw    5 dup(?)
 ExeIP     dw    ?
 ReloCS    dw    ?
 len_hdr   equ   $-hdr            ;Команды, записываемые
 imit      label       byte                        ;в конец файла
           mov   ax, es                 ;Команды записи в стек
 I_1:                                              ;адреса начала EXE-файла
           add   ax, 0
           add   ax, 10h
           push  ax
 I_2:
           mov   ax, 0
           push  ax                     ;Команды пердачи управления
           mov   ax, 100h               ;source_file, как и для COM
           push  ax                                ;файла
           db    0C3h
 len_imit  equ   $-imit
 st_2exe:
           mov   ah, 42h                ;Читать заголовок EXE-файла
           mov   bx, hand_1             ;Установить указатель на
           xor   cx, cx                 ;начало файла
           xor   dx, dx
           mov   al, 0
           int   21h
           jc    cn_mov_1
           mov   ah, 3Fh
           lea   dx, hdr
           mov   cx, len_hdr
           int   21h
           jnc   prep_end
 cn_r_1:
           int   20h
 prep_end:                                           ;Настроить    команды,
 дописываемые
           mov   ax, ReloCS             ;в конец файла target_file
           mov   word ptr i_1[1], ax ;Записать в стек адреса
           mov   ax, ExeIP              ;начала EXE-файла
           mov   word ptr i_2[1], ax ;Передать управление файлу
           mov   cx, len_t_1            ;source_file по соглашениям
           mov   dx, len_t_2            ;системы DOS
           mov   si, cx                 ;Записать команды в конец
           mov   di, dx                      ;EXE-файла
           mov   ah, 42h
           mov   al, 0
           mov   bx, hand_1
           int   21h
           jnc   yes_wr
 cn_mov_1:
           int   20h
 yes_wr:
           mov   ah, 40h
           lea   dx, imit
           mov   cx, len_imit
           int   21h
           jnc   wr_sour
 cn_w_1:
           int   20h
 wr_sour:                                          ;Записать source_file  в
 конец
           mov   cx, si                      ;EXE-файла
           mov   dx, di
           add   dx, len_imit
           jnc   m1
           inc   cx
 m1:
           add   dx, 15
      jnc  m2
           inc   cx
 m2:
           and   dx, 0FFF0h
           mov   si, cx
           mov   di, dx
           mov   ah, 42h
           mov   al, 0
           int   21h
           jc    cn_mov_1
           mov   ah, 40h
           lea   dx, buff
           mov   cx, len_s
           int   21h
           jc    cn_w_1
           mov   ax, si
           mov   bx, di
           add   bx, ax
           mov   cl, 4
           ror   bx, cl
           sub   bx, 10h
           sub   bx, HdrSize
           mov   ReloCS, bx
           mov   ax, PartPag
           and   ax, 000Fh
           mov   bx, ax
           add   ax, len_imit
           add   ax, 15
           and   ax, 0FFF0h
           add   bx, 100h
           sub   bx, ax
           mov   ExeIP, bx
           mov   ax, si
           mov   bx, di
           add   bx, len_s
           jnc   m3
           inc   ax
 m3:
           mov   dx, bx
           and   dx, 1FFh
           mov   PartPag, dx
           add   bx, 511
           jnc   m4
           inc   ax
 m4:
           and   bh, 0FEh
           mov   ah, bh
           mov   cl, 9
           ror   ax, cl
           mov   PageCnt, ax            ;Записать настроенный
           mov   ah, 42h                                ;заголовок в начало
 EXE-файла
           mov   bx, hand_1
           xor   cx, cx
           xor   dx, dx
           mov   al, 0
           int   21h
           jnc   write_1
           jmp   cn_mov_1
 write_1:
           mov   ah, 40h
           lea   dx, hdr
           mov   cx, len_hdr
           int   21h
           jnc   m_ret
           jmp   cn_w_1
 m_ret:
           pop   di
           pop   si
           pop   dx
           pop   cx
           pop   bx
           pop   ax
           ret
 wr2exe    endp



 wr2com    proc                   ;Процедура дописывания в
                                                   ;конец COM-файла
           jmp   st_2com
 new_beg label   byte
           mov   ax, cs
 c_1:
           add   ax, 0
           push  ax
 c_2:
           mov   ax, 0
           push  ax
           db    0CBh
 len_new_beg equ $-new_beg
 com  label      byte
           mov   di, 100h
           push  cs
           pop   ds
 c_3:
           mov   ax, 0
 c_4:
           add   ax, 0
           and   AX, 000Fh
           mov   bx, 16
           sub   bx, ax
           and   bx, 000Fh
           add   bx, len_new_beg
           mov   ax, 100h
           sub   ax, bx
           mov   si, ax
           mov   cx, len_new_beg
 rep  movsb
           push  es
           pop   ds
           push  es
           mov   ax, 100h
           push  ax
           push  ax
           db    0C3h
 len_com equ $-com
 old_beg   label       byte
           db    len_new_beg dup(?)
  len_im   equ   $-com
 st_2com:
           mov   bx, hand_1
           mov   ah, 42h
           xor   cx, cx
           xor   dx, dx
           mov   al, 0
           int   21h
           jnc   read_beg
           jmp   cn_mov_2
 read_beg:
           mov   ah, 3Fh
           lea   dx, old_beg
           mov   cx, len_new_beg
           int   21h
           jnc   prep_beg
           jmp   cn_r_1
 prep_beg:
           mov   ax, len_t_1
           mov   bx, len_t_2
           add   bx, len_im
           jnc   pr1
           inc   ax
 pr1:
           add   bx, 15
           and   bx, 0FFF0h
           add   bx, ax
           mov   cl, 4
           ror   bx, cl
           mov   word ptr c_1[1], bx
           mov   ax, len_t_2
           and   ax, 000Fh
           mov   bx, ax
           add   ax, len_im
           add   ax, 15
           and   ax, 0FFF0h
           add   bx, 100h
           sub   bx, ax
           mov   word ptr c_2[1], bx
           mov   bx, hand_1
           mov   ah, 42h
           xor   cx, cx
           xor   dx, dx
           mov   al, 0
           int   21h        jnc   wr_beg
           jmp   cn_mov_2
 wr_beg:
           mov   ah, 40h
           lea   dx, new_beg
           mov   cx, len_new_beg
           int   21h
           jnc   prep_c_end
           jmp   cn_w_1
 prep_c_end:
           mov   ax, len_t_2
           mov   word ptr c_3[1], ax
           mov   word ptr c_4[1], len_im
           mov   bx, hand_1
           mov   ah, 42h
           mov   cx, len_t_1
           mov   dx, len_t_2
           mov   al, 0
           int   21h
           jnc   wr_end
           jmp   cn_mov_2
 wr_end:
           mov   ah, 40h
           lea   dx, com
           mov   cx, len_im
           int   21h
           jnc   cal_b
           jmp   cn_w_1
 cal_b:
           mov   cx, len_t_1
           mov   dx, len_t_2
           add   dx, len_im
           jnc   cal_1
           inc   cx
 cal_1:
           add   dx, 15
           jnc   cal_2
           inc cx
 cal_2:
           and   dx, 0FFF0h
           mov   bx, hand_1
           mov   ah, 42h
           mov   al, 0
           int   21h
           jnc   wr_sr
           jmp   cn_mov_2
 wr_sr:
           mov   ah, 40h
           lea   dx, buff
           mov   cx, len_s
           int   21h
           jnc   end_2com
           jmp   cn_w_1
 end_2com:
           ret
 wr2com endp
 buff      label       byte
 copyright db          'Copyright(C) Юзефович Артем ( МГВРК,'
      db         ' Минск ), 1996'
                 db         0Dh, 0Ah, 'Программа дописывания'
                 db         ' по вирусному принципу.', 0Dh, 0Ah
                 db         0Dh, 0Ah, 0Dh, 0Ah, '$'
 code      ends
 end  start

 {**************************************************************************
 **}
 {**************************************************************************
 **}
 {**
 **}
 {**                          КП      "ЗАЩИТА      ДАННЫХ      ОТ      НСД"
 **}
 {**                 Выполнил    учащийся    гр.46491    ЮЗЕФОВИЧ     АРТЕМ
 **}
 {**                                                                   1996
 **}
 {**
 **}
 {**                                     Пароль           на           файл
 **}
 {**************************************************************************
 **}
 {**************************************************************************
 **}
 сode      segment
           assume      cs: code, ds:code, es: code, ss: code
           org   100h
 start:    jmp   print
 enter_pas label       byte
           db    'E'+60h, 80h,'n'+60h, 80h,'t'+60h, 80h,'e'+60h, 80h
           db    'r'+60h, 80h
           db    80h, 80h, 80h
           db    'P'+60h, 80h,'a'+60h, 80h,'s'+60h, 80h,'s'+60h, 80h
            db     'w'+60h,  80h,'o'+60h,  80h,'r'+60h,  80h,'d'+60h,  80h,
 ':'+60h
           db    6Ah, 6Dh
 len_enter equ   $-enter_pas
 password label  byte
           db    'm'+60h, '&'+60h, 'a'+60h      ;Пароль m&a
 len_pas   equ   $-password             ;Счетчик повторов
 count_err equ   3
 buff      label       byte
           db    len_pas dup(?)
 print:
           push  es
           push  ds
           push  cs
           push  cs               ;Адресация регистров
           pop   es
            mov    cx,  count_err                            ;Инициализация
 счетчика
 pr_1:                                                  ;Печать приглашения
           mov   ah, 2
           mov   bx, 0
 pr_ent:
           mov   dl, enter_pas[bx]
           sub   dl, 60h
           int   21h
           inc   bx
           cmp   bx, len_enter
           jb    pr_ent
           push  cx
           mov   cx, len_pas                       ;Ввести пароль
           lea   di, buff
 rd_pass:
           mov   al, 7
           mov   ah, 0Ch
           int   21h
           stosb
           loop  rd_pass
           pop   cx
           mov   bx, 0
 cmp_p:
            mov    al,  password[bx]                   ;Сравнить  пароль  с
 введенным
           sub   al, 60h
           cmp   al, buff[bx]
           jne   repeat
           inc   bx
           cmp   bx, len_pas
           jb    cmp_p
 equal:
           pop   ds                                ;Пароль верный
           pop   es                                     ;Перейти к основной
           db    0CBh                                   ;программе
 repeat:
           loop  pr_1
 dos:
           jmp   cs_1
 ms_1      db    '*', 10, 13, '$'
 cs_1:
           mov   ah, 9                                  ;Пароль не верный
           lea   dx, ms_1
           int   21h                                    ;Вывести сообщение
           mov   ah, 4Ch
           int   21h                                    ;Выйти в DOS
 copyright db          'Copyright(C) Юзефович Артем ( МГВРК,'
                 db         ' Минск ), 1996'
                 db         0Dh, 0Ah, 'Запрос'
                 db         ' пароля.', 0Dh, 0Ah
                 db         0Dh, 0Ah, 0Dh, 0Ah, '$'
 code      ends
 end  start

 {**************************************************************************
 **}
 {**************************************************************************
 **}
 {**
 **}
 {**                          КП      "ЗАЩИТА      ДАННЫХ      ОТ      НСД"
 **}
 {**                 Выполнил    учащийся    гр.46491    ЮЗЕФОВИЧ     АРТЕМ
 **}
 {**                                                                   1996
 **}
 {**
 **}
 {**                                         Ключевая               дискета
 **}
 {**************************************************************************
 **}
 {**************************************************************************
 **}
 code      segment
           assume      cs: code, ds:code, es: code, ss: code
           org   100h       ;Счетчик команд-100h
 start:    jmp   print
 recsize   equ   512                               ;Размер сектора
 buffer    db    recsize dup(?)         ;Буферы ввода-вывода
 bufrez    db    recsize dup(?)
 buffer1   db    recsize dup(?)
 protect         label      byte
           db    'T'+60h,'h'+60h,'i'+60h,'s'+60h
           db    80h, 80h
           db    'i'+60h,'s'+60h
           db    80h, 80h
           db    'k'+60h,'e'+60h,'y'+60h
           db    80h, 80h
           db    'd'+60h,'i'+60h,'s'+60h,'k'+60h
 len_enter2 equ  $-protect              ;Длина сообщения

 dsk_key   label       byte
           db    'Э'+10h,'т'+10h,'о'+10h
           db    30h, 30h
           db    'н'+10h,'е'+10h
           db    30h, 30h
           db    'к'+10h,'л'+10h,'ю'+10h,'ч'+10h
           db    'е'+10h,'в'+10h,'а'+10h,'я'+10h
           db    30h, 30h
           db    'д'+10h,'и'+10h,'с'+10h,'к'+10h
           db    'е'+10h,'т'+10h,'а'+10h
           db    6Ah-50h, 6Dh-50h
 len_enter1 equ  $-dsk_key        ;Длина сообщения

 enter_pas label       byte
           db    'В'+10h, 30h,'с'+10h, 30h,'т'+10h, 30h,'а'+10h, 30h
           db    'в'+10h, 30h, 'ь'+10h, 30h, 'т'+10h, 30h, 'е'+10h, 30h
           db    30h, 30h, 30h
           db    'к'+10h, 30h,'л'+10h, 30h,'ю'+10h, 30h,'ч'+10h, 30h
           db    'е'+10h, 30h,'в'+10h, 30h,'у'+10h, 30h,'ю'+10h, 30h
           db    30h, 30h, 30h
           db    'д'+10h, 30h,'и'+10h, 30h,'с'+10h, 30h,'к'+10h, 30h
           db    'е'+10h, 30h,'т'+10h, 30h,'у'+10h, 30h
           db    30h, 30h, 30h
           db    'и'+10h
           db    30h, 30h, 30h
           db    'н'+10h, 30h,'а'+10h, 30h,'ж'+10h, 30h,'м'+10h, 30h
           db    'и'+10h, 30h,'т'+10h, 30h,'е'+10h, 30h
           db    30h, 30h
           db    'В'+10h, 'В'+10h, 'О'+10h, 'Д'+10h
           db    6Ah-50h, 6Dh-50h
 len_enter  equ  $-enter_pas      ;Длина сообщения
 print:
           push  es                          ;Сохранение регистров
           push  ds
           push  cs
           push  cs
           pop   ds                          ;cs=>ds
           pop   es                          ;cs=>es

           mov   ah, 2
           mov   bx, 0
 pr_ent:
           mov   dl, enter_pas[bx] ;Вывод сообщения
           sub   dl, 10h
           int   21h
           inc   bx
           cmp   bx, len_enter
           jb    pr_ent
           mov   ah, 08h                ;Ожидание нажатия Ввода
           int   21h
           mov   al, 0
           mov   cx, 1
           mov   dx, 1
           mov   bx, offset buffer
           int   25h        ; считали FAT
           pop   dx                          ;25h и 26h оставляют лишнее
           mov   al, 0                       ;слово в стеке, извлекаем его
           mov   cx, 1
           mov   dx, 1
           mov   bx, offset bufrez      ;Сохраняем резервную копию
           int   25h                         ;FAT
           pop   dx
           mov   bx, offset buffer      ;Процедура,которая определяет
           mov   ax, 118                     ;запись FAT по номеру сектора
           mov   cx, ax
           shl   ax, 1
           add   ax, cx
           test  ax, 1
           pushf
           shr   ax, 1
           add   bx, ax
           mov   ax, [bx]
           popf
           jnz   getFAT11
           and   ax, 0FFFh
           jmp   getFAT21

 getFAT11:
           shr   ax, 4
 getFAT21:
           cmp   ax, 0ff7h        ;1-ая проверка. BAD-?
           jne   no_disk1               ;НЕТ

           mov   bx, offset buffer      ;ДА
           mov   ax, 120
           mov   cx, ax
           shl   ax, 1
           add   ax, cx
           test  ax, 1
           pushf
           shr   ax, 1
           add   bx, ax
           mov   ax, [bx]
           popf
           jnz   getFAT111
           and   ax, 0FFFh
           jmp   getFAT212
 getFAT111:
           shr   ax, 4
 getFAT212:
           cmp   ax, 0ff7h        ;2-ая проверка. BAD-?
           jne   no_disk1               ;НЕТ
           jmp   f1
 no_disk1:
                 jmp   no_disk
 f1:

 good       macro        x,   y                          ;Макроопределение,
 которое
           mov   bx, offset buffer      ;помечает сектор, как
           mov   ax, x                       ;свободный(занятый, плохой)
           mov   cx, ax
           shl   ax, 1
           add   ax, cx
           test  ax, 1
           pushf
           shr   ax, 1
           add   bx, ax
           popf
           mov   ax, y
           mov   [bx], ax
      endm

      good       118, 0h                ;Пометить, как свободный
           good  120, 0h                    ;Пометить, как свободный

 fat  macro      b
           mov   al, 0
           mov   cx, 1
           mov   dx, 1
           mov   bx, offset b
           int   26h                         ;Записали 1-ую копию FAT
           pop   dx
      endm

           fat   buffer                      ;Запись FAT
           mov   al, 0
           mov   cx, 1
           mov   dx, 248
           mov   bx, offset buffer1
           int   25h                         ;Считываем сектор
           pop   dx

           mov   bx, 0
           mov   ax, 0
 pr_ent2:
           mov   dh, protect[bx]        ;3-яя проверка. Проверяется
           cmp   buffer1[bx], dh        ;наличие на диске
           jne   g1                          ;закодированной информации
           jmp   g2
 g1:
           inc   ax
 g2:
           inc   bx
           cmp   bx, len_enter2
           jb    pr_ent2
           cmp   ax, 0
           jne   no_disk
           mov   al, 0
           mov   cx, 1
           mov   dx, 244
           mov   bx, offset buffer
           int   26h                    ;Попытка записи на сектор
           pop   dx

           mov   al, 0
           mov   cx, 1
           mov   dx, 244
           mov   bx, offset buffer1
           int   25h                    ;Попытка чтения с сектора
           pop   dx

           cld                                          ;df=0
           lea   si, buffer
           lea   di, buffer1
           mov   cx, 512
           mov   ax, 0
 l:
           cmpsb                                   ;Сравнение записанной и
           jne   l1                          ;считаной информации
           jmp   l2
 l1:  inc  ax
 l2:  loop       l
           cmp   ax, 5
           jl    no_disk

           fat   bufrez                 ;Запись FAT
           pop   ds
           pop   es
           db    0cbh                   ;RetF. Перейти на программу

 no_disk:                                          ;Это не ключевая дискета
           mov   ah, 2
           mov   bx, 0
 pr_ent1:
           mov   dl, dsk_key[bx]  ;Вывод сообщения
           sub   dl, 10h
           int   21h
           inc   bx
           cmp   bx, len_enter1
           jb    pr_ent1

           fat   bufrez                 ;Запись FAT
           mov   ah, 4ch                ;Выход в DOS
           mov   al, 0
           int   21h

 copyright db          'Copyright(C) Юзефович Артем ( МГВРК,'
      db         ' Минск ), 1996'
                 db         0Dh, 0Ah, 'Ключевая'
                 db         ' дискета.', 0Dh, 0Ah
                 db         0Dh, 0Ah, 0Dh, 0Ah, '$'

 code      ends
 end  start

 ;**************************************************************************
 **
 ;**************************************************************************
 **
 ;**
 **
 ;**                          КП      "ЗАЩИТА      ДАННЫХ      ОТ      НСД"
 **
 ;**         Выполнили учащиеся гр.46491 ЕГАНОВ  МАКСИМ  и  ЮЗЕФОВИЧ  АРТЕМ
 **
 ;**                                                                   1996
 **
 ;**
 **
 ;**                                        Защита               винчестера
 **
 ;**************************************************************************
 **
 ;**************************************************************************
 **
 keybd_flags_1_  equ     417h                     ;Флаги клавиатуры
 data_10e        equ     0

 seg_a           segment byte public
                 assume  cs:seg_a, ds:seg_a


                 org     100h                     ;Счетчик команд

 Block           proc    far

 start:

                 jmp     real_start
 data_1          db      1
 data_2          dw      7241h, 6574h
 data_4          dw      2E6dh, 2020h
 data_6          dw      2020h, 2020h
 flag1           db      0
 flag2           db      0
 flag3           db      0
 allf            db      0
 nameF           db      'C:\sub_rosa\block.com', 0
 Block           endp

 int_09h_entry   proc    far                      ;Процедура обработки 09h
                 push    ax                       ;прерывания
                 push    ds
                 mov     al,cs:allf
                 xor     al,1
                 mov     cs:allf,al
                 jmp     k2
 k:
                 mov     cs:allf,1
 k2:
                  in       al,60h                    ;Обращение   к   порту
 клавиатуры
                 cmp     al,32h                   ;Проверка на нужную
                 je      l1                       ;комбинацию
                 cmp     al,08h
                 je      l2
                 cmp     al,1eh
                 je      l3
                 jmp     loc_1

 l1:
                 mov     cs:flag1,1
                 jmp     loc_2
 l2:
                 cmp     cs:flag1,0
                 je      loc_1
                 mov     cs:flag2,1
                 jmp     loc_2
 l3:
                 cmp     cs:flag2,0
                 je      loc_1
                 mov     cs:flag3,1
                 jmp     loc_2
 loc_1:
                 pop     ds
                 pop     ax
                 cmp     cs:allf,1
                 jne     r2
                 mov     cs:flag1,0
                 mov     cs:flag2,0
                 mov     cs:flag3,0
 r2:
                 jmp     dword ptr cs:data_2
 loc_2:
                 sub     ax,ax
                 mov     ds,ax
                 test    byte ptr ds:keybd_flags_1_,8
                 jz      loc_1                    ;Alt нажата ?
                 in      al,61h
                 mov     ah,al                    ;Слудующий код  необходим
 для
                 or      al,80h                   ;отработки аппаратного
                 out     61h,al                   ;прерывания
                 xchg    ah,al
                 out     61h,al

                 mov     al,20h                   ;Послать сигнал "конец
                 out     20h,al                   ;прерывания" контроллеру
                                                  ;прерываний 8259
                 push    bx
                 mov     ah,0Fh
                 int     10h                      ;Video display
                                                  ;ah=functn 0Fh
                                                   ;get   state,   al=mode,
 bh=page
                                                  ;ah=columns on screen
                 cmp     cs:flag1,1
                 jne     loc_6
                 cmp     cs:flag2,1
                 jne     loc_6
                 cmp     cs:flag3,1
                 jne     loc_6

                 cmp     al,1
                 je      loc_3                    ;Jump if equal
                 cmp     al,3
                 jne     loc_6                    ;Jump if not equal
 loc_3:
                 mov     ax,0B800h
                 mov     ds,ax                    ;Установка ключа проверки
                 mov     al,cs:data_1             ;для 13h прерывания
                 xor     al,1
                 mov     cs:data_1,al
                 test    al,1
                 jz      loc_4                    ;Jump if zero
                 mov     ax,7458h                 ;Вывод символа
                 jmp     short loc_5
                 db      90h
 loc_4:
                 mov     ax,744Fh                 ;Вывод символа
 loc_5:
                 mov     cs:flag1,0
                 mov     cs:flag2,0
                 mov     cs:flag3,0
                 mov     ds:data_10e,ax
 loc_6:
                 mov     cs:allf,1
                 pop     bx
                 pop     ds
                 pop     ax
                 iret                             ;Interrupt return
 int_09h_entry   endp


 int_2Fh_entry      proc       far                          ;Mультиплексное
 прерывание
                 cmp     ah,13h
                 je      loc_7                    ;Jump if equal
                 jmp     dword ptr cs:data_6
 loc_7:
                 mov     bx,0F000h
                 mov     es,bx
                 mov     bx,0FFF0h
                 mov     dx,bx
                 iret                             ;Interrupt return
 int_2Fh_entry   endp


 sub_1           proc    near
                 sub     ax,ax
                 mov     ds,ax
                 mov     ax,[bx+2]
                 mov     es,ax
                 mov     bx,[bx]
                 mov     byte ptr es:[bx],0CFh
                 retn
 sub_1           endp


 int_13h_entry   proc    far                      ;Процедура обработки 13h
                 cmp     ax,1059h                 ;прерывания
                 jne     loc_8                    ;Jump if not equal
                 cmp     dx,2517h
                 jne     loc_8                    ;Jump if not equal
                 xchg    dx,ax
                 iret                             ;Interrupt return
 int_13h_entry   endp

 loc_8:
                 test    cs:data_1,1              ;Проверка на ключ
                 jnz     loc_10                   ;Jump if not zero
 loc_9:
                  jmp      dword  ptr  cs:data_4       ;Вернуться   к   13h
 прерыванию
 loc_10:
                 push    ax
                 push    bx
                 push    ds
                 push    es
                 mov     bx,4
                 call    sub_1
                 mov     bx,0Ch
                 call    sub_1
                 pop     es
                 pop     ds                       ;Далее слудуют проверки
                 pop     bx                       ;функций 13h прерывания
                 pop     ax
                 cmp     ah,3
                 je      loc_11                   ;Jump if equal
                 cmp     ah,5
                 je      loc_11                   ;Jump if equal
                 cmp     ah,6
                 je      loc_11                   ;Jump if equal
                 cmp     ah,7
                 je      loc_11                   ;Jump if equal
                 cmp     ah,0Bh
                 je      loc_11                   ;Jump if equal
                 cmp     ah,1Ah
                 jne     loc_9                    ;Jump if not equal
 loc_11:
                 mov     dl,3
                 jmp     short loc_9

 real_start:
                 mov     ax,1059h                 ;Block уже загружен ?
                 mov     dx,2517h
                 int     13h

                 cmp     ax,2517h
                 jne     loc_12                   ;Jump if not equal
                 cmp     dx,1059h
                 jne     loc_12                   ;Jump if not equal

                 mov     ax,4C01h                 ;Выход в DOS
                 int     21h

 loc_12:
                 mov     ax,3509h
                 int     21h

                 mov     data_2,bx                ;Запомнить адрес 09h INT
                 mov     bx,es
                 mov     word ptr data_2+2,bx
                 mov     dx,offset int_09h_entry
                 mov     ax,2509h
                 int     21h                      ;Установка нового 09h INT

                 mov     ax,3513h
                 int     21h

                 mov     data_4,bx                ;Запомнить адрес 13h INT
                 mov     bx,es
                 mov     word ptr data_4+2,bx
                 mov     dx,offset int_13h_entry
                 mov     ax,2513h
                 int     21h                      ;Установка нового 13h INT

                 mov     ax,352Fh
                 int     21h

                 mov     data_6,bx                ;Запомнить адрес 2Fh INT
                 mov     bx,es
                 mov     word ptr data_6+2,bx
                 mov     dx,offset int_2Fh_entry
                 mov     ax,252Fh
                 int     21h                      ;Установка нового 2Fh INT
                                                     ;Необходимое     число
 параграфов
                                                  ;памяти
                 mov     cs:data_1, 0
                 mov     ah, 41h
                 push    cs
                 pop     ds
                 mov     dx, offset nameF
                 int     21h
                 mov     cs:data_1, 1
                 mov     dx,((offset pgm_len+15)/16)+10h
                 mov     ax,3100h                 ;Завершить и оставить
                 int     21h                      ;резидентным


 data_8          db      'Защита Винчестера. '

 copyright       db      'Copyright(C) Юзефович Артем ( МГВРК,'
                 db      ' Минск ), 1996'
                 db      0Dh, 0Ah, 'Винчестер'
                 db      ' блокирован.', 0Dh, 0Ah
                 db      0Dh, 0Ah, 0Dh, 0Ah, '$'

 pgm_len         equ     $-Block                  ;Длина программы
 seg_a           ends



                 end     start



                                Приложение 3
                           Пример работы программы



      В  качестве  примера  работы  программы  приведем  текстовый  файл  до
 зашифрования:
      “Sub Rosa - втайне (буквально: под розой).
      У  древних  римлян  роза была эмблемой тайны. Когда хозяин дома  вешал
 розу над  пиршественным  столом,  гости  знали, что все  сказанное  должно
 оставаться тайной.
      Впоследствии   изображение   розы   на    потолке    помещений,    где
 происходили совещания,  свидетельствовало   о   том,   что  все  сказанное
 здесь не должно быть разглашено.”
      и после зашифрования:

 9