Windows 驅動開發庫裡面提供了函數 LdrRegisterDllNotification , LdrUnregisterDllNotification , 可以讓你監視進程裝載/卸載DLL 的事件。 當你想在某個DLL被載入的時候Hook它的函數; 或者當你想在某個DLL推出之前做一些儲存清理工作; 或者當你想阻止某個DLL 被載入(比如外掛) .... 這個機制正可以派上用場 。
以下是程式碼範例如何使用 LdrRegisterDllNotification , LdrUnregisterDllNotification 監聽DLL裝載/卸載。
#include <Ntsecapi.h> // DDK<br />typedef const UNICODE_STRING* PCUNICODE_STRING;</p><p>typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA {<br /> ULONG Flags; //Reserved.<br /> PCUNICODE_STRING FullDllName; //The full path name of the DLL module.<br /> PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.<br /> PVOID DllBase; //A pointer to the base address for the DLL in memory.<br /> ULONG SizeOfImage; //The size of the DLL image, in bytes.<br />} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;</p><p>typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA {<br /> ULONG Flags; //Reserved.<br /> PCUNICODE_STRING FullDllName; //The full path name of the DLL module.<br /> PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.<br /> PVOID DllBase; //A pointer to the base address for the DLL in memory.<br /> ULONG SizeOfImage; //The size of the DLL image, in bytes.<br />} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;</p><p>typedef union _LDR_DLL_NOTIFICATION_DATA {<br /> LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;<br /> LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;<br />} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;</p><p>typedef const PLDR_DLL_NOTIFICATION_DATA PCLDR_DLL_NOTIFICATION_DATA;</p><p>typedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)(ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context);<br />typedef NTSTATUS (NTAPI *pfnLdrRegisterDllNotification)(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, void* Context, void **Cookie);<br />typedef NTSTATUS (NTAPI *pfnLdrUnregisterDllNotification)(void *Cookie);</p><p>#define LDR_DLL_NOTIFICATION_REASON_LOADED 1<br />#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2</p><p>VOID NTAPI MyLdrDllNotification(<br /> ULONG NotificationReason,<br /> PCLDR_DLL_NOTIFICATION_DATA NotificationData,<br /> PVOID Context<br />)<br />{<br />switch (NotificationReason)<br />{<br />case LDR_DLL_NOTIFICATION_REASON_LOADED:<br />printf ("Dll Loaded: %S/n", NotificationData->Loaded.FullDllName->Buffer);<br />break;<br />case LDR_DLL_NOTIFICATION_REASON_UNLOADED:<br />printf ("Dll Unloaded: %S/n", NotificationData->Unloaded.FullDllName->Buffer);<br />break;<br />}<br />}</p><p>int _tmain(int argc, _TCHAR* argv[])<br />{</p><p>HMODULE hModule = GetModuleHandleW(L"NTDLL.DLL");</p><p> // 取得函數指標<br />pfnLdrRegisterDllNotification pLdrRegisterDllNotification = (pfnLdrRegisterDllNotification)GetProcAddress(hModule, "LdrRegisterDllNotification");<br />pfnLdrUnregisterDllNotification pLdrUnregisterDllNotification = (pfnLdrUnregisterDllNotification)GetProcAddress(hModule, "LdrUnregisterDllNotification");<br />void *pvCookie = NULL;</p><p> // 初始化<br />pLdrRegisterDllNotification(0, MyLdrDllNotification, NULL, &pvCookie);</p><p>// 測試DLL 裝載<br />HMODULE hLoad = ::LoadLibraryW(L"mshtml.dll");<br />Sleep(1000);<br /> // 測試 DLL 卸載<br />::FreeLibrary(hLoad);</p><p> // 清除<br />if (pvCookie)<br />{<br />pLdrUnregisterDllNotification(pvCookie);<br />pvCookie = NULL;<br />}</p><p>return 0;<br />}<br />
運行程式, 輸出如下。可以證實以上代碼監聽了 mshtml.dll 的裝載和卸載。 而且系統自動裝載的其他DLL也被監視到。
Dll Loaded: C:/Windows/system32/mshtml.dll
Dll Loaded: C:/Windows/system32/msls31.dll
Dll Loaded: C:/Windows/system32/VERSION.dll
Dll Unloaded: C:/Windows/system32/mshtml.dll
Dll Unloaded: C:/Windows/system32/VERSION.dll
Dll Unloaded: C:/Windows/system32/msls31.dll
>> 原創文章的著作權屬於作者,轉載請註明出處和作者資訊(http://blog.csdn.net/WinGeek/), 謝謝。 <<