Операционная система MS-DOS© Александр Фролов, Григорий ФроловТом 1, книга 3, М.: Диалог-МИФИ, 1992. 6.1. Ограничение доступа при загрузке MS-DOSОперационная система MS-DOS не содержит каких-либо средств разграничения доступа. Однако если компьютером пользуется несколько человек, или если возможен доступ к вашему компьютеру посторонних лиц, желательно использовать программу, запрашивающую пароль при загрузке операционной системы. Одним из примеров коммерческой системы разграничения доступа для MS-DOS может служить системный администратор ADM. Эта система обеспечивает разграничение доступа к отдельным логическим дискам для нескольких пользователей. Логический диск может быть предоставлен пользователю с правом на чтение, чтение/запись или полностью "спрятан" от пользователя. Для создания логических дисков используется нестандартная схема разделов диска, поэтому, загрузив операционную систему с дискеты, вы "увидите" только диск C:, остальные диски будут для вас недоступны. Системный администратор ADM в целом удовлетворяет требованиям защиты от НСД, но, к сожалению, в настоящее время эта система полностью исчерпала запас "секретности" - доступна информация о способах получения статуса привилегированного пользователя, которому предоставлены все логические диски. Имеется даже программа для удобного и легкого взламывания этой системы защиты. В ответственных случаях едва ли целесообразно использовать такие широко распространенные средства защиты от НСД, так как почти наверняка кто-то уже подобрал к ним ключи. В любом случае, эти ключи есть в руках фирмы-разработчика системы защиты. Как же можно доработать MS-DOS, для того, чтобы она обеспечивала ограничение доступа при загрузке? Для ответа на этот вопрос вспомним, как выполняется загрузка операционной системы. После тестирования аппаратуры и инициализации векторов прерываний BIOS происходит попытка выполнить чтение самого первого сектора на нулевой дорожке и нулевой стороне диска А: или, при отсутствии дискеты в дисководе А:, первого сектора нулевой дорожки нулевой стороны накопителя на жестком диске С:. В любом случае, содержимое сектора записывается в оперативную память по адресу 7C00:0000, после чего по этому же адресу передается управление. Если загрузка операционной системы выполняется с жесткого диска, считанный сектор содержит главную загрузочную запись - Master Boot Record и таблицу разделов диска. Идея заключается в замене программы загрузки, находящейся в главной загрузочной записи на свою, разработанную специальным образом - по аналогии с печально известным вирусом Stone. При установке системы защиты первый сектор, содержащий главную загрузочную запись, переписывается на другое место, например, во второй или третий сектор нулевой дорожки нулевой стороны. Это возможно, так как обычно на нулевой дорожке нулевой стороны используется только самый первый сектор. Таблица разделов, находящаяся в этом секторе, зашифровывается специальным системным паролем, доступным только системному программисту. В первый сектор (на место главной загрузочной записи) записывается специальная программа и таблица имен пользователей и их, разумеется зашифрованные, пароли. После передачи управления эта программа переписывает себя в другое место оперативной памяти и запрашивает имя и пароль пользователя. Если имя и пароль указаны правильно, программа считывает главную загрузочную запись в память по адресу 7C00:0000 и там (в памяти, а не на диске) расшифровывает таблицу разделов. После этого управление передается главной загрузочной записи по адресу 7C00:0000 и загрузка продолжается обычным образом. Теперь, если выполнить загрузку операционной системы с дискеты, разделы жесткого диска станут недоступны, так как, во-первых, таблица разделов находится в другом секторе диска, а во-вторых, она зашифрована. Используя указанную выше схему защиты от НСД, не забывайте о такой программе, как Norton Disk Doctor. Эта программа сможет восстановить и таблицу разделов, и корневые каталоги, и все остальное... Вы можете усложнить приведенную выше схему, добавив специальный драйвер. Этот драйвер, переназначив дисковые прерывания (INT 13h и INT 40h - используется MS-DOS вместо INT 13h) и прерывания для работы с каталогами, будет отслеживать все обращения к каталогам и расшифровывать их при необходимости. Однако при этом производительность системы может несколько снизиться. Если все, что вам нужно, это ограничить доступ к загрузке операционной системы с жесткого диска, вы можете использовать драйвер, который запрашивает пароль на стадии инициализации. Если пароль введен правильно, драйвер завершает работу без установки себя резидентно в памяти, вслед за чем продолжается обычная загрузка операционной системы. Приведем пример такого драйвера. Вы можете записать его на диск С: и первой строкой в файле CONFIG.SYS записать: device=c:\stop.sys Для продолжения загрузки введите пароль sys. .MODEL tiny .CODE ; Драйвер состоит из одного ; сегмента кода org 0 ; Эта строка может отсутствовать include sysp.inc ;=========================================================== stop PROC far ;драйвер - это FAR-процедура ;=========================================================== E_O_P: ;Метка конца программы, ;устанавливаем ее в начало ;драйвера, т.к. нам не надо ;оставлять драйвер резидентно ;в памяти ; Заголовок драйвера dd 0ffffffffh ;адрес следующего драйвера dw 8000h ;байт атрибутов dw dev_strategy ;адрес процедуры стратегии dw dev_interrupt ;адрес процедуры прерывания db 'STOP ' ;имя устройства (дополненное пробелами) ;=========================================================== ; Программа стратегии dev_strategy: mov cs:req_seg,es mov cs:req_off,bx ret ; Здесь запоминается адрес заголовка запроса req_seg dw ? req_off dw ? ;=========================================================== ;Обработчик прерывания dev_interrupt: push es ;сохраняем регистры push ds push ax push bx push cx push dx push si push di push bp ; Устанавливаем ES:BX на заголовок запроса mov ax,cs:req_seg mov es,ax mov bx,cs:req_off ; Получаем код команды из заголовка запроса и умножаем ; его на два, чтобы использовать в качестве индекса ; таблицы адресов обработчиков команд mov al,es:[bx]+2 shl al,1 sub ah,ah ; Обнуляем AH lea di,functions ; DI указывает на смещение таблицы add di,ax ; Добавляем смещение в таблице jmp word ptr [di] ; Переходим на адрес из таблицы functions LABEL WORD ; Таблица функций dw initialize dw check_media dw make_bpb dw ioctl_in dw input_data dw nondestruct_in dw input_status dw clear_input dw output_data dw output_verify dw output_status dw clear_output dw ioctl_out dw Device_open dw Device_close dw Removable_media ; Выход из драйвера, если функция не поддерживается check_media: make_bpb: ioctl_in: nondestruct_in: input_status: clear_input: output_verify: output_status: clear_output: ioctl_out: Removable_media: Device_open: Device_close: output_data: input_data: or es:word ptr [bx]+3,8103h jmp quit ;=========================================================== quit: or es:word ptr [bx]+3,100h pop bp pop di pop si pop dx pop cx pop bx pop ax pop ds pop es ret ;=========================================================== ; Процедура выводит на экран строку ; символов в формате ASCIIZ dpc proc near push si dpc_loop: cmp ds:byte ptr [si],0 jz end_dpc mov al,ds:byte ptr [si] @@out_ch al inc si jmp dpc_loop end_dpc: pop si ret dpc endp ;=========================================================== hello db 13,10,'++' db 13,10,'¦ *STOP* (C)Frolov A., 1990 ¦' db 13,10,'++' db 13,10 db 13,10,'Enter password...' db 13,10,0 ;=========================================================== initialize: lea ax,E_O_P ;смещение конца программы в AX mov es:word ptr [bx]+14,ax ;помещаем его в заголовок mov es:word ptr [bx]+16,cs ; ; Стираем экран mov dh,18h mov dl,80h xor cx,cx mov bh,7 xor al,al mov ah,6 int 10h ; Устанавливаем курсор в левый верхний угол экрана mov bh,0 xor dx,dx mov ah,2 int 10h ; Выводим сообщение mov ax,cs mov ds,ax mov si,offset hello call dpc ; Ожидаем ввода правильного пароля loop_password: mov ax,0 int 16h cmp al,'s' jne loop_password mov ax,0 int 16h cmp al,'y' jne loop_password mov ax,0 int 16h cmp al,'s' jne loop_password jmp quit stop ENDP END stop Участок программы, ответственный за ввод пароля, имеет смысл усложнить. Предоставляем это сделать вам самим. Описанный выше драйвер эффективен в тех случаях, когда посторонний пользователь не может по тем или иным причинам загрузить операционную систему с дискеты. Дополнительным средством защиты информации (возможно, наилучшим) может служить шифрование файлов данных. Для этого можно воспользоваться готовыми программами или написать собственные. Одна из готовых программ, которая может быть использована для шифрования данных - архиватор PKZIP. Эта программа кроме шифрования файлов еще и уплотняет их, что полезно и само по себе. После образования зашифрованного архива программа PKZIP удаляет исходные файлы. К сожалению, эти файлы можно легко восстановить, например, утилитой Нортона QU. Для того, чтобы удалить эти файлы окончательно, можно в конце рабочего дня запускать утилиту Нортона WIPEINFO, которая прописывает сектора свободных кластеров нулями (при вызове с соответствующими параметрами). Для удобства шифрования файлов программой PKZIP мы подготовили две программы (соответственно, для шифрования и дешифрования). Первая программа запрашивает пароль, не отображая его на экране. Затем она ищет программу PKZIP в каталогах, описанных переменной среды PATH и запускает ее с соответствующими параметрами. Вторая программа выполняет аналогичные действия с программой PKUNZIP, использующейся для дешифрования. Программа шифрования всех файлов текущего каталога: #include <stdio.h> #include <conio.h> #include <process.h> void main(int argc, char *argv[]) { char passw[80], filebuf[80], parms[100], ch; _searchenv( "pkzip.exe", "PATH", filebuf ); if(!(*filebuf) ) { printf("PKZIP not found.\n"); exit(-2); } printf( "Enter password: " ); getpw(passw, 80); sprintf(parms,"-m -s%s %s",passw,argv[1]); execl( filebuf, parms, parms, NULL ); exit(-1); } int getpw( char *buf, int size) { int i; char ch; for(i=0; i<size; ) { ch = getch(); if(ch == 0) ch=getch(); putch('.'); *buf = ch; if(*buf == 0xd) break; i++; buf++; } *buf = 0; } Программа дешифрования: #include <stdio.h> #include <conio.h> #include <process.h> void main(int argc, char *argv[]) { char passw[80], filebuf[80], parms[100], ch; _searchenv( "pkunzip.exe", "PATH", filebuf ); if(!(*filebuf) ) { printf("PKUNZIP not found.\n"); exit(-2); } printf( "Enter password: " ); getpw(passw, 80); sprintf(parms,"-s%s %s",passw,argv[1]); execl( filebuf, parms, parms, NULL ); exit(-1); } int getpw( char *buf, int size) { int i; char ch; for(i=0; i<size; ) { ch = getch(); if(ch == 0) ch=getch(); putch('.'); *buf = ch; if(*buf == 0xd) break; i++; buf++; } *buf = 0; } В качестве параметра программам надо задать имя образуемого архива (можно без расширения). Если это имя не указывать, используется имя (NULL) - на эту строку указывает неинициализированный параметр argv[1]. |