Лучшие практики для DLL инъекций?
Предположим, я хочу внедрить DLL в процесс, который хочет редактировать значение адреса A каждые 250 мс. Мне нужно будет использовать DllMain, верно? Проблема в том, что мне не разрешают ждать внутри DllMain. Так я бы создал тему? Или это не обойти ограничение? Как бы я поступил так?
Кроме того, есть ли преимущества использования DLL-инъекций для редактирования памяти приложения по сравнению с использованием EXE?
Кроме того, какой размер стека должен быть в CreateThread? Что если он слишком маленький или слишком большой? Как я знаю, сколько мне нужно?
1 ответ
Из вашего описания кажется, что вы уже знаете, как заставить целевой процесс загрузить вашу DLL. Если мое предположение верно, то ответ прост: создайте поток из DLLMain и внедрите свою логику в поток. Если ваш код соответствует правилам, изложенным ниже, у вас все должно быть в порядке.
Этот документ описывает, что можно и нельзя делать в DLLMain и почему.
Как задокументировано, вы никогда не должны выполнять следующие задачи из DllMain:
- Вызовите LoadLibrary или LoadLibraryEx (прямо или косвенно). Это может вызвать тупик или сбой.
- Синхронизировать с другими потоками. Это может вызвать тупик.
- Получите объект синхронизации, который принадлежит коду, который ожидает получения блокировки загрузчика. Это может вызвать тупик.
- Инициализируйте потоки COM с помощью CoInitializeEx. При определенных условиях эта функция может вызывать LoadLibraryEx.
- Вызовите функции реестра. Эти функции реализованы в Advapi32.dll. Если Advapi32.dll не инициализирован до вашей DLL, DLL может получить доступ к неинициализированной памяти и вызвать сбой процесса.
- Вызови CreateProces. Создание процесса может загрузить другую DLL.
- Вызов ExitThread. Выход из потока во время отсоединения DLL может привести к повторному получению блокировки загрузчика, вызывая взаимоблокировку или сбой.
- Вызов CreateThread. Создание потока может работать, если вы не синхронизируете его с другими потоками, но это рискованно.
- Создайте именованный канал или другой именованный объект (только для Windows 2000). В Windows 2000 именованные объекты предоставляются библиотекой служб терминалов. Если эта DLL не инициализирована, вызов DLL может привести к сбою процесса.
- Используйте функцию управления памятью из динамического C-Run-Time (CRT). Если библиотека CRT не инициализирована, вызовы этих функций могут вызвать сбой процесса.
- Вызовите функции в User32.dll или Gdi32.dll. Некоторые функции загружают другую DLL, которая не может быть инициализирована.
- Используйте управляемый код.
Следующие задачи безопасны для выполнения в DllMain:
- Инициализируйте статические структуры данных и члены во время компиляции.
- Создать и инициализировать объекты синхронизации
- Выделите память и инициализируйте динамические структуры данных (избегая функций, перечисленных выше.)
- Настройте локальное хранилище потока (TLS).
- Открывайте, читайте и пишите в файлы.
- Вызовите функции в Kernel32.dll (кроме функций, перечисленных выше).
- Установите глобальные указатели на NULL, откладывая инициализацию динамических членов. В Microsoft Windows Vista™ вы можете использовать одноразовые функции инициализации, чтобы гарантировать, что блок кода выполняется только один раз в многопоточной среде.
Ваш второй вопрос мне менее понятен. Чтобы внедрить код в другой процесс, вы должны начать откуда-нибудь (браузер, exe и т. Д.), А затем записать в память целевого процесса, чтобы он загрузил вашу DLL.