У комп'ютерному програмуванні DLL-ін'єкція — це техніка виконання коду в адресному просторі іншого процесу шляхом примусового завантаження динамічної бібліотеки. DLL-інʼєкція часто використовується для впливу на поведінку іншої програми способом, не передбаченим її авторами. Наприклад, введений код може перехоплювати виклики системних функцій або зчитувати вміст текстових полів що містять паролі, що неможливо зробити звичайним способом. Програма, яка використовується для введення довільного коду в довільні процеси, називається DLL-ін'єктором.
Підходи в Microsoft Windows У Microsoft Windows існує кілька способів примусово завантажувати та виконувати код у DLL:
Динамічні бібліотеки перелічені в реєстрі за ключем: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs завантажуються в кожен процес який завантажує User32.dll під час початкового виклику цієї DLL. Починаючи з Windows Vista, AppInit_DLLs вимкнений за замовчуванням. Починаючи з Windows 7, AppInit_DLL інфраструктура підтримує підписання коду. Починаючи з Windows 8, вся функціональність AppInit_DLL вимкнена коли Secure Boot увімкнений, незалежно від того чи є dll підписаною, а також незалежно від налаштувань реєстру Windows. DLL перелічені за ключем: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs завантажуються в кожен процес який викликає такі Win32 API функції: CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW та WinExec. Це правильний спосіб для DLL ін'єкцій на Windows 10. DLL має бути підписаною дійсним сертифікатом. Функції для керування процесом на кшталт CreateRemoteThread або техніки ін'єкції коду як от AtomBombing, можуть бути використані для ін'єкції DLL в програму після запуску програми. Відкрийте дескриптор для потрібного процесу. Це можна зробити створивши процес або використовуючи щось створене цим процесом що відомо що існує – наприклад, вікно з передбачуваною назвою, або отримавши список працюючих процесів та шукаючи ім'я виконуваного файлу. Виділіть пам'ять в потрібному процесі, та запишіть туди назву DLL яку буде ін'єктовано. Цей крок можна пропустити якщо потрібне ім'я DLL вже визначене в процесі. Наприклад якщо процес пов'язується з бібліотеками User32.dll, GDI32.dll, Kernel32.dll або іншою бібліотекою ім'я якої закінчується на 32.dll, тоді є можливість завантажити бібліотеку з назвою 32.dll. Колись цей метод показав свою ефективність проти захисту процесу від DLL ін'єкції. Створіть потік у цільовому процесі, встановивши його стартову адресу на адресу функції LoadLibrary, і передайте як параметр адресу рядка з ім’ям DLL у пам’яті цього процесу.. Замість того, щоб записувати в цільовий процес ім’я DLL для завантаження і запускати новий потік з адреси функції LoadLibrary, можна записати безпосередньо код, який потрібно виконати, в адресний простір цільового процесу і запустити потік з адреси цього коду. Після цього операційна система викликає ініціалізаційну процедуру ін’єктованої DLL. Зверніть увагу, що без додаткових запобіжних заходів цей підхід може бути виявлений цільовим процесом, оскільки під час запуску потоку кожному завантаженому модулю надсилаються сповіщення DLL_THREAD_ATTACH. Перехоплення викликів у Windows за допомогою таких функцій, як SetWindowsHookEx. Використовуючи функції SuspendThread або NtSuspendThread, щоб призупинити всі потоки, а потім застосовуючи SetThreadContext або NtSetContextThread для зміни контексту існуючого потоку в застосунку з метою виконання ін’єктованого коду, який, у свою чергу, може завантажити DLL. Експлуатація обмежень проєктування Windows та застосунків, які викликають функції LoadLibrary або LoadLibraryEx, не вказуючи повний (кваліфікований) шлях до DLL, що завантажується. Підміна DLL, специфічної для застосунку, альтернативною бібліотекою, що має ті самі експортовані функції, що й оригінальна. DLL що здатні завантажувати себе. DLL копіюється в адресний простір цільового процесу, після чого виконання передається до точки входу DLL, яка завантажує себе безпосередньо з пам’яті.
Підходи на Unix-подібних системах На Unix-подібних операційних системах, де динамічний компонувальник базується на ld.so (у BSD) або ld-linux.so (у Linux), можна примусово під’єднувати довільні бібліотеки до нового процесу. Для цього достатньо вказати шлях до бібліотеки у змінній середовища LD_PRELOAD, яку можна встановити як глобально для всієї системи, так і окремо — лише для конкретного процесу.
Наприклад, у системі macOS така команда запускає програму prog, під’єднуючи до неї спільну бібліотеку з назвою test.dylib ще на етапі запуску програми:DYLD_INSERT_LIBRARIES="./test.dylib" DYLD_FORCE_FLAT_NAMESPACE=1 progТаку бібліотеку можна створити так само, як і інші спільні об'єкти . У GCC це передбачає компіляцію вихідного файлу, що містить нові глобальні змінні, які потрібно зв'язати, з -fpic або -fPIC опцією, та зв'язування з параметром -shared. Бібліотека має доступ до зовнішніх символів, оголошених у програмі, як і будь-яка інша бібліотека. Наприклад, у системі Linux ця команда запускає команду "prog" зі спільною бібліотекою з файлу "test.so", підключеною до неї під час запуску:LD_PRELOAD="./test.so" progМожна також застосовувати підходи, що базуються на використанні налагоджувача в Unix-подібних системах. https://web.archive.org/web/20100612084526/http://www.codeproject.com/KB/DLL/code_injection.aspx