[Windows编程] 监视DLL装载/卸载

简介:
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;
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;
}
 
运行程序, 输出如下。可以证实以上代码监听了 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


 本文转自 陈本峰 51CTO博客,原文链接:http://blog.51cto.com/wingeek/274017,如需转载请自行联系原作者



相关文章
|
1月前
|
存储 Java C语言
Windows 下 JNI 调用动态链接库 dll
Windows 下 JNI 调用动态链接库 dll
33 0
|
3月前
|
消息中间件 C++ Windows
02 MFC - Windows 编程模型
02 MFC - Windows 编程模型
19 0
|
1月前
|
存储 Java C++
Windows 下 JNA 调用动态链接库 dll
Windows 下 JNA 调用动态链接库 dll
23 0
|
1月前
|
网络协议 Linux C语言
005.在Windows下编程让效率起飞
windows开发Linux方式: 先用编辑器编写源代码 然后进入Linux 系统,使用gcc编译器(后面会讲),对源代码进行编译运行。 熟练后推荐使用VS2019 开发Linux C++ 程序 将自己的Ip地址设为静态IP
27 1
|
2月前
|
数据安全/隐私保护 Windows
Windows卸载与清除工具 “ Geek 与 CCleaner ”
一、Geek的简介 1、大概介绍 geek是一款专业的Windows软件卸载软件,它可以卸载程序并查找以前卸载的应用程序在注册表中留下的点点滴滴,彻底地卸载干净,还用户一个干净整洁的电脑。 2、详细介绍 Geek Uninstaller - the best FREE uninstaller
53 1
|
2月前
|
Oracle 关系型数据库 数据库
windows Oracle Database 19c 卸载教程
打开任务管理器 ctrl+Shift+Esc可以快速打开任务管理器,找到oracle所有服务然后停止。 停止数据库服务 在开始卸载之前,确保数据库服务已经停止。你可以使用以下命令停止数据库服务: net stop OracleServiceORCL Universal Installer 卸载Oracle数据库程序 一般情况运行Oracle自带的卸载程序,如使用Universal Installer 工具卸载。 点击开始菜单找到Oracle,然后点击Oracle安装产品,再点击Universal Installer。 点击之后稍等一会然后会进入进入下图界面,点击卸载产品。 选中要删除的Orac
41 1
|
2月前
|
人工智能 机器人 C#
Windows编程课设(C#)——基于WPF和.net的即时通讯系统(仿微信)
一款参考QQ、微信的即时通讯软件。采用CS结构,客户端基于.Net与WPF开发,服务端使用Java开发。
|
2月前
|
网络协议 安全 API
9.9 Windows驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章`《内核RIP劫持实现DLL注入》`介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过`NtCreateThreadEx`这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,`NtCreateThreadEx`函数最终会调用`ZwCreateThread`,本章在寻找函数的方式上有所不同,前一章通过内存定位的方法得到所需地址,本章则是通过解析导出表实现。
9.9 Windows驱动开发:内核远程线程实现DLL注入
|
3月前
|
开发者 Windows
什么是 Windows 操作系统 DLL 文件的 Side-by-Side Assemblies 技术
什么是 Windows 操作系统 DLL 文件的 Side-by-Side Assemblies 技术
32 0
|
3月前
|
API UED Windows
什么是 Windows 操作系统的 DLL 文件
什么是 Windows 操作系统的 DLL 文件
57 0

相关产品

  • 云迁移中心