Прежде всего, извините, но мой ответ будет длиннее, чем другие ответы.
Я использую DLL-инъекцию много лет в другой версии операционной системы (от Windows NT 4.0 до Windows 7), и у меня не было временилюбая проблема с любым антивирусным сканером (включая Norton и McAfee в разных версиях).Поэтому я не согласен со Стивеном Клири (см. Его ответ) в этом аспекте.
Использование CreateRemoteThread()
на самом деле является лишь одним из способов. AppInit_DLLs - это еще один способ.У обоих есть свои преимущества и недостатки.Основным преимуществом AppInit_DLLs является простота внедрения DLL в любой процесс.Основными недостатками подхода AppInit_DLLs являются:
- Все приложения с графическим интерфейсом будут загружать DLL.Если вы хотите загрузить его только в одном процессе, таком как explorer.exe , вы не сможете этого сделать.Таким образом, рабочее пространство всех процессов GUI будет увеличено вашей DLL.Ошибка в вашей DLL (особенно внутри
DllMain
или в любой зависимой DLL вашей DLL) может привести к сбою многих процессов, о которых вы в данный момент не знаете. - Вы не можете внедрить свою DLL с учетом подхода AppInit_DLLsв консольном приложении или в любом EXE-файле, который не зависит от User32.dll.
- Вы должны быть очень осторожны внутри вашего
DllMain
, потому что он будет называться до User32.dllбудет полностью инициализирован.Таким образом, безопасная DLL, которую вы можете использовать внутри DllMain
вашей DLL - Kernel32.dll.
Что касается CreateRemoteThread()
, можно запустить дополнительный поток в процессе.Основная проблема CreateRemoteThread()
заключается в том, что его параметр lpStartAddress
должен быть адресом удаленного процесса .Поэтому необходимо использовать функции OpenProcess
, VirtualAllocEx
и WriteProcessMemory
для записи некоторой информации в память процесса назначения.Чтобы иметь возможность открыть процесс, необходимо включить привилегию отладки.Если вы хотите сделать только 2 + 2 внутри процесса назначения, вы можете скопировать соответствующий двоичный код непосредственно в процесс назначения.Вся настоящая интересная работа может быть выполнена с использованием некоторого Windows API.Так что в основном никто не копирует код.Вместо этого один вызов LoadLibrary("MyPath\\MyDll.dll"
) внутри процесса назначения.Поскольку прототип LoadLibrary
совпадает с прототипом ThreadProc
из CreateThread
, вы можете назвать LoadLibrary
как ThreadProc
из CreateRemoteThread()
.Этот способ имеет имя DLL Injection .
Я рекомендую использовать эту DLL Injection , только если она действительно требуется .Если у вашего конечного приложения есть какой-то другой способ, например, плагины для загрузки вашей DLL внутри процесса, вы должны использовать этот способ вместо DLL Injection.
Некоторые общие проблемы, которые вам придется решать после того, как у вас будет рабочий примерИнъекция DLL.Эти проблемы вы не видите в первый раз, но после длительного использования вашего приложения вы увидите его важность:
- Вы должны найти момент, когда процесс назначения уже запущен, прежде чем выможно использовать
CreateRemoteThread()
. - Приложение назначения должно быть уже инициализировано перед вызовом
CreateRemoteThread()
.Так что не стоит использовать CreateRemoteThread()
слишком рано.В случае explorer.exe вы можете использовать запуск вашей небольшой триггерной программы из ключа реестра Run.На данный момент файл explorer.exe полностью подготовлен для внедрения DLL. - Следует учитывать 64-разрядную версию Windows.
- Не забывайте о перемещении DLL внутри целевого процесса.Будьте осторожны, чтобы ваша DLL могла быть загружена в процессе назначения по другому адресу, как в вашем процессе.В большинстве случаев это хорошая идея, чтобы выбрать хороший базовый адрес (вариант компоновщика) для вашей DLL, которую вы будете вставлять.Kernel32.dll иногда (очень редко) может быть загружен по другому адресу, как в исходном процессе.Вы можете создать код DLL-инъекции, в котором нет этой проблемы.
- Службы терминалов изолируют каждый сеанс терминала по проекту.Следовательно,
CreateRemoteThread
завершается ошибкой, если целевой процесс находится в другом сеансе, чем вызывающий процесс.Проблема, которую вы можете увидеть в XP (которая не подключена к домену) или особенно в Vista или Windows 7, если вы попытаетесь внедрить DLL из службы Windows.Чтобы решить эту проблему, вы должны сделать DLL Injection либо из процесса, запущенного в том же терминальном сеансе, что и целевой процесс, либо вам нужно переключить текущий сеанс перед использованием CreateRemoteThread
.Ваш процесс должен иметь привилегию SE_TCB_NAME
и использовать SetTokenInformation
с параметром TokenSessionId
.Чтобы получить идентификатор сеанса процесса назначения, вы можете использовать разные методы.Функции с префиксом WTS (например, WTSGetActiveConsoleSessionId
) могут быть очень полезными.
Так что все не очень просто, но это действительно интересная тема, где вы можете многое узнать об операционной системе.Вам следует потратить немного времени на анализ вашей проблемы и различные способы ее решения, прежде чем выбрать один из способов, который соответствует требованиям вашего проекта и начать программирование.