Консультация № 175115
10.12.2009, 22:31
0.00 руб.
0 8 2
Доброго времени суток уважаемые эксперты. С целью ознакомления решил написать резидентную программу ОС MS-DOS, которая запрещала создавать файл с определенным именем. Написал резидентную часть программы перехватывающее прерывание 21h функции 3Ch — Создание файла(резидент приведен в приложении).
Функция DOS 3Ch — Создать файл

Ввод: AX = 3Ch
СХ = атрибут файла
бит 7: файл можно открывать разным процессам в Novell Netware
бит 6: не используется
бит 5: архивный бит (1, если файл не сохранялся)
бит 4: каталог (должен быть 0 для функции 3Ch)
бит 3: метка тома (игнорируется функцией 3Ch)
бит 2: системный файл
бит 1: скрытый файл
бит 0: файл только для чтения
DS:DX = адрес ASCIZ-строки с полным именем файла (ASCIZ-строка ASCII-символов, оканчивающаяся нулем)
Вывод: CF = 0 и АХ = идентификатор файла, если не произошла ошибка
CF = 1 и АХ = 03h, если путь не найден
CF = 1 и АХ = 04h, если слишком много открытых файлов
CF = 1 и АХ = 05h, если доступ запрещен

Следовательно, для достижения цели нам нужно при перехвате прерывания функции создания нового файла:
1)Сравнить имя создаваемых с именем запрещенным
2) Если совпадают вызвать ошибку(как я понял флаг CF в 1 и любой код ошибки в AX)
3) Если нет вернуть управление.

Возникшие вопросы:
1) При создании имя файла храниться DS:DX, при перехвате прерывания где будет храниться название создаваемого файла
2) Как можно будет сравнить имена файлов? Циклом посимвольно или есть другой способ?
3) Вызвать ошибку будет достаточно установить флаг CF в 1 и любой код ошибки в AX и вернуть управление или я ошибаюсь?
4) Я не много не уверен в правельности вектора прерывания в моей резиденте...


Приложение:
CODE SEGMENT
ORG 100h
ASSUME CS:CODE,DS:CODE
Begin:
JMP Start
OLD_VEC LABEL DWORD
IP_OLD DW ?
CS_OLD DW ?
Kol DW ?
PRO:
PUSHF
CALL CS:OLD_VEC

IRET
Start:
MOV AX,353Ch
INT 21h
MOV IP_OLD,BX
MOV CS_OLD,ES
MOV AX,253Ch
LEA DX,PRO
INT 21h
LEA DX,Start

INT 27h
CODE ENDS
END Begin

Обсуждение

давно
Посетитель
7438
7205
11.12.2009, 09:49
общий
это ответ
Здравствуйте, Земцов Дмитрий Анатольевич.
Всегда приятно не делать за кого-то, а помочь разобраться... Итак:
1) Совершенно верно, при создании имя файла хранится в DS:DX, т.е. используются длинные указатели.
Поэтому при прехвате там его надо и искать.
2) Сравнивать две строки лучше всего следующим образом
Код:
mov si, dx ;DS:SI - адрес имени создаваемого файла
les di,TestName ;загрузка ES:DI адресом строки с тестовым именем
mov cx,TestNameLen ;длина тестового имени с завершающим нулем
repe cmpsb ;сравниваем, пока равно
je Equal ;делаем выводы
NotEqual:
Не забываем о том, что работаем в прерывании, поэтому сохраняем все используемые регистры
3) В принципе, верно: устанавливаем CF=1 и даем код ошибки в AX.
Только код надо давать не любой, а соответствующий. Лучше всего, пожалуй, подойдет 5 (Access denied)
4) Код вполне рабочий, за исключением:
Меняем вектор прерывания 21h, а не 3Ch, поэтому надо писать MOV AX,3521h и, соответственно, MOV AX,2521h
Только код же ничего не делает :)
Надо же, хотя бы, проверять на номер перехватываемой функции...
5) Файл можно еще создать при помощи функции 16h
6) Желательно принимать меры, чтобы резидент не устанавливался повторно и/или имел возможность выгрузиться
Удачи!
В приложении исправленная Ваша программа

Приложение:
model tiny
.code
.186
org 100h
begin:
jmp init
;данные о старом векторе
old_vec21 label dword
old_21o dw ?
old_21s dw ?
;контролируемая строка
check_name db 'check.txt',0

;наш обработчик
new_vec21:
cmp ah,3Ch
jne notInt

;наша функция
isInterupt:
pusha
push es
mov si,DX
push cs
pop es
mov di,offset check_name
mov cx,10
repe cmpsb
jne notintf

Equal:
pop es
mov bp,sp
or byte ptr [bp+20],1
popa
mov ax,5
iret

notintf:
pop es
popa
notInt:
jmp cs:old_vec21

;инициализация
init: mov ax,3521h
int 21h
;запоминаем старый вектор
mov old_21o,bx
mov old_21s,es
;контролируем присутсвие
mov cx,9h
mov si,107h
mov di,107h
repe cmpsb
jz isStop
;сообщение о начале работы
isGo: mov ah,9
mov dx,offset dbMessageGo
int 21h
;ставим свой вектор
mov ax,2521h
mov dx,offset new_vec21
int 21h
;выходим
mov dx,offset init
int 27h

dbMessageGo db 'interupt set up$'
dbMessageNo db 'Im here$'

;сообщаем о повторе
isStop: mov ah,9
mov dx,offset dbMessageNo
int 21h
xor ax,ax
int 16h
ret
end begin
5
Спасибо огромное за советы, а так же за помощь в изучении работы с флагами и сравнение строки в асм
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
31795
6196
11.12.2009, 10:48
общий
Лысков Игорь Витальевич:

Цитата: 233255
MOV AX,353Ch

Прерывание не то:
Int 3C - FLOATING POINT EMULATION - INSTRUCTIONS WITH SEGMENT OVERRIDE


Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
7438
7205
11.12.2009, 10:56
общий
Земцов Дмитрий Анатольевич:
А-а-а, ну да.... На автомате не заметил...
Меняем на MOV AX,3521h и, соответственно, MOV AX,2521h
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
31795
6196
11.12.2009, 15:32
общий
это ответ
Здравствуйте, Земцов Дмитрий Анатольевич.

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

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

В регистрах DS:DX хранится адрес памяти с именем файла, но тамже может хранится дополнительно ещё и путь к нему, т.е. приблизительно в таком виде D:\_CAT\_LANG\my_LIB\check.txt. Если путь к файлу не указан, то файл создается в текущем каталоге, иначе в указаном. Этот момент тоже нужно учитывать при анализе имени файла.

Удачи!

Приложение:
model tiny
.code
.186
org 100h
begin: jmp init
;данные о старом векторе
old_vec21 label dword
old_21o dw ?
old_21s dw ?
;контролируемая строка
check_name db 'check.txt',0
check_size equ $-check_name
control_message db 'illegal file name : $'
;наш обработчик
new_vec21: cmp ah,3ch
jz isInterupt
jmp cs:old_vec21
;наша функция
isInterupt: pusha
push ds
;востанавливаем наш сегмент памяти
push cs
pop ds
;выводим сообщение
mov ah,9
pushf
mov dx,offset control_message
call cs:old_vec21
;выходим из прерывания
pop ds
mov bp,sp
mov ax,[bp+20]
or ax,1
mov [bp+20],ax
popa
iret
;инициализация
init: mov ax,3521h
int 21h
;запоминаем старый вектор
mov old_21o,bx
mov old_21s,es
;контролируем присутсвие
mov cx,check_size
mov si,107h
mov di,107h
repe cmpsb
or cx,cx
jz isStop
;сообщение о начале работы
isGo: mov ah,9
mov dx,offset dbMessageGo
int 21h
;ставим свой вектор
mov ax,2521h
mov dx,offset new_vec21
int 21h
;выходим
mov dx,offset init
int 27h
dbMessageGo db 'interupt set up$'
dbMessageNo db 'Im here$'
;сообщаем о повторе
isStop: mov ah,9
mov dx,offset dbMessageNo
int 21h
xor ax,ax
int 16h
ret
end begin
5
Спасибо огромное за советы, а так же за детальный пример разидентной программы прерыванием 21h функции 3Ch
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
11.12.2009, 15:35
общий
Забыл добавить, ниже тестовая программа:
Код:
model tiny
.code
.186
org 100h
begin:
mov ah,3ch
xor cx,cx
mov dx,offset myName
int 21h
jc isStop
mov bx,ax
mov ah,3eh
int 21h
xor ax,ax
int 16h
ret
isStop:
mov ah,9
mov dx,offset myName
int 21h
xor ax,ax
int 16h
ret
myName db 'error.fil',0,'$'
end begin

Удачи!
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
11.12.2009, 22:20
общий
Спасибо большое разобрался в ваших кодах, но хотелось бы доделать поставленую задачу, а имеено запрещать создавать файл с опр именем файла(пока что без учета пути). Ниже приведен код на основе программы Зенченко Константина Николаевича. Не могу найти ошибку(разрешает создавать все возможные файлы) помоему возможны 1 ошибки
а) ошибка в сравнении имен файлов(Лысков Игорь Витальевич, у вас в строке кода les di,TestName мне кажеться ошибка, кроме как оператора lea мне больше не чего не вспомнилось)
б) ошибка в переходах(где я уже помоему сам запутался)

И еще если можно пару вопросов:
1) Назначение этой сторки CALL CS:OLD_VEC как я понимаю вызов старого прерывания, но для чего?
2) При создании файла в MS-DOS командой copy con или copy создаеться файл при помощи какого прерывания и какой функции, можно ли это отследить резидентной программой?

Код:
model tiny
.code
.186
org 100h
begin:
jmp init
;данные о старом векторе
old_vec21 label dword
old_21o dw ?
old_21s dw ?
;контролируемая строка
check_name db 'check.txt',0
;наш обработчик
new_vec21:
cmp ah,3Ch
je isInterupt

jmp notInt
;наша функция
isInterupt:
pusha
push SI
push DI
push CX
mov si,DX
mov di,offset check_name
mov cx,9
repe cmpsb
jne notintf

Equal:
STC
mov ax,5
pop CX
pop DI
pop SI
popa
jmp exit1
notint:
jmp cs:old_vec21
notintf:
pop CX
pop DI
pop SI
popa
jmp cs:old_vec21
exit1:
iret
;инициализация
init: mov ax,3521h
int 21h
;запоминаем старый вектор
mov old_21o,bx
mov old_21s,es
;контролируем присутсвие
mov cx,9h
mov si,107h
mov di,107h
repe cmpsb
or cx,cx
jz isStop
;сообщение о начале работы
isGo: mov ah,9
mov dx,offset dbMessageGo
int 21h
;ставим свой вектор
mov ax,2521h
mov dx,offset new_vec21
int 21h
;выходим
mov dx,offset init
int 27h
dbMessageGo db 'interupt set up$'
dbMessageNo db 'Im here$'
сообщаем о повторе
isStop: mov ah,9
mov dx,offset dbMessageNo
int 21h
xor ax,ax
int 16h
ret
end begin
давно
Старший Модератор
31795
6196
11.12.2009, 22:29
общий
Земцов Дмитрий Анатольевич:
Код:

mov si,DX
mov di,offset check_name
mov cx,9
repe cmpsb

Этой команде нужны пары регистров ds:si и es:di, на момент вызова обработчика у Вас известно только cs:ip, остальное принадлежит прерваной программе.

Цитата: 233255
(Лысков Игорь Витальевич, у вас в строке кода les di,TestName мне кажеться ошибка, кроме как оператора lea мне больше не чего не вспомнилось)

У Вас есть книга С.В.Зубкова, т.к. Ваша цитата именно из неё, проверьте команду les и ещё lds
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
7438
7205
11.12.2009, 23:14
общий
Земцов Дмитрий Анатольевич:
Я добавил в ответ подправленную Вашу программу. Внимательно сравните со своей...
Хочу объяснить один момент:
Когда происходит прерывание, то в стек засылаются регистр флагов, сегмент и смещение.
При возврате по iret все восстанавливается, включая регистр флагов. Поэтому установка флага С по STC ничего не дает,
т.е. после возврата из прерывания восстановится старое значение.
Поэтому надо взводить бит в стеке, там, где хранится старое значение регистра флагов.
После iret сохраненное значение попадет в регистр флагов и, ву-аля, CF взведен!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа