VS之DLL延迟载入

dll延迟加载


延迟加载机制是为了提高进程加载效率的技术。

延迟加载机制没有对dll任何特殊要求,也就是说任意的一个DLL都可以被延迟加载(除了kernel32.dll)。

vs配置

#include <windows.h>
#include <delayimp.h>
#pragma comment(lib, "Delayimp.lib")

也可以项目属性添加依赖库。

链接器 - 输入 - 延迟加载的DLL,填入需要延迟加载的DLL名称。

如果需要用到卸载功能,链接器 - 高级 - 卸载延迟加载的DLL

可以直接使用延迟加载的函数,当调用这个函数才会加载这个dll

DLL延迟加载机制的核心就是delayLoadHelper()函数,对延迟加载函数的调用实际上是调用它,该函数引用特殊的DelayImport节,并且会在其内部自动调用LoadLibrary()之后再调用GetProcAddress()以获取函数地址。

手动卸载dll时,必须通过__FUnloadDelayLoadedDLL2(“xxx.dll”)卸载,不能使用FreeLibray()

卸载时传递的DLL名字不应该包含路径。

代码示例

vs模块窗口可以调试时观察。



#include<windows.h>
#include<delayimp.h>
#pragma comment(lib, "Delayimp.lib")

#include<stdio.h>
#include "dll.h"

#pragma comment(lib,"../Debug/Dll.lib")


int main()
{

	GetModuleHandle(L"Dll.dll") ? printf("Dll is loaded\n") : printf("Dll is not loaded\n");

	func1();
	GetModuleHandle(L"Dll.dll") ? printf("Dll is loaded\n") : printf("Dll is not loaded\n");

	__FUnloadDelayLoadedDLL2("Dll.dll");
	GetModuleHandle(L"Dll.dll") ? printf("Dll is loaded\n") : printf("Dll is not loaded\n");

	func2();

	return 0;
}

/*
Dll is not loaded
func1
Dll is loaded
Dll is not loaded
func2
*/

注意:

  • 一个导出的字段的DLL是无法延迟载入的;
  • Kernel32.dll模块是无法延迟载入的,因为必须载入该模块才能调用LoadLibrary和GetProcAddress。
  • 不应在DllMain入口函数中调用一个延迟载入的函数,这可能导致程序崩溃

在PE中的结构体

#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13

typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR {
    union {
        DWORD AllAttributes;		// 没用;
        struct {
            DWORD RvaBased : 1;             // Delay load version 2
            DWORD ReservedAttributes : 31;
        };
    } Attributes;

    DWORD DllNameRVA;                       // RVA to the name of the target library (NULL-terminate ASCII string)
    DWORD ModuleHandleRVA;                  // RVA to the HMODULE caching location (PHMODULE)
    DWORD ImportAddressTableRVA;            // RVA to the start of the IAT (PIMAGE_THUNK_DATA)
    DWORD ImportNameTableRVA;               // RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData)
    DWORD BoundImportAddressTableRVA;       // RVA to an optional bound IAT
    DWORD UnloadInformationTableRVA;        // RVA to an optional unload info table
    DWORD TimeDateStamp;                    // 0 if not bound,
                                            // Otherwise, date/time of the target DLL

} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR;

下面几个成员比较重要:

  • ImportAddressTableRVA; 延迟载入IAT的RVA (函数地址(VA))
  • ImportNameTableRVA; 延迟载入INT的RVA(PIMAGE_THUNK_DAT * BoundImportAddressTableRVA; 绑定IAT的RVA
  • UnloadInformationTableRVA; 卸载函数
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值