Можно ли вызвать DllMain .exe? - PullRequest
       14

Можно ли вызвать DllMain .exe?

1 голос
/ 16 января 2009

Мой вопрос не совсем такой, как этот (это не теоретически, есть только главный поток без цикла сообщений, InitInstance и ExitInstance не являются подходящими вызовами).

Я использую консольное приложение без цикла сообщений; Это приложение загружает исполняемый файл с функцией LoadLibrary, чтобы он мог использовать свои экспортированные функции. Плохая новость: функция DllMain в exe не вызывается (и я проверил таблицы символов, используя файл def, DllMain отображается правильно); документ говорит: он вызывается, если загруженный модуль является DLL (слишком плохо).

Каковы условия (если они существуют), которые могут привести к выполнению функции DllMain exe при вызове LoadLibrary (и, возможно, снова при вызове FreeLibrary)?

С наилучшими пожеланиями

Ответы [ 4 ]

4 голосов
/ 16 января 2009

Наиболее очевидным условием является то, что процесс, вызывающий LoadLibrary (), явно получает GetProcAddress ("DllMain"), а затем вызывает его.

3 голосов
/ 13 сентября 2012

Условия:

1) Загружаемый бинарный файл был скомпилирован как DLL (при использовании gcc / ld это означает использование опции --shared; если вы используете --shared, результирующий файл будет dll и не будет работать, см. Ниже)

2) IMAGE_FILE_DLL устанавливается в заголовке PE-файла загружаемого двоичного файла. Если он установлен, файл является dll, и компоновщик Windows будет вызывать для вас функцию DllMain(), когда связывает этот файл с вашей программой (не имеет значения, как он связан - LoadLibrary() во время выполнения или -llibraryname при компиляции время). Для этого файл также должен удовлетворять (1). Но с этим флагом загружаемый двоичный файл не будет работать. Если IMAGE_FILE_DLL не задано, DllMain() не будет вызываться при загрузке файла в вашу программу.

Компиляция dll с помощью --shared и последующее ручное удаление IMAGE_FILE_DLL из его заголовка (т. Е. С помощью шестнадцатеричного редактора) не будет работать - при его запуске будет выполняться только DllMain(), и fdwReason будет неопределенный номер (0x28ffd4 на моей машине).

Обновление

Все файлы DLL и EXE в Windows являются PE-файлами, разница в том, как они связаны и какие флаги установлены в их заголовках. Вот почему я пишу file being loaded, а не dll being loaded.

В последнем абзаце также описывается сценарий, в котором вы компилируете файл как dll, а затем превращаете его в exe, связываясь с его заголовком. Это не работает.

Именование не имеет к этому никакого отношения (вы можете выбрать любое имя, и, немного поработав pexports + dlltool, вы можете создать библиотеку импорта для файла .exe и связать ее как -lexenamewithoutextension

уточнить:

  • , если вы скомпилируете его без --shared:
    • IMAGE_FILE_DLL не будет установлен в нем, он будет работать, но DllMain () НЕ будет вызываться, когда вы связываете его.
  • , если вы скомпилируете его с --shared:
    • IMAGE_FILE_DLL будет установлен в нем, он НЕ будет работать, но DllMain () будет вызываться при его привязке.
  • если вы скомпилируете его без --shared, то включите флаг IMAGE_FILE_DLL в нем вручную:
    • он больше не будет работать, и при его связывании DllMain () не будет вызываться.
  • если вы скомпилируете его с помощью --shared, а затем вручную отключите флаг IMAGE_FILE_DLL:
    • он будет запущен, но DllMain () будет выполняться вместо main (), и DllMain () НЕ будет вызываться при его связывании.
1 голос
/ 22 августа 2013

Действительно, имя «DllMain» функции полностью игнорируется Windows (старая документация по Windows API для Windows NT 3.x указала это явно).

Когда загружается DLL, вызывается не функция DllMain (), а функция, которая находится в точке входа файла.

Конечно, компоновщик создаст файл DLL таким образом, что DllMain () является этой функцией.

Однако для файлов EXE функция входа (которая будет вызывать WinMain ()) находится в точке входа.

Таким образом, очевидно, что Windows не может вызвать эту функцию при загрузке EXE-файла как DLL.

0 голосов
/ 16 января 2009

Завершение хорошего ответа MSalters :

Итак, затем вызовите «фальшивый» DllMain с DLL_XXX_ATTACH сразу после LoadLibrary и с DLL_XXX_DETACH непосредственно перед FreeLibrary и выполните другие вызовы вручную.

Другая следующая реализация будет состоять в том, чтобы создать и загрузить интерфейсную DLL, которая могла бы автоматически вызывать EXE на своем поддельном DllMain (я не знаю, может ли это работать); но это может быть более сложным, чем просто ручной вызов поддельного DllMain в ряде случаев. (невозможно загрузить библиотеку в DllMain)

...