DLL延迟加载与资源释放

selph
selph
发布于 2020-09-25 / 603 阅读
0
0

DLL延迟加载与资源释放

本文来自本人对《Windows黑客编程技术详解》书籍第二章节的学习笔记

DLL延迟加载

DLL延迟加载通过设置VS2019的项目属性即可实现,DLL延迟加载可以实现程序先运行再加载dll文件的功能,这里以下面的源代码为例来看看DLL延迟加载前后的区别:

源代码

#include<stdio.h>
#include<windows.h>
#pragma comment(lib,"MessageBoxDll")
extern "C" VOID CallMsgBox();
int main() {
	CallMsgBox();
	return 0;
}

DLL延迟加载与普通加载的区别

DLL延迟加载除了加载的时间不同,还会让PE结构中的导入表产生变化,

可通过项目右键,属性,链接器,输入,延迟加载的DLL来设置延迟加载

未进行延迟加载设置可执行文件导入表:

image-20200922165244477

导入表会有导入的dll和函数名

设置延迟加载的可执行文件导入表:

image-20200922165409656

这里就没有延迟导入的DLL信息

延迟到入的DLL信息都存在了延迟导入表里:

image-20200922165457371

资源释放

通过资源释放相关API,可以把一些必要的dll、图片、音乐等文件以资源的形式存放到exe中,当exe运行的时候进行释放,在文件传输方面会比较方便,因为可以一个exe装一堆东西

先介绍要用到的API

API:FindResource

获取指定模块的资源,返回资源句柄

HRSRC
WINAPI
FindResourceW(
    _In_opt_ HMODULE hModule,//资源所在模块句柄,如果是当前模块,则NULL就行
    _In_ LPCWSTR lpName,//资源名称:MAKEINTRESOURCE(ID)
    _In_ LPCWSTR lpType//资源类型
    );

API:SizeofResource

获取资源的大小

DWORD
WINAPI
SizeofResource(
    _In_opt_ HMODULE hModule,//模块句柄,当前模块就NULL
    _In_ HRSRC hResInfo//资源句柄
    );

API:LoadResource

加载资源到全局存储器,返回指向资源文件首地址的指针(资源数据句柄)

HGLOBAL
WINAPI
LoadResource(
    _In_opt_ HMODULE hModule,	//模块句柄
    _In_ HRSRC hResInfo		//资源句柄
    );

API:LockResource

锁定内存中的资源,返回指向资源文件首地址的指针

LPVOID
WINAPI
LockResource(
    _In_ HGLOBAL hResData	//资源数据句柄
    );


这里以释放DLL文件并调用DLL内的函数为例,演示资源释放的过程

源代码

记得先右键项目,添加,资源,导入,这里导入dll文件就行了

#include<stdio.h>
#include<windows.h>
#include"resource1.h"
typedef VOID(*DllFun)();

BOOL FreeMyResoure(UINT uiResourceName, wchar_t* lpszResourceType, char* lpszSaveFileName) {
	//获取指定模块里的资源
	HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResourceName), lpszResourceType);
	//获取资源大学
	DWORD dwSize = ::SizeofResource(NULL, hRsrc);
	//加载资源到内存
	HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
	//锁定资源
	LPVOID lpVoid = ::LockResource(hGlobal);
	//保存资源为文件
	FILE* fp = NULL;
	fopen_s(&fp,lpszSaveFileName,"wb+");
	fwrite(lpVoid, sizeof(char), dwSize, fp);
	fclose(fp);
	return TRUE;
}

int main() {
	FreeMyResoure(106,(wchar_t*)L"dlls",(char*)"MessageBoxDll.dll");
	Sleep(1000);
	HINSTANCE hModule = LoadLibrary(L"MessageBoxDll.dll");
	DllFun CallMsgBox = (DllFun)GetProcAddress(hModule, "CallMsgBox");
	CallMsgBox();
	return 0;
}

效果演示

image-20200922163419418

一个exe文件,运行之后释放dll文件,然后动态加载dll文件中的函数,输出消息框。

总结

DLL延迟加载是针对DLL静态加载的,DLL延迟加载可与资源释放搭配使用,也许能产生更好的使用体验


评论