Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Рефлексия DLL Инжектора на Delphi: Решение Проблемы Сегментации

Delphi , Файловая система , DLL и PlugIns

 

Введение

Рефлексия DLL (Reflective DLL Injection) — это техника загрузки динамических библиотек в процесс без использования стандартных API-функций, таких как LoadLibrary. Этот метод часто используется в сфере информационной безопасности, но также может быть полезен для легитимных целей, например, при разработке плагинов или модульных приложений.

Однако при реализации рефлексии DLL в Delphi разработчики могут столкнуться с проблемой сегментации памяти, которая приводит к аварийному завершению программы. В этой статье мы разберём причины этой проблемы и предложим несколько решений.


Проблема сегментации при рефлексии DLL

При рефлексивной загрузке DLL код библиотеки копируется в память целевого процесса, после чего выполняется вручную, минуя стандартные механизмы загрузки Windows. Основные причины ошибок сегментации:

  1. Некорректное выравнивание памяти — код DLL может требовать определённого выравнивания сегментов.
  2. Отсутствие релокации — если DLL загружается не по предпочтительному базовому адресу, необходимо выполнить релокацию.
  3. Ошибки в ручном разрешении импортов — если функции из других DLL не разрешены корректно, программа упадёт.

Решение: Корректная загрузка и выполнение DLL

1. Выделение памяти с правильным выравниванием

При копировании DLL в память важно учитывать выравнивание секций. В Windows обычно используется выравнивание по границе 4 КБ (страница памяти).

function AllocateMemoryAt(ProcessHandle: THandle; Size: NativeUInt; DesiredAddress: Pointer): Pointer;
var
  OldProtect: DWORD;
begin
  Result := VirtualAllocEx(ProcessHandle, DesiredAddress, Size, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  if Result = nil then
    RaiseLastOSError;
end;

2. Релокация DLL

Если DLL загружается не по предпочтительному адресу, необходимо исправить все относительные адреса.

procedure PerformRelocation(ImageBase: Pointer; NewBase: Pointer; ImageSize: Cardinal);
var
  NtHeaders: PImageNtHeaders;
  RelocDir: PImageDataDirectory;
  RelocBlock: PImageBaseRelocation;
  RelocEntry: PWord;
  i, j: Integer;
  Offset, TypeOffset: Integer;
  PatchAddr: PPointer;
begin
  NtHeaders := PImageNtHeaders(PtrUInt(ImageBase) + PImageDosHeader(ImageBase)^._lfanew);
  RelocDir := @NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

  if RelocDir.Size = 0 then Exit;

  RelocBlock := PImageBaseRelocation(PtrUInt(ImageBase) + RelocDir.VirtualAddress);

  while RelocBlock.VirtualAddress <> 0 do
  begin
    RelocEntry := PWord(PtrUInt(RelocBlock) + SizeOf(TImageBaseRelocation));

    for i := 0 to (RelocBlock.SizeOfBlock - SizeOf(TImageBaseRelocation)) div SizeOf(Word) - 1 do
    begin
      TypeOffset := RelocEntry^;
      Offset := TypeOffset and $0FFF;
      PatchAddr := PPointer(PtrUInt(ImageBase) + RelocBlock.VirtualAddress + Offset);

      if (TypeOffset shr 12) = IMAGE_REL_BASED_HIGHLOW then
        PatchAddr^ := PtrUInt(PatchAddr^) - PtrUInt(ImageBase) + PtrUInt(NewBase);

      Inc(RelocEntry);
    end;

    RelocBlock := PImageBaseRelocation(PtrUInt(RelocBlock) + RelocBlock.SizeOfBlock);
  end;
end;

3. Разрешение импортов

Перед выполнением кода DLL необходимо загрузить все зависимости и исправить таблицу импорта.

procedure ResolveImports(ImageBase: Pointer);
var
  NtHeaders: PImageNtHeaders;
  ImportDir: PImageDataDirectory;
  ImportDesc: PImageImportDescriptor;
  ThunkData: PImageThunkData;
  FuncName: PAnsiChar;
  LibHandle: HMODULE;
  ProcAddr: Pointer;
begin
  NtHeaders := PImageNtHeaders(PtrUInt(ImageBase) + PImageDosHeader(ImageBase)^._lfanew);
  ImportDir := @NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

  if ImportDir.Size = 0 then Exit;

  ImportDesc := PImageImportDescriptor(PtrUInt(ImageBase) + ImportDir.VirtualAddress);

  while ImportDesc.Name <> 0 do
  begin
    LibHandle := LoadLibraryA(PAnsiChar(PtrUInt(ImageBase) + ImportDesc.Name));
    if LibHandle = 0 then RaiseLastOSError;

    ThunkData := PImageThunkData(PtrUInt(ImageBase) + ImportDesc.FirstThunk);

    while ThunkData.AddressOfData <> 0 do
    begin
      if (ThunkData.Ordinal and IMAGE_ORDINAL_FLAG) <> 0 then
        ProcAddr := GetProcAddress(LibHandle, PAnsiChar(ThunkData.Ordinal and $FFFF))
      else
      begin
        FuncName := PAnsiChar(PtrUInt(ImageBase) + ThunkData.AddressOfData + 2);
        ProcAddr := GetProcAddress(LibHandle, FuncName);
      end;

      if ProcAddr = nil then RaiseLastOSError;

      PPointer(ThunkData)^ := ProcAddr;
      Inc(ThunkData);
    end;

    Inc(ImportDesc);
  end;
end;

Альтернативное решение: Использование LoadLibrary с маскировкой

Если рефлексия не является обязательным требованием, можно использовать стандартный LoadLibrary, но замаскировать факт загрузки DLL:

function StealthLoadLibrary(const DllPath: string): HMODULE;
var
  OldErrorMode: UINT;
begin
  OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
  try
    Result := LoadLibrary(PChar(DllPath));
  finally
    SetErrorMode(OldErrorMode);
  end;
end;

Этот способ проще и стабильнее, но менее скрытен.


Заключение

Рефлексия DLL — мощный, но сложный метод, требующий аккуратной работы с памятью. Основные проблемы (сегментация, релокация, импорты) решаются ручной корректировкой адресов и разрешением зависимостей.

Если вам не нужна полная скрытность, лучше использовать стандартные методы загрузки DLL. Однако если рефлексия необходима, приведённые выше примеры помогут избежать ошибок сегментации.

Рекомендация: Всегда тестируйте инжектор на различных версиях Windows, так как поведение API и структура PE-файлов могут отличаться.

Создано по материалам из источника по ссылке.

Рефлексия DLL в Delphi — это метод загрузки динамических библиотек без стандартных API, требующий ручного управления памятью и разрешения зависимостей для избежания ошибок сегментации.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: DLL и PlugIns ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-06 00:53:40/0.0063760280609131/0