Некоторые недокументированные возможности DOS

Дата публикации 16 июн 2002

Некоторые недокументированные возможности DOS — Архив WASM.RU

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

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

КОММЕНТАРИИ К НЕБОЛЬШОЙ СЕРИИ СТАТЕЙ О НЕДОКУМЕНТИРОВАННЫХ ВОЗМОЖНОСТЯХ MS-DOS.

  Описываемые возможности проникновения в DOS и недокументированное поведение функции 13h являются серьезной прорехой с точки зрения недопущения несанкционированных действий и в то же время лакомым кусочком для создателей вирусов. Существующие резидентные антивирусы не следят за этим способом проникновения в DOS, чем, кстати говоря, воспользовался вирус RD-1024. Ужасные же возможности функции 13h пока вроде бы еще не использовались и их еше не поздно закрыть. Для этого может быть использован драйвер, опубликованный в Dr.Dobb's Journal, текст которого здесь приводится. Почему-то о нем ничего не было сказано в "Софтпанораме", хотя, казалось бы, одна из функций бюллетеня защита от вирусов. В результате пришлось отражать атаку нового вируса, воспользовавшегося именно этим способом.

  Я вполне допускаю возможность вопроса о необходимости обнародования недокументированных возможностей MS-DOS, ибо это может вроде бы стимулировать создателей вирусов на новые творения. Однако нужно понимать, что авторы вирусов тоже любят читать всякие западные компьютерные журналы, где можно найти кое-что интересное по этой теме, как, например, вышеуказанная статья из Dr.Dobb's Journal. И своевременная информация принесла бы больше пользы, чем вреда, поскольку указанные прорехи были бы раньше закрыты, что свело бы на нет все усилия творцов вирусов. Вовремя эта информация не появилась, но лучше поздно, чем никогда, я надеюсь.

  Необходимо заметить, что в процессе написания этой серии статей использовались материалы из статьи Closing the DOS Backdoor, опубликованной в Dr.Dobb's Journal. В то же время написанное не является переводом опубликованной статьи.

ПРЕРЫВАНИЯ 30H И 31H

  Прерывания 30h и 31h не используются в DOS и о них ничего не говорится в обычных руководствах программиста по DOS. Строго говоря, их вообще нельзя назвать прерываниями и тем более пытаться их выполнить. Ни к чему хорошему это не приведет, поскольку ячейки памяти, зарезервированные для векторов этих двух прерываний (0:00C0 - 0:00C7) не содержат, как обычно, адресов процедур, выполняющих обработку прерываний.

  Вместо зтого, начиная с адреса 0:00C0 (адрес вектора пре- рывания 30h) располагается команда JMP FAR seg:off, которая указы- вает на альтернативный обработчик прерывания 21h. В результате, зная правила передачи параметров и и другой необходимой для обработчика прерывания информации, можно осуществить прямой доступ в DOS, не генерируя прерывание 21h, а просто выполняя переход на описанную команду.

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

  Своим существованием эта команда обязана желанию разработчиков PC-DOS и MS-DOS обеспечить совместимость с операционной системой CP/M, где для вызова функции DOS было необходимо выполнить команду CALL 0005, предварительно загрузив номер функции в регистр CL. Этот вызов выполнял команду, находяшуюся по смещению 5 в PSP, а та, в свою очередь, вызывала DOS.

  Описанный способ доступа к DOS существует в PC-DOS, начиная с версии 1.1, и в большинстве версий MS-DOS.

Код (Text):
  1.  
  2. ;----------------------------------------------------------------------------
  3. ;   Пример вызова функции DOS через альтернативный обработчик
  4. ;   прерывания 21h.
  5.  
  6.         mov  ax, offset RETURN     ; Взять смещение адреса возврата
  7.         push ax                    ; Занести в стек флаги, сегмент
  8.         push cs                    ;    и смещение адреса возврата
  9.         pushf                      ;    в обратном порядке.
  10.         mov  cl, 9                 ; Функция: показать строку.
  11.         mov  dx, offset MESSAGE    ; Загрузить адрес сообщения.
  12.         push cs                    ; Для уверенности, что DS
  13.         pop  ds                    ;    указывает на текущий код.
  14.         jmp  dword ptr ALT_DOS_PTR ; Выполнить функцию.
  15.  
  16. RETURN: mov  ah, 4Ch               ; Завершить процесс через DOS.
  17.         int  21h                   ;
  18.  
  19. ALT_DOS_PTR dw 00C0h, 0000         ; Адрес для перехода в альтер-
  20.                                    ;    нативный обработчик
  21.  
  22. MESSAGE db 0Dh, 0Ah, "Example of backdoor MS-DOS "
  23.         db "function call.", 0Dh, 0Ah, 7, "$"
  24.  

АЛЬТЕРНАТИВНЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЯ 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.

Код (Text):
  1.  
  2. ;----------------------------------------------------------------------------
  3. ;        Листинг (срез) альтернативного обработчика прерывания 21h.
  4. ;        Текст немного упрощен для лучшей читабельности при
  5. ;        сохранении полной смысловой идентичности.
  6. ;----------------------------------------------------------------------------
  7.  
  8. RefuseRequest:          ; Отказ от выполнения запрашиваемой функции,
  9.     mov  ax, 0              ;     т.к. номер функции недопустим.
  10.     iret
  11.  
  12. Alt_DOS_Entry:      ; Точка входа в альтернативный обработчик прерывания
  13.     pop ax              ; Извлечь из стека содержимое регистра флагов
  14.     pop ax              ; Извлечь из стека сегмент адреса возврата
  15.     pop cs:Temp         ; Извлечь из стека смещение адреса возврата
  16.             ; Перестроить стек для команды IRET
  17.     pushf                   ; Сохранить в стеке флаги
  18.     cli                     ; Запретить генерацию прерывания 21h
  19.     push    ax              ; Сохранить сегмент адреса возврата
  20.     push    cs:Temp         ; Сохранить смещение адреса возврата
  21.  
  22.     cmp cl, 24h         ; Номер функции меньше максимального?
  23.     ja  RefuseRequest   ; Нет. Отказ обрабатывать запрос.
  24.             ; Допустимый номер функции.
  25.     mov ah, cl          ; Загружаем номер функции в AH и переходим
  26.     jmp short INT_21h_Further   ; в стандартный обработчик INT 21h
  27.  
  28. INT_21h_Entry:      ; Стандартный обработчик прерывания 21h
  29.     cmp ah, 6Ch     ; Номер функции меньше максимального?
  30.     ja  RefuseRequest   ; Нет. Отказ обрабатывать запрос.
  31.             ; Допустимый номер функции.
  32. INT_21h_Further:
  33.     cmp ah, 51h
  34.     . . .
  35.     . . .
  36. ;----------------------------------------------------------------------------
  37.  
Код (Text):
  1.  
  2. ;----------------------------------------------------------------------------
  3. ;   Пример вызова функции DOS через альтернативный обработчик
  4. ;   прерывания 21h.
  5. ;----------------------------------------------------------------------------
  6.  
  7.         mov ax, offset RETURN     ; Взять смещение адреса возврата
  8.         push    ax                    ; Занести в стек флаги, сегмент
  9.         push    cs                    ;    и смещение адреса возврата
  10.         pushf                         ;    в обратном порядке.
  11.         mov cl, 9                 ; Функция: показать строку.
  12.         mov     dx, offset MESSAGE    ; Загрузить адрес сообщения.
  13.         push    cs                    ; Для уверенности, что DS
  14.         pop ds                    ;    указывает на текущий код.
  15.         jmp dword ptr ALT_DOS_PTR ; Выполнить функцию.
  16.  
  17. RETURN:     mov ah, 4Ch               ; Завершить процесс через DOS.
  18.         int 21h                   ;
  19.  
  20. ALT_DOS_PTR dw  00C0h, 0000           ; Адрес для перехода в альтер-
  21.                           ;    нативный обработчик
  22. MESSAGE     db  0Dh, 0Ah, "Example of backdoor MS-DOS "
  23.         db  "function call.", 0Dh, 0Ah, 7, "$"
  24.  
  25. ;-----------------------------------------------------------------------------
  26.  

СОДЕРЖИМОЕ PSP: ЯЧЕЙКИ 05H-09H
ОПИСАНИЕ ДЕЙСТВИЙ ДЛЯ ВЫЗОВА ФУНКЦИЙ DOS В СТИЛЕ CP/M

  В операционной системе CP/M программисты для вызова функций DOS использовали близкий CALL: по смещению 5 в PSP каждой программы находится команда CALL FAR seg:off, которая теоретически позволяет вызвать DOS выполнением команды CALL 0005, точно так же, как в CP/M.

  Однако это поле обычно содержит команду, подобную, скажем, CALL FAR F5C2:A496. Она указывает на ячейку памяти, которая, как кажется, либо принадлежит BIOS, либо находится в несуществующей области памяти. Команды же по этому адресу обычно представляют собой просто мусор. В результате, большинство программистов просто игнорирует этот способ, хотя он и был тщательно документирован с первых же версий MS-DOS.

  Дело же здесь в том, что адрес, содержащийся в PSP, несет в себе еще одну, дополнительную нагрузку и поэтому не совсем корректен с точки зрения его истинного предназначения. Содержимое второго и третьего байтов, кроме того, что является вроде бы смещением адреса, по которому происходит переход при выполнении CALL, означает количество свободных байтов в сегменте программы. Поэтому перед использованием этот адрес должен быть слегка подкорректирован: выравнен вверх до ближайшего параграфа. Используя предыдущий пример, получаем CALL FAR F5C2:A4A0.

  Если взглянуть на команду, находящуюся по этому адресу, можно увидеть ту же самую инструкцию, что находится в векторе прерывания 30h и которая указывает на альтернативный обработчик прерывания 21h. Таким образом, сохранив в стеке необходимые данные в требуемом порядке и, воспользовавшись откорректированным адресом (сформировав, например, команду JMP FAR с этим адресом), можно попасть в DOS обходным путем, не генерируя прерывание 21h.

  Вместе с тем, откорректировав адрес, содержащийся в PSP, можно вызывать функции DOS и в стандартном для CP/M стиле: выполнением команды CALL 0005, с указанием номера вызываемой функции в регистре CL. Может показаться, что такой способ не обеспечивает корректного возврата в программу, однако это не так. Благодаря первым командам альтернативного обработчика прерывания 21h все проходит прекрасно. Рассмотрим этот процесс более детально.

  Выполнение команды CALL 0005 заносит в стек корректный адрес возврата, то есть адрес следующей команды. Затем выполняется далекий CALL в PSP. Выполнение его заносит в стек значение кодового сегмента программы, а затем еще один адрес возврата. Однако, он уже указывает на ячейку памяти со смещением 0Ah в PSP. Тем не менее, возврат происходит куда следует, потому что первое, что делает этот обработчик прерывания - это удаляет второй адрес возврата командой POP AX. Затем он извлекает из стека два других значения и снова заносит их туда, но уже в порядке, необходимом для команды IRET: сначала регистр флагов, затем сегмент и, наконец, смещение адреса возврата. В результате по выполнении вызванной функции DOS команда IRET заносит в CS:IP корректные значения.

  Осталось только понять, почему по откорректированному адресу находится такая же команда, что и в векторе прерывания 30h. Для этого нужно вспомнить, что память в IBM PC построена по принципу кольца и за самым старшим адресом снова следует самый младший (сказанное относится только к реальному режиму микропроцессоров 80286 и 80386). И поэтому адрес в PSP F5C2:A4A0 на самом деле переходит в 0:00C0 : смещение A4A0=сегмент 0A4A, и сегмент F5C2 плюс сегмент A4A есть сегмент 1000C, что по правилам кольца становится сегментом 000C или, что то же самое, адресом 0:00C0. Таким образом, откорректированный адрес в PSP на самом деле указывает на вектор прерывания 30h.

ФУНКЦИЯ 13H ПРЕРЫВАНИЯ 21H.
НЕДОКУМЕНТИРОВАННЫЕ ВОЗМОЖНОСТИ

  Функция 13h прерывания 21h относится к серии функций, выполняющих операции с файлами с использованием FCB. Она удаляет файл или группу файлов.

  Эта функция имеет один недокументированный случай, когда расширенный FCB использует имя файла ??????????? и атрибут файла 1Fh. При этой специфической комбинации функция 13h удаляет все файлы в текущем каталоге, включая файлы с атрибутами "только для чтения", "том" и "каталог". Чтобы усугубить положение, эта функция заменяет первый символ в имени удаленного файла на 0, а не на обычный 0E5h. Это вводит в заблуждение многие утилиты восстановления файлов.

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

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

Код (Text):
  1.  
  2. ;----------------------------------------------------------------------
  3. ;   Пример использования недокументированново свойства функции 13h
  4. ;   прерывания 21h.
  5. ;   НИ В КОЕМ СЛУЧАЕ НЕ ВЫПОЛНЯЙТЕ ЭТОТ ПРИМЕР НА ЖЕСТКОМ ДИСКЕ:
  6. ;   ЭТО МОЖЕТ ПРИВЕСТИ К НЕПРЕДСКАЗУЕМЫМ ПОСЛЕДСТВИЯМ. ЕСЛИ УЖ ЕСТЬ
  7. ;   ГОРЯЧЕЕ ЖЕЛАНИЕ ИСПЫТАТЬ ЕЕ, ВЫДЕЛИТЕ ДЛЯ ЭТОЙ ЦЕЛИ ОТДЕЛЬНУЮ
  8. ;   ДИСКЕТУ.
  9. ;-----------------------------------------------------------------------
  10.  
  11.         mov ax, offset RETURN     ; Взять смещение адреса возврата
  12.         push    ax                    ; Занести в стек флаги, сегмент
  13.         push    cs                    ;    и смещение адреса возврата
  14.         pushf                         ;    в обратном порядке.
  15.         mov cl, 13h               ; Функция: удалить по FCB
  16.         mov dx, offset FCB        ; Расширенный FCB
  17.         push    cs                    ; Для уверенности, что DS
  18.         pop ds                    ;    указывает на текущий код.
  19.         jmp dword ptr ALT_DOS_PTR ; Выполнить функцию.
  20.  
  21. RETURN:     mov ah, 4Ch               ; Завершить процесс через DOS.
  22.         int 21h                   ;
  23.  
  24. ALT_DOS_PTR dw  00C0h, 0000           ; Адрес для перехода в альтер-
  25.                           ;    нативный обработчик
  26. FCB     db  0FFh        ; Расширенный FCB
  27.         db  5 dup (0)       ; Зарезервированные байты
  28.         db  1Fh             ; Установлены все биты атрибута файла
  29.         db  0               ; Номер дискового устройства
  30.         db  "???????????"   ; Искать все файлы
  31.         db  19h dup (0)     ; Остальная часть FCB
  32.  
  33. ;--------------------------------------------------------------------------
  34.  

ПОСЛЕСЛОВИЕ

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

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

  150000, г.Ярославль,
  ул.Б.Октябрьская, д.63/3, кв.29

  телефоны: (085-2) 25-49-53 (раб)
  (085-2) 22-51-05 (дом) © Алексей Баулин


0 2.078
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532