Недокументированные возможности MS-DOS - Альтернативный обработчик прерывания int 21h
Альтернативный обработчик прерывания 21h предъявляет другие требования к входным параметрам, чем обычный вызов INT 21h. Его использование требует некоторых специальных действий и понимания того, что он позволяет.
Прежде всего, обработчик ожидает, что адрес возврата будет в стеке в отличном от обычного порядке. Обычно, когда генерируется прерывание, процессор сначала заносит в стек флаги, а затем сегмент и смещение адреса возврата. Однако в этой точке входа предполагается, что флаги были занесены в стек последними, после занесения смещения и сегмента адреса возврата.
Назначение команд, находящихся в этой точке входа - выполнить некоторую предварительную обработку входных данных и стека, прежде чем передать управление стандартному обработчику прерывания 21h. Иными словами, альтернативный обработчик прерывания является лишь надстройкой над стандартным. Поэтому первое, что он делает - это перестраивает стек в стандартном порядке, приемлемом для команды IRET.
Следующим действием альтернативный обработчик прерывания 21h контролирует номер запрашиваемой для выполнения функции и допускает только функции с номерами 00h-24h. Поскольку регистр AX разрушается сразу же после входа, номер функции передается в регистре CL, а не в AH. Это же означает, что даже среди допустимых функций есть недоступные: те, которые требуют дополнительного параметра в регистре AL. Так, например, недоступна функция 0Ch (очистить буфер клавиатуры и затем вызвать одну из функций 01h, 06h, 07h, 08h, или 0Ah), поскольку она требует номер подфункции в регистре AL.
Однако как узнать, где располагается этот обработчик прерывания, чтобы получить к нему доступ? Вектор прерывания 30h содержит команду JMP FAR, позволяющую перейти по требуемому адресу. Таким образом, чтобы использовать прямой вызов DOS, вызывающая программа должна занести в стек сначала флаги, затем смещение и сегмент адреса возврата, а потом загрузить в регистр CL номер функции и выполнить далекий переход по адресу 0:00C0, передав таким образом управление альтернативному обработчику прерывания 21h. По окончании функционирования обработчик прерывания 21h выполняет команду IRET по адресу возврата, находящемуся, как обычно, в стеке.
Остается выяснить вопрос: для чего вообще нужен альтернативный обработчик прерывания 21h, почему к нему такой необычный способ доступа и отчего в нем такое странное соглашение о входных параметрах. На все эти три вопроса можно ответить одновременно: это связано с желанием разработчиков MS-DOS обеспечить совместимость с операционной системой CP/M, господствовавшей до появления MS-DOS. Поэтому соглашение о входных параметрах и ограниченность выбора функций, столь странные для пользователей MS-DOS, отнюдь не покажутся странными тем, кто еще помнит CP/M. А что же касается необычного способа доступа к альтернативному обработчику прерывания, то описанный способ в действительности не используется, хотя он вполне корректен, а команда JMP FAR в векторе прерывания 30h существует исключительно для поддержки вызова функций DOS в стиле CP/M через PSP: командой CALL 0005.
Описанный альтернативный обработчик прерывания 21h существует во всех версиях PC-DOS и почти во всех версиях MS-DOS. Интересно заметить, что код этого обработчика, судя по проведенным исследованиям, одинаков во всех версиях DOS и, следовательно, имеет одну и ту же длину. Очевидно, что он является не более чем рудиментом, оставшимся в наследство от операционной системы CP/M, этакий аппендикс MS-DOS. Далее, сегмент DOS, где располагаются все его функции, можно получить многими способами, а смещение в нем альтернативного обработчика прерывания 21h, как, следовательно, и стандартного, одинаково в пределах одной версии DOS, пусть даже и разных фирм.
Можно, конечно, и обойти существующее в этой точке входа ограничение на номер функции. Для этого нужно просто затереть командами NOP проверку на допустимость номера. При этом нельзя упускать из виду другое ограничение: нельзя пользоваться функциями, требующими параметров в регистрах AL и CL.
;---------------------------------------------------------------------------- ; Листинг (срез) альтернативного обработчика прерывания 21h. ; Текст немного упрощен для лучшей читабельности при ; сохранении полной смысловой идентичности. ;---------------------------------------------------------------------------- RefuseRequest: ; Отказ от выполнения запрашиваемой функции, mov ax, 0 ; т.к. номер функции недопустим. iret Alt_DOS_Entry: ; Точка входа в альтернативный обработчик прерывания pop ax ; Извлечь из стека содержимое регистра флагов pop ax ; Извлечь из стека сегмент адреса возврата pop cs:Temp ; Извлечь из стека смещение адреса возврата ; Перестроить стек для команды IRET pushf ; Сохранить в стеке флаги cli ; Запретить генерацию прерывания 21h push ax ; Сохранить сегмент адреса возврата push cs:Temp ; Сохранить смещение адреса возврата cmp cl, 24h ; Номер функции меньше максимального? ja RefuseRequest ; Нет. Отказ обрабатывать запрос. ; Допустимый номер функции. mov ah, cl ; Загружаем номер функции в AH и переходим jmp short INT_21h_Further ; в стандартный обработчик INT 21h INT_21h_Entry: ; Стандартный обработчик прерывания 21h cmp ah, 6Ch ; Номер функции меньше максимального? ja RefuseRequest ; Нет. Отказ обрабатывать запрос. ; Допустимый номер функции. INT_21h_Further: cmp ah, 51h . . . . . . ;---------------------------------------------------------------------------- ;---------------------------------------------------------------------------- ; Пример вызова функции DOS через альтернативный обработчик ; прерывания 21h. ;---------------------------------------------------------------------------- mov ax, offset RETURN ; Взять смещение адреса возврата push ax ; Занести в стек флаги, сегмент push cs ; и смещение адреса возврата pushf ; в обратном порядке. mov cl, 9 ; Функция: показать строку. mov dx, offset MESSAGE ; Загрузить адрес сообщения. push cs ; Для уверенности, что DS pop ds ; указывает на текущий код. jmp dword ptr ALT_DOS_PTR ; Выполнить функцию. RETURN: mov ah, 4Ch ; Завершить процесс через DOS. int 21h ; ALT_DOS_PTR dw 00C0h, 0000 ; Адрес для перехода в альтер- ; нативный обработчик MESSAGE db 0Dh, 0Ah, "Example of backdoor MS-DOS " db "function call.", 0Dh, 0Ah, 7, "$" ;-----------------------------------------------------------------------------