Il DllMain di un .exe può essere chiamato?
Domanda
La mia domanda non è esattamente la stessa di questa (non è teorica, c'è solo un thread principale senza loop di messaggi, InitInstance ed ExitInstance non sono chiamate appropriate).
Sto usando un'app console senza loop di messaggi; questa app carica un exe con la funzione LoadLibrary, in modo che possa usare le sue funzioni esportate. Cattive notizie: la funzione DllMain dell'exe non viene chiamata (e ho verificato le tabelle dei simboli, usando un file def, DllMain appare correttamente); dice il documento viene chiamato se il modulo caricato è una DLL (anche cattivo).
Quali sono le condizioni (se esistono) che potrebbero portare all'esecuzione della funzione DllMain dell'exe quando viene chiamato LoadLibrary (e forse di nuovo quando viene chiamato FreeLibrary)?
Cordiali saluti
Soluzione
La condizione più ovvia è che il processo che chiama LoadLibrary () ottenga esplicitamente GetProcAddress (" DllMain ") e quindi lo chiami.
Altri suggerimenti
Le condizioni sono:
1) Il file binario caricato è stato compilato come DLL (quando si utilizza gcc / ld significa utilizzare l'opzione --shared
; se si utilizza --shared
, il file risultante essere una dll e non funzionerà, vedi sotto)
2) IMAGE_FILE_DLL
è impostato nell'intestazione del file PE del file binario da caricare. Se è impostato, il file è una dll e il linker di Windows chiamerà la sua funzione DllMain ()
quando collega questo file al tuo programma (non importa come sia collegato - LoadLibrary ()
in fase di esecuzione o -llibraryname
al momento della compilazione). Per questo il file deve anche soddisfare (1). Ma con questo flag il file binario che viene caricato non sarà eseguibile. Se IMAGE_FILE_DLL
non è impostato, DllMain ()
non verrà chiamato quando il file viene caricato nel programma.
Compilare la dll con --shared
e quindi rimuovere manualmente IMAGE_FILE_DLL
dalla sua intestazione (cioè usando l'editor esadecimale) non funzionerà - quando lo esegui, solo fdwReason
sarà un numero non definito ( 0x28ffd4
sulla mia macchina).
Aggiorna
Tutti i file DLL ed EXE su Windows sono file PE, la differenza è in che modo sono collegati e quali flag sono impostati nelle loro intestazioni. Questo è il motivo per cui scrivo file caricato
, non dll caricato
.
L'ultimo paragrafo descrive anche lo scenario in cui si compila il file come dll, quindi lo si trasforma in exe rovinando la sua intestazione. Non funziona.
La denominazione non ha nulla a che fare con questo (puoi scegliere qualsiasi nome, e con alcuni pexports
+ dlltool
puoi creare una libreria di importazione per un file .exe e essere in grado di collegarlo come -lexenamewithoutextension
Per chiarire:
- se lo compili senza
--shared
:-
IMAGE_FILE_DLL
non verrà impostato in esso, sarà eseguibile, ma DllMain () NON verrà chiamato quando lo colleghi.
-
- se lo compili con
--shared
:-
IMAGE_FILE_DLL
verrà impostato in esso, NON sarà eseguibile, ma DllMain () verrà chiamato quando lo colleghi.
-
- se lo compili senza
--shared
, quindi attiva il flagIMAGE_FILE_DLL
in esso manualmente:- NON sarà più eseguibile e nessun DllMain () verrà chiamato quando lo colleghi.
- se lo compili con
--shared
, quindi disattiva manualmente il flagIMAGE_FILE_DLL
:- sarà eseguibile, ma DllMain () verrà eseguito invece di main () e DllMain () NON verrà chiamato quando lo colleghi.
In effetti il ??Nome "quot DainMain" della funzione è completamente ignorata da Windows (la vecchia documentazione API Windows di Windows NT 3.x lo affermava esplicitamente).
Quando viene caricata una DLL non viene chiamata la funzione DllMain () ma la funzione che si trova nel punto di ingresso del file.
Naturalmente il linker creerà il file DLL in modo che DllMain () sia questa funzione.
Tuttavia, per i file EXE la funzione di inserimento (che chiamerà WinMain ()) si trova nel punto di ingresso.
Quindi è ovvio che Windows non può chiamare questa funzione quando si carica il file EXE come DLL.
Completamento della buona risposta di MSalters :
Quindi, quindi, chiama il " fake " DllMain con DLL_XXX_ATTACH subito dopo LoadLibrary e con DLL_XXX_DETACH appena prima di FreeLibrary ed effettua manualmente le altre chiamate.
Un'altra seguente implementazione sarebbe quella di costruire e caricare una DLL di interfaccia che potesse richiamare automaticamente l'EXE sul suo falso DllMain (non so se potesse funzionare); ma può essere più complicato della semplice chiamata manuale del falso DllMain in diversi casi. (impossibile LoadLibrary in un DllMain)