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

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

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
2 894
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

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

Завершая хороший ответ MSalters:

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

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

Вы не можете вызвать LoadLibrary ("your.exe") из DllMain в вашей вспомогательной DLL - часть длинного списка вещей, которые вы не можете там делать. Это делает вашу вспомогательную DLL довольно сложной в использовании; это не может быть просто обертка / экспедитор,

MSalters 19.01.2009 19:15

Условия следующие:

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 () НЕ будет вызываться, когда вы его свяжете.

В вопросе конкретно упоминается загрузка исполняемого файла (.exe) с использованием LoadLibrary, а не DLL. Пожалуйста, перечитайте вопрос.

Ken White 13.09.2012 05:56

Ваше редактирование ничего не меняет. Нигде в вопросе не говорится, что файл был скомпилирован / связан как что-либо, кроме файла .exe. (Исполняемые файлы в Windows могут экспортировать функции так же, как DLL, без необходимости сначала компилировать их как DLL.)

Ken White 13.09.2012 06:10

Был задан вопрос: «Каковы условия (если они существуют), которые могут привести к выполнению функции exe DllMain при вызове LoadLibrary (и, возможно, снова при вызове FreeLibrary)?» Вот на что я отвечаю. Для автоматического вызова DllMain () необходимо скомпилировать двоичный файл как разделяемую библиотеку и установить в нем флаг DLL.

LRN 17.09.2012 08:03

Вы все еще упустили мою точку зрения. :-) Если у вас есть .EXE, DLLMain не будет вызываться автоматически. Конечно, у вас может быть функция с именем DLLMain, но это все равно, что назвать класс Car и ожидать, что вы сможете использовать его для доступа к приложению вашего врача. В .EXE нет функции auto-callable DLLMain(), поэтому вы не можете заставить ее автоматически вызываться при загрузке .EXE с LoadLibrary().

Ken White 17.09.2012 14:56

Вы говорите, что он упустил вашу точку зрения, но затем вы переходите к заявлению, которое в основном покрывается его ответом. Ответ от LRN, похоже, является надмножеством большей части вашего утверждения. Та часть, которой у него не было, была Зачем, она работает именно так, хотя Мартин упоминает об этом в своем ответе.

Loduwijk 31.05.2015 16:29

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

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

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

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

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

Другие вопросы по теме