DLL-инъекция

DLL-инъекция (англ. DLL injection) — в программировании, метод, используемый для запуска кода в адресном пространстве другого процесса, заставляя его загружать динамически подключаемую библиотеку[1]. DLL-инъекции часто используются внешними программами, чтобы повлиять на поведение другой программы так, как её авторы не задумывали и не предполагали[1][2][3]. Например, внедрённый код может перехватывать системные вызовы функций[4][5] или прочитать содержимое текстовых полей пароля, что невозможно сделать обычным способом[6]. Программа, используемая для внедрения произвольного кода в произвольные процессы, называется DLL-инжектором.

Microsoft Windows

На Microsoft Windows имеется множество способов заставить процесс загрузить код в DLL-библиотеке против воли автора приложения:

  • DLL-файлы, указанные в списке системного реестра по ключу HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs, будут загружаться в каждом процессе, загружающем библиотеку User32.dll при её начальном вызове.[7][8][9]
  • DLL-файлы по ключу HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs будут загружаться в каждом процессе, которые вызывают функции Windows API CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW и WinExec. Это один из законных методов DLL-инъекции на Windows 10 при условии, что DLL-файл подписан корректным сертификатом.
  • Функции манипуляции процессами, такие как CreateRemoteThread, либо технологии внедрения кода, например AtomBombing[10], которых возможно использовать для внедрения DLL в программу после её запуска.[5][6][11][12][13][14]
  • Перехватывающие вызовы Windows, например SetWindowsHookEx.[2][5][6][15][16][17]
  • Применение функций SuspendThread или NtSuspendThread, чтобы приостановить все потоки, а также использование функций SetThreadContext или NtSetContextThread, чтобы модифицировать контекст существующих потоков в приложении с целью запустить внедряемый код, который сможет загрузить DLL.[4][18][19]
  • Эксплуатация ограничений Windows и приложений, вызывающих LoadLibrary или LoadLibraryEx без указания пути к загружаемой DLL.[20][21][22]
  • Оперирование прослойками системного уровня.
  • Подмена одного из зависимых DLL-файлов приложения на поддельный, который содержит те же экспортированные объекты, что и оригинал.[23]

Unix-подобные операционные системы

На Unix-подобных операционных системах, с помощью динамического линковщика, основанном на ld.so (на BSD) и на ld-linux.so (на Linux), можно подгружать произвольные библиотеки в новый процесс, указав путь к библиотеке с помощью переменной среды LD_PRELOAD, которую можно как назначить глобально, так и назначить конкретному процессу индивидуально.[24]

Например, на Linux-системе, данная команда запускает процесс "prog" вместе с разделяемой библиотекой "test.so", сопоставленной в него во время запуска:

LD_PRELOAD="./test.so" prog

Такие библиотеки создаются тем же способом, что и разделяемые объекты. Библиотека имеет доступ к внешним символам, указанным в программе, как и любая другая библиотека.


На macOS, данная команда запускает процесс "prog" вместе с разделяемой библиотекой "test.dylib", сопоставленной в него во время запуска:[25]

DYLD_INSERT_LIBRARIES="./test.dylib" DYLD_FORCE_FLAT_NAMESPACE=1 prog

В Unix-подобных системах также возможно использовать методы, основанные на отладочиках.[26]

Пример кода

Использование API-функции LoadLibrary

Пример функции, представленный ниже, использует метод DLL-инъекции, который эксплуатирует тот факт, что kernel32.dll сопоставлен с тем же адресом, что и почти все процессы. Поэтому, LoadLibrary (которая является функцией из kernel32.dll) также сопоставлена с тем же адресом. LoadLibrary также подходит для процедуры запуска потока, необходимой для CreateRemoteThread.

#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;
}

Примечания

  1. James Shewmaker. Analyzing DLL Injection. GSM Presentation. Bluenotch. Дата обращения: 31 августа 2008. Архивировано 3 декабря 2008 года.
  2. Iczelion. Tutorial 24: Windows Hooks. Iczelion's Win32 Assembly Homepage (August 2002). Дата обращения: 31 августа 2008. Архивировано 1 августа 2008 года.
  3. Rocky Pulley. Extending Task Manager with DLL Injection. CodeProject. CodeProject (May 19, 2005). Дата обращения: 1 сентября 2008. Архивировано 6 февраля 2009 года.
  4. Nasser R. Rowhani. DLL Injection and function interception tutorial. CodeProject. CodeProject (October 23, 2003). Дата обращения: 31 августа 2008.
  5. Ivo Ivanov. API hooking revealed. CodeProject. CodeProject (December 2, 2002). Дата обращения: 31 августа 2008.
  6. Robert Kuster. Three Ways to Inject Your Code into Another Process. CodeProject. CodeProject (August 20, 2003). Дата обращения: 31 августа 2008.
  7. Working with the AppInit_DLLs registry value (англ.). Microsoft (21 ноября 2006).
  8. Raymond Chen. AppInit_DLLs should be renamed Deadlock_Or_Crash_Randomly_DLLs (англ.). The Old New Thing. Microsoft (13 декабря 2007).
  9. dllmain.c (англ.). ReactOS. ReactOS Foundation.
  10. 'AtomBombing' Microsoft Windows Via Code Injection, Dark Reading (27 октября 2016).
  11. Trent Waddington. InjectDLL (англ.) (31 августа 2008).
  12. Dll Injection (англ.) (недоступная ссылка). DreamInCode.net. MediaGroup1 (31 августа 2008). Архивировано 2 сентября 2008 года.
  13. Greg Jenkins. DLL Injection Framework (англ.) (недоступная ссылка история ). Ring3 Circus (1 ноября 2007).
  14. Drew Benton. A More Complete DLL Injection Solution Using CreateRemoteThread (англ.). CodeProject. CodeProject (17 августа 2007).
  15. SetWindowsHookEx Function (англ.). Platform SDK for Windows XP SP2. Microsoft (31 августа 2008).
  16. AppInit_DLLs Registry Value and Windows 95 (англ.). Microsoft Help and Support. Microsoft (1 марта 2005).
  17. Dll Injection using SetWindowsHookEx() Method (англ.). Game Reversal (3 апреля 2008).
  18. SetThreadContext DLL Injection (англ.) (16 января 2007).
  19. Ben Botto. DLL Injector (англ.) (недоступная ссылка) (6 сентября 2008). Архивировано 7 февраля 2009 года.
  20. Insecure Library Loading Could Allow Remote Code Execution (англ.). Microsoft (20 апреля 2016).
  21. Secure loading of libraries to prevent DLL preloading attacks (англ.). Microsoft (10 июня 2011).
  22. Microsoft Security Advisory: Insecure library loading could allow remote code execution. support.microsoft.com. Дата обращения: 28 декабря 2021.
  23. Endpoint Protection - Symantec Enterprise. community.broadcom.com. Дата обращения: 28 декабря 2021.
  24. Торвальдс, Линус; Linus Torvalds, David Engel, Eric Youngdale, Peter MacDonald, Hongjiu Lu, Lars Wirzenius, Mitch D'Souza. ld.so/ld-linux.so – dynamic linker/loader (англ.) (недоступная ссылка). UNIX man pages (14 марта 1998). Архивировано 6 февраля 2009 года.
  25. Peter Goldsborough. The LD_PRELOAD trick. Peter Goldsborough. Дата обращения: 28 декабря 2021.
  26. Code Injection into Running Linux Application (англ.) ?. CodeProject (12 февраля 2009). Дата обращения: 28 декабря 2021.
This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.