В компьютерном программировании , DLL инъекция является методом , используемым для запуска кода в пределах адресного пространства другого процесса , заставляя его загрузить динамическую библиотеку . [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 во время первоначального вызова этой DLL. [7] [8] [9] Начиная с Windows Vista , AppInit_DLL по умолчанию отключены. [10] Начиная с Windows 7, инфраструктура AppInit_DLL поддерживает подписывание кода . Начиная с Windows 8 , вся функциональность AppInit_DLL отключается, когда включена безопасная загрузка , независимо от подписи кода или настроек реестра. [11] - DLL, перечисленные в разделе реестра
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs
, загружаются в каждый процесс, который вызывает функции Win32 API CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW и WinExec. Это правильный способ использовать легальную инъекцию DLL в текущей версии Windows - Windows 10. DLL должна быть подписана действующим сертификатом. - Функции управления процессами, такие как CreateRemoteThread, или методы внедрения кода, такие как AtomBombing [12], могут использоваться для внедрения библиотеки DLL в программу после ее запуска. [5] [6] [13] [14] [15] [16]
- Откройте дескриптор целевого процесса. Это можно сделать, запустив процесс [17] [18] или отключив что-то, созданное этим процессом, о существовании которого известно, - например, окно с предсказуемым заголовком, [19] или получив список запущенных процессов. [20] и поиск имени файла целевого исполняемого файла. [21]
- Выделите часть памяти в целевом процессе [22], и в него будет записано имя внедряемой DLL. [13] [23]
- Этот шаг можно пропустить, если подходящее имя DLL уже доступно в целевом процессе. Например, если процесс ссылается на ' User32.dll ', ' GDI32.dll ', ' Kernel32.dll ' или любую другую библиотеку, имя которой заканчивается на '32 .dll ', можно будет загрузить библиотеку с именем '32. .dll '. Ранее было продемонстрировано, что этот метод эффективен против метода защиты процессов от внедрения DLL. [24]
- Создайте новый поток в целевом процессе [25] с начальным адресом потока, установленным как адрес LoadLibrary, и аргументом, установленным на адрес строки, только что загруженной в целевой объект. [13] [26]
- Вместо того, чтобы записывать имя загружаемой библиотеки DLL в целевой объект и запускать новый поток в LoadLibrary, можно записать код, который необходимо выполнить, в целевой объект и запустить поток с этого кода. [6]
- Затем операционная система вызывает процедуру инициализации внедренной DLL. [13] [27]
- Обратите внимание, что без мер предосторожности этот подход может быть обнаружен целевым процессом из-за уведомлений DLL_THREAD_ATTACH, отправляемых каждому загруженному модулю при запуске потока. [27]
- Windows , закрепляя вызовы , такие , как SetWindowsHookEx. [2] [5] [6] [28] [29] [30]
- Используйте функцию SuspendThread или NtSuspendThread, чтобы приостановить все потоки, а затем используйте функцию SetThreadContext или NtSetContextThread, чтобы изменить контекст существующего потока в приложении для выполнения внедренного кода, который, в свою очередь, может загрузить DLL. [4] [31] [32]
- Используйте ограничения дизайна в Windows и приложениях, которые вызывают функцию LoadLibrary или LoadLibraryEx без указания полного пути к загружаемой DLL. [33] [34] [35]
- Операционная система на уровне прокладки .
- Замена библиотеки DLL для конкретного приложения мошеннической заменой, которая реализует тот же экспорт функций, что и оригинал. [36]
Подходы к Unix-подобным системам [ править ]
В Unix-подобных операционных системах с динамическим компоновщиком на основе ld.so (в BSD ) и ld-linux.so (в Linux ) произвольные библиотеки могут быть связаны с новым процессом, указав путь к библиотеке в переменной среды LD PRELOAD. , который можно настроить глобально или индивидуально для одного процесса. [37]
Например, в системе Linux эта команда запускает команду «prog» с разделяемой библиотекой из файла «test.so», связанного с ней во время запуска:
LD_PRELOAD = "./test.so" прога
Такую библиотеку можно создать так же, как и другие общие объекты . В GCC это включает в себя компиляцию исходного файла, содержащего новые глобальные объекты, которые необходимо связать, с параметром -fpic или -fPIC , [38] и связывание с параметром -shared . [39] Библиотека имеет доступ к внешним символам, объявленным в программе, как и любая другая библиотека.
В macOS следующая команда запускает команду «prog» с разделяемой библиотекой из файла «test.dylib», связанной с ней во время запуска: [40]
DYLD_INSERT_LIBRARIES = "./test.dylib" DYLD_FORCE_FLAT_NAMESPACE = 1 прога
Также возможно использовать методы на основе отладчика в Unix-подобных системах. [41]
Образец кода [ править ]
Использование функции API LoadLibrary [ править ]
В приведенном ниже примере функции используется метод внедрения DLL, который использует тот факт, что kernel32.dll отображается на один и тот же адрес почти во всех процессах. Поэтому LoadLibrary (которая является функцией kernel32.dll) также отображается на тот же адрес. LoadLibrary также подходит для процедуры запуска потока, требуемой CreateRemoteThread.
#include <windows.h>РУЧКА inject_DLL ( Const символ * имя_файла , INT ПИД ) { HANDLE h_process = OpenProcess ( PROCESS_ALL_ACCESS , FALSE , ПИД ); // получение дескриптора целевого процесса char fullDLLPath [ _MAX_PATH ]; // получение полного пути к файлу dll GetFullPathName ( имя_файла , _MAX_PATH , fullDLLPath , NULL ); LPVOID DLLPath_addr = VirtualAllocEx ( h_process , NULL , _MAX_PATH , MEM_COMMIT | MEM_RESERVE , PAGE_READWRITE ); // выделение памяти в целевом процессе WriteProcessMemory ( h_process , DLLPath_addr , fullDLLPath , strlen ( fullDLLPath ), NULL ); // записываем путь к dll в эту память LPVOID LoadLib_addr = GetProcAddress ( GetModuleHandle ( "Kernel32" ), // получение адреса LoadLibraryA (то же самое для "LoadLibraryA" ); // все процессы), чтобы начать выполнение на нем HANDLE h_rThread = CreateRemoteThread ( h_process , NULL , 0 , // запуск потока удаленного выполнения в LoadLibraryA ( LPTHREAD_START_ROUTINE ) LoadLib_addr , DLLPath_addr , 0 , NULL ); // и передавая путь к dll в качестве аргумента WaitForSingleObject ( h_rThread , БЕСКОНЕЧНЫЙ ); // ждем завершения DWORD exit_code ; GetExitCodeThread ( h_rThread , & exit_code ); // получение возвращаемого значения, т. е. дескриптора модуля, // возвращаемого LoadLibraryA CloseHandle ( h_rThread ); // освобождение дескриптора внедренного потока VirtualFreeEx ( h_process , DLLPath_addr , 0 , MEM_RELEASE ); // ... и память, выделенная для пути к DLL, CloseHandle ( h_process ); // ... и дескриптор целевого процесса return ( HANDLE ) код_выхода ; }
Ссылки [ править ]
- ^ a b Джеймс Шумейкер (2006). «Анализ внедрения DLL» (PDF) . Презентация GSM . Голубое небо. Архивировано из оригинального (PDF) 3 декабря 2008 года . Проверено 31 августа 2008 года .
- ^ a b Iczelion (август 2002 г.). «Учебник 24: ловушки Windows» . Домашняя страница сборки Win32 Iczelion . Архивировано из оригинала на 1 августа 2008 года . Проверено 31 августа 2008 года .
- ↑ Rocky Pulley (19 мая 2005 г.). «Расширение диспетчера задач с помощью внедрения DLL» . CodeProject . CodeProject. Архивировано из оригинала на 6 февраля 2009 года . Проверено 1 сентября 2008 года .
- ^ a b Насер Р. Роухани (23 октября 2003 г.). "Учебник по внедрению DLL и перехвату функций" . CodeProject . CodeProject . Проверено 31 августа 2008 года .
- ^ a b c Иво Иванов (2 декабря 2002 г.). «Обнаружен перехват API» . CodeProject . CodeProject . Проверено 31 августа 2008 года .
- ^ a b c d Роберт Кустер (20 августа 2003 г.). «Три способа внедрения вашего кода в другой процесс» . CodeProject . CodeProject . Проверено 31 августа 2008 года .
- ^ «Работа со значением реестра AppInit_DLLs» . Справка и поддержка Microsoft . Microsoft. 21 ноября 2006 . Проверено 31 августа 2008 года .
- ↑ Раймонд Чен (13 декабря 2007 г.). «AppInit_DLLs следует переименовать в Deadlock_Or_Crash_Randomly_DLLs» . Старая новая вещь . Microsoft . Проверено 31 августа 2008 года . CS1 maint: обескураженный параметр ( ссылка )
- ^ "dllmain.c" . ReactOS . Фонд ReactOS. 8 июля 2008 . Проверено 31 августа 2008 года .[ постоянная мертвая ссылка ]
- ^ AppInit_DLL в Windows 7 и Windows Server 2008 R2
- ^ «AppInit DLL и безопасная загрузка» . MSDN . Проверено 29 марта 2016 года .
- ^ " ' AtomBombing' Microsoft Windows через внедрение кода" . Темное чтение . Проверено 20 апреля 2017 года .
- ^ a b c d Трент Уоддингтон. "InjectDLL" . Проверено 31 августа 2008 года .
- ^ "Dll Injection" . DreamInCode.net . MediaGroup1. 4 мая 2006 года архивации с оригинала на 2 сентября 2008 года . Проверено 31 августа 2008 года .
- ↑ Грег Дженкинс (ноябрь 2007 г.). «Фреймворк для внедрения DLL» . Ring3 Circus . WordPress . Проверено 31 августа 2008 года .
- ↑ Дрю Бентон (17 августа 2007 г.). «Более полное решение для внедрения DLL с использованием CreateRemoteThread» . CodeProject . CodeProject . Проверено 1 сентября 2008 года .
- ^ "CreateProcess" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "ПРОЦЕСС_ИНФОРМАЦИЯ" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "Функция GetWindowThreadProcessId" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "EnumProcesses" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "GetModuleBaseName" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "VirtualAllocEx" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "WriteProcessMemory" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "Аванпост обхода самозащиты через усовершенствованную инъекцию DLL с уязвимостью кражи дескрипторов" . Matousec . 1 декабря 2006 . Проверено 31 августа 2008 года .
- ^ "CreateRemoteThread" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "LoadLibrary" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ a b "DllMain" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ "Функция SetWindowsHookEx" . Платформа SDK для Windows XP SP2 . Microsoft . Проверено 31 августа 2008 года .
- ^ «Значение реестра AppInit_DLL и Windows 95» . Справка и поддержка Microsoft . Microsoft. 1 марта 2005 . Проверено 31 августа 2008 года .
- ^ «Внедрение DLL с использованием метода SetWindowsHookEx ()» . Смена игры . 3 апреля 2008 . Проверено 1 сентября 2008 года .
- ^ "SetThreadContext DLL Injection" . 16 января 2007 . Проверено 1 сентября 2008 года .
- ↑ Бен Ботто (6 сентября 2008 г.). «Инжектор DLL» . Архивировано из оригинала на 7 февраля 2009 года . Проверено 1 сентября 2008 года .
- ^ «Небезопасная загрузка библиотеки может позволить удаленное выполнение кода» . Microsoft . 10 июня 2011 . Проверено 20 апреля 2016 года .
- ^ "Безопасная загрузка библиотек для предотвращения атак предварительной загрузки DLL" . Microsoft . 10 июня 2011 . Проверено 8 августа 2012 года .
- ^ «Microsoft Security Advisory: небезопасная загрузка библиотеки может позволить удаленное выполнение кода» . Microsoft . 10 июня 2011 . Проверено 20 апреля 2016 года .
- ^ Николас Falliere (26 сентября 2010). «Заражение Stuxnet проектов Step 7» . Symantec.
- ^ Линус Торвальдс ; Дэвид Энгель; Эрик Янгдейл; Питер Макдональд; Хунцзю Лу; Ларс Вирзениус; Митч Д'Суза (14 марта 1998 г.). «ld.so/ld-linux.so - динамический компоновщик / загрузчик» . Справочные страницы UNIX . Архивировано из оригинала на 6 февраля 2009 года . Проверено 31 августа 2008 года . CS1 maint: обескураженный параметр ( ссылка )
- ^ «Параметры генерации кода» . Использование коллекции компиляторов GNU (GCC) . Фонд свободного программного обеспечения . Проверено 31 августа 2008 года .
Сгенерируйте позиционно-независимый код (PIC), подходящий для использования в разделяемой библиотеке, если поддерживается для целевой машины.
sqq.
-fpic
- ^ "Параметры ссылки" . Использование коллекции компиляторов GNU (GCC) . Фонд свободного программного обеспечения . Проверено 31 августа 2008 года .
Создайте общий объект, который затем можно связать с другими объектами, чтобы сформировать исполняемый файл.
sqq.
-shared
- ^ "Уловка LD_PRELOAD" . Питер Голдсборо . Проверено 17 мая 2017 года .
- ↑ Григорий Шпитальник (12 февраля 2009 г.). «Внедрение кода в работающее приложение Linux» . Код проекта . Проверено 18 ноября 2010 года .