Nehmen Sie eine Standard-Windows-Anwendung. Es lädt eine DLL mit LoadLibrary, um eine Funktion darin aufzurufen (wir nennen das DLL_A). Diese Funktion lädt eine andere DLL (wir nennen sie DLL_B). Die Anwendung entlädt jetzt die DLL_A DLL mithilfe von FreeLibrary, da sie nicht mehr benötigt wird.
Die Frage ist: Ist DLL_B noch im Speicher und geladen?
Ist das etwas, auf das ich mich verlassen kann, oder ist es undokumentiert?
Nein. DLL_B
wird nicht entladen. Der Aufruf LoadLibrary()
von DLL_A
erhöht den Ladezähler für DLL_B
. Da für FreeLibrary()
kein entsprechender DLL_B
-Aufruf vorhanden ist, wird der Refcount nicht auf Null gesetzt.
Aus der LoadLibrary () -Dokumentation:
Das System behält einen pro-Prozess bei Referenzzähler auf allen geladenen Modulen. Durch den Aufruf von LoadLibrary wird der Wert von Referenzzahl Anrufen der FreeLibrary oder FreeLibraryAndExitThread-Funktion dekrementiert den Referenzzähler. Das System entlädt ein Modul, wenn es Referenzzählung erreicht Null oder wann der Prozess endet (unabhängig von die Referenzzahl).
Sie haben ein Handle-Leck in dem Fall:
%Vor%Kein Code wird implizit von einem Modul ausgeführt, das entladen wird, um die geladenen Module zu entladen.
Da kein Code ausgeführt wird, um die Referenzzählung zu verringern, wird das Modul B niemals entladen.
Hier sind die Regeln zum Laden / Entladen von DLLs:
Immer noch im Speicher vs noch geladen:
Es gibt keine Garantie, dass Ihr Modul zu einem bestimmten Zeitpunkt aus dem Speicher freigegeben wird, wenn die Referenz 0 erreicht. Sie sollten das Modul jedoch so betrachten, als ob es entladen wird, wenn der Referenzzähler 0 erreicht.
Stoppen des Entladens der DLL:
Um das Entladen der DLL zu erzwingen, können Sie
versuchenBearbeiten:
Sie haben erwähnt, dass Ihr Ziel es ist, Code in das laufende Programm zu injettieren und dass Sie den Griff absichtlich durchlecken wollten.
Das ist in Ordnung, aber wenn Sie diese Operation viel ausführen, kann dies zu einem Absturz in Ihrem Quellprogramm führen, weil zu viele Handles verwendet werden oder schließlich zu viel Speicher verwendet wird.
Sie können FALSE von Ihrem DllMain zurückgeben, damit es nicht geladen wird, damit Sie keinen Speicher verschwenden. Sie tun dies, wenn fdwReason DLL_PROCESS_ATTACH ist. Sie können hier mehr darüber lesen .
Wenn Sie versuchen, eine DLL zu emulieren und Ihre eigenen zusätzlichen Funktionen hinzuzufügen, müssen Sie alle Funktionen implementieren, die von der Quell-DLL implementiert werden, und jeden Aufruf an die Quell-DLL delegieren.
Lesen Sie den Abschnitt Hinweise für eine detaillierte Erläuterung.
Der wichtigste Punkt ist:
Das System behält für jedes geladene Modul eine pro-process-Referenzzählung bei
und weiter unten
Wenn die Referenzzählung eines Moduls null erreicht oder der Prozess beendet wird, entlädt das System das Modul aus dem Adressraum des Prozesses
Von MSDN :
Gibt das geladene DLL-Modul (dynamic-link library) frei und dekrementiert bei Bedarf die Anzahl der Referenzen. Wenn der Referenzzähler null erreicht, wird das Modul aus dem Adressraum des aufrufenden Prozesses entladen und das Handle ist nicht mehr gültig.
DLLs in Windows werden als Referenz gezählt. Wenn A entladen ist, dekrementieren Sie die Referenzzählung auf A, wenn sie Null erreicht, wird sie entladen und (unter der Annahme, dass keine Fehler im Code vorhanden sind) die Referenzzahl auf B verringern. Wenn die Refcount auf B auf Null geht, wird sie entladen . Es ist möglich, dass DLL C einen Refcount auf B hat, und das Entladen von A wird B nicht entladen.