栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【无标题】

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【无标题】

windows黑客编程之单一实例/DLL延时加载/资源释放 1 运行单一实例 原因:

为什么要让进程再操作系统上只保存一份实例?
因为某些情况,只需要运行一份实例。比如病毒木马,又或者开启多进程会导致程序出问题等。

实现原理:

如何确保一个进程只运行一个实例?

方法很多,可以通过扫描进程列表来实现,可以枚举程序窗口来实现,也可以通过共享全局变量来实现,也可以通过创建系统命名互斥对象的方式来实现。

编码实现:
BOOL IsAlreadyRun()
{
	HANDLE hMutex = NULL;
	hMutex = ::CreateMutex(NULL, FALSE, "TEST");
	if (hMutex)
	{
		if (ERROR_ALREADY_EXISTS == ::GetLastError())
		{
			return TRUE;
		}
	}
	return FALSE;
}
小结:

关键是熟悉CreateMutex的使用,在调用CreateMutex函数创建互斥的命名对象时,注意不要与已有的事件、信号量或者文件映射等对象相同。且特别注意不要调用CloseHandle来关闭互斥对象的句柄,不然就会释放资源,无法起到单一实例的效果了。

2 DLL延时加载 原因:

为什么要使用DLL延时加载?

因为再开发程序的时候通常会使用第三方库,有些第三方库不提供静态库LIB,只提供动态库DLL,这样的话,程序需要依赖相应的DLL才能加载。通过DLL延时加载技术可以实现,所依赖的DLL再正式调用时再加载进来。这样做的好处是把DLL以资源的形式插入到exe中,这样就不用附加DLL文件了,一个exe搞定。

实现原理:

本程序以加载第三方库——skin++ SkinPPWTL.dll为例,首先编译不延时加载的exe,发现运行这个exe报错。

观察该exe的导入表可以发现包含SkinPPWTL.dll,所以程序加载运行的时候,SkinPPWTL.dll必须存在。

![在这里插入图片描述](https://img-blog.csdnimg.cn/d76c57a3ad80435cb25ae97663b824d5.png且观察exe的导入表可发现是依赖SkinPPWTL.dll的
如果采用DLL延时加载呢?
在项目属性中配置

然后编译,运行exe可发现,可以直接运行,不需要依赖SkinPPWTL.dll,且会把SkinPPWTL.dll释放到同级目录。
观察导入表可发现没有这个SkinPPWTL.dll了。

小结:

DLL延迟加载技术不需要编码实现,只需要对VS开发环境设置链接器即可完成。

3 资源释放 原因:

为什么要使用资源释放?
资源释放主要是可以让程序变得更简洁,如果程序需要额外加载一些诸如DLL,文本,图片等文件,可以把他们作为资源插件到程序里面,等到程序运行后,再把他们释放到本地。好处就是只编译出来一个exe,而不需要附带其他文件。

实现原理:

右键项目->添加->资源,自定义一个“MYRES”,然后导入相关资源文件,如此便完成了插入资源的操作。
插入了资源之后怎么获取呢?Windows提供了API。
首先,通过FindResoure定位程序里的资源,主要是根据”资源类型“和“资源名称”进行定位,获取资源信息块句柄。
其次,根据获取的句柄,利用SizeofResoure获取资源的大小,再通过LoadResoure把资源加载到程序内存。
接着通过LockResoure锁定加载到内存中的资源,防止程序中的其他操作影响这块内存,返回值就是资源在内存进程中的起始地址。
最后,根据资源大小已经进程内存的起始地址,可以将资源文件读出来保存到本地。
原理就是通过PE文件结构,确定资源在PE文件中的偏移和大小。

编码实现:
BOOL FreeMyResource(UINT uiResouceName, char *lpszResourceType, char *lpszSaveFileName)
{
	// 获取指定模块里的指定资源
	
	HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResouceName), lpszResourceType);
	if (NULL == hRsrc)
	{
		FreeRes_ShowError("FindResource");
		return FALSE;
	}
	
	// 获取资源的大小  NULL表示当前进程
	DWORD dwSize = ::SizeofResource(NULL, hRsrc);
	if (0 >= dwSize)
	{
		FreeRes_ShowError("SizeofResource");
		return FALSE;
	}
	// 将资源加载到内存里 NULL表示当前进程
	HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
	if (NULL == hGlobal)
	{
		FreeRes_ShowError("LoadResource");
		return FALSE;
	}
	// 锁定资源
	LPVOID lpVoid = ::LockResource(hGlobal);
	if (NULL == lpVoid)
	{
		FreeRes_ShowError("LockResource");
		return FALSE;
	}

	// 保存资源为文件
	FILE *fp = NULL;
	fopen_s(&fp, lpszSaveFileName, "wb+");
	if (NULL == fp)
	{
		FreeRes_ShowError("LockResource");
		return FALSE;
	}
	fwrite(lpVoid, sizeof(char), dwSize, fp);
	fclose(fp);

	return TRUE;
}
小结:

资源释放技术主要是理解相关的API的调用关系,注意一点的就是,明确资源所在模块,如果资源包含在DLL文件中,则需要获取DLL模块的句柄去读取文件。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/954634.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号