Windows 驱动开发库里面提供了函数 LdrRegisterDllNotification , LdrUnregisterDllNotification , 可以让你监视进程装载/卸载DLL 的事件。 当你想在某个DLL被加载的时候Hook它的函数; 或者当你想在某个DLL推出之前做一些保存清理工作; 或者当你想阻止某个DLL 被加载(比如外挂) .... 这个机制正可以派上用场 。
以下是代码示例如何使用 LdrRegisterDllNotification , LdrUnregisterDllNotification 监听DLL装载/卸载。
view plaincopy to clipboardprint?
#include <Ntsecapi.h> // DDK
typedef const UNICODE_STRING* PCUNICODE_STRING;
typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA {
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;
typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA {
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;
typedef union _LDR_DLL_NOTIFICATION_DATA {
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;
typedef const PLDR_DLL_NOTIFICATION_DATA PCLDR_DLL_NOTIFICATION_DATA;
typedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)(ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context);
typedef NTSTATUS (NTAPI *pfnLdrRegisterDllNotification)(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, void* Context, void **Cookie);
typedef NTSTATUS (NTAPI *pfnLdrUnregisterDllNotification)(void *Cookie);
#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2
VOID NTAPI MyLdrDllNotification(
ULONG NotificationReason,
PCLDR_DLL_NOTIFICATION_DATA NotificationData,
PVOID Context
)
{
switch (NotificationReason)
{
case LDR_DLL_NOTIFICATION_REASON_LOADED:
printf ("Dll Loaded: %S\n", NotificationData->Loaded.FullDllName->Buffer);
break;
case LDR_DLL_NOTIFICATION_REASON_UNLOADED:
printf ("Dll Unloaded: %S\n", NotificationData->Unloaded.FullDllName->Buffer);
break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hModule = GetModuleHandleW(L"NTDLL.DLL");
// 取得函数指针
pfnLdrRegisterDllNotification pLdrRegisterDllNotification = (pfnLdrRegisterDllNotification)GetProcAddress(hModule, "LdrRegisterDllNotification");
pfnLdrUnregisterDllNotification pLdrUnregisterDllNotification = (pfnLdrUnregisterDllNotification)GetProcAddress(hModule, "LdrUnregisterDllNotification");
void *pvCookie = NULL;
// 初始化
pLdrRegisterDllNotification(0, MyLdrDllNotification, NULL, &pvCookie);
// 测试DLL 装载
HMODULE hLoad = ::LoadLibraryW(L"mshtml.dll");
Sleep(1000);
// 测试 DLL 卸载
::FreeLibrary(hLoad);
// 清除
if (pvCookie)
{
pLdrUnregisterDllNotification(pvCookie);
pvCookie = NULL;
}
return 0;
}
#include <Ntsecapi.h> // DDK
typedef const UNICODE_STRING* PCUNICODE_STRING;
#include <Ntsecapi.h> // DDK
typedef const UNICODE_STRING* PCUNICODE_STRING;
typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA {
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;
typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA {
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;
typedef union _LDR_DLL_NOTIFICATION_DATA {
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;
typedef const PLDR_DLL_NOTIFICATION_DATA PCLDR_DLL_NOTIFICATION_DATA;
typedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)(ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context);
typedef NTSTATUS (NTAPI *pfnLdrRegisterDllNotification)(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, void* Context, void **Cookie);
typedef NTSTATUS (NTAPI *pfnLdrUnregisterDllNotification)(void *Cookie);
#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2
VOID NTAPI MyLdrDllNotification(
ULONG NotificationReason,
PCLDR_DLL_NOTIFICATION_DATA NotificationData,
PVOID Context
)
{
switch (NotificationReason)
{
case LDR_DLL_NOTIFICATION_REASON_LOADED:
printf ("Dll Loaded: %S\n", NotificationData->Loaded.FullDllName->Buffer);
break;
case LDR_DLL_NOTIFICATION_REASON_UNLOADED:
printf ("Dll Unloaded: %S\n", NotificationData->Unloaded.FullDllName->Buffer);
break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hModule = GetModuleHandleW(L"NTDLL.DLL");
// 取得函数指针
pfnLdrRegisterDllNotification pLdrRegisterDllNotification = (pfnLdrRegisterDllNotification)GetProcAddress(hModule, "LdrRegisterDllNotification");
pfnLdrUnregisterDllNotification pLdrUnregisterDllNotification = (pfnLdrUnregisterDllNotification)GetProcAddress(hModule, "LdrUnregisterDllNotification");
void *pvCookie = NULL;
// 初始化
pLdrRegisterDllNotification(0, MyLdrDllNotification, NULL, &pvCookie);
// 测试DLL 装载
HMODULE hLoad = ::LoadLibraryW(L"mshtml.dll");
Sleep(1000);
// 测试 DLL 卸载
::FreeLibrary(hLoad);
// 清除
if (pvCookie)
{
pLdrUnregisterDllNotification(pvCookie);
pvCookie = NULL;
}
return 0;
}
#include <Ntsecapi.h> // DDK
typedef const UNICODE_STRING* PCUNICODE_STRING;
typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA {
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;
typedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA {
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;
ULONG Flags; //Reserved.
PCUNICODE_STRING FullDllName; //The full path name of the DLL module.
PCUNICODE_STRING BaseDllName; //The base file name of the DLL module.
PVOID DllBase; //A pointer to the base address for the DLL in memory.
ULONG SizeOfImage; //The size of the DLL image, in bytes.
} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;
typedef union _LDR_DLL_NOTIFICATION_DATA {
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;
LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;
typedef const PLDR_DLL_NOTIFICATION_DATA PCLDR_DLL_NOTIFICATION_DATA;
typedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)(ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context);
typedef NTSTATUS (NTAPI *pfnLdrRegisterDllNotification)(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, void* Context, void **Cookie);
typedef NTSTATUS (NTAPI *pfnLdrUnregisterDllNotification)(void *Cookie);
typedef NTSTATUS (NTAPI *pfnLdrRegisterDllNotification)(ULONG Flags, PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, void* Context, void **Cookie);
typedef NTSTATUS (NTAPI *pfnLdrUnregisterDllNotification)(void *Cookie);
#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2
VOID NTAPI MyLdrDllNotification(
ULONG NotificationReason,
PCLDR_DLL_NOTIFICATION_DATA NotificationData,
PVOID Context
)
{
switch (NotificationReason)
{
case LDR_DLL_NOTIFICATION_REASON_LOADED:
printf ("Dll Loaded: %S\n", NotificationData->Loaded.FullDllName->Buffer);
break;
case LDR_DLL_NOTIFICATION_REASON_UNLOADED:
printf ("Dll Unloaded: %S\n", NotificationData->Unloaded.FullDllName->Buffer);
break;
}
}
ULONG NotificationReason,
PCLDR_DLL_NOTIFICATION_DATA NotificationData,
PVOID Context
)
{
switch (NotificationReason)
{
case LDR_DLL_NOTIFICATION_REASON_LOADED:
printf ("Dll Loaded: %S\n", NotificationData->Loaded.FullDllName->Buffer);
break;
case LDR_DLL_NOTIFICATION_REASON_UNLOADED:
printf ("Dll Unloaded: %S\n", NotificationData->Unloaded.FullDllName->Buffer);
break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
{
HMODULE hModule = GetModuleHandleW(L"NTDLL.DLL");
// 取得函数指针
pfnLdrRegisterDllNotification pLdrRegisterDllNotification = (pfnLdrRegisterDllNotification)GetProcAddress(hModule, "LdrRegisterDllNotification");
pfnLdrUnregisterDllNotification pLdrUnregisterDllNotification = (pfnLdrUnregisterDllNotification)GetProcAddress(hModule, "LdrUnregisterDllNotification");
void *pvCookie = NULL;
// 取得函数指针
pfnLdrRegisterDllNotification pLdrRegisterDllNotification = (pfnLdrRegisterDllNotification)GetProcAddress(hModule, "LdrRegisterDllNotification");
pfnLdrUnregisterDllNotification pLdrUnregisterDllNotification = (pfnLdrUnregisterDllNotification)GetProcAddress(hModule, "LdrUnregisterDllNotification");
void *pvCookie = NULL;
// 初始化
pLdrRegisterDllNotification(0, MyLdrDllNotification, NULL, &pvCookie);
// 测试DLL 装载
HMODULE hLoad = ::LoadLibraryW(L"mshtml.dll");
Sleep(1000);
// 测试 DLL 卸载
::FreeLibrary(hLoad);
pLdrRegisterDllNotification(0, MyLdrDllNotification, NULL, &pvCookie);
// 测试DLL 装载
HMODULE hLoad = ::LoadLibraryW(L"mshtml.dll");
Sleep(1000);
// 测试 DLL 卸载
::FreeLibrary(hLoad);
// 清除
if (pvCookie)
{
pLdrUnregisterDllNotification(pvCookie);
pvCookie = NULL;
}
if (pvCookie)
{
pLdrUnregisterDllNotification(pvCookie);
pvCookie = NULL;
}
return 0;
}
}
运行程序, 输出如下。可以证实以上代码监听了 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
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
本文转自 陈本峰 51CTO博客,原文链接:http://blog.51cto.com/wingeek/274017,如需转载请自行联系原作者