[DLL劫持] 2 DLL劫持之DLL基础(2)

本文介绍了动态链接库(DLL)的基本概念及其核心函数DllMain的工作原理。详细解释了DllMain如何在DLL加载和卸载时被调用,以及不同调用场景下的行为。此外,还提供了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

该系列文章是依据本人平时对动态链接库的学习,归纳总结,所做的学习笔记。如有错误或待改善之处,请留下您宝贵的意见或建议。

 

以下讲的是DLLDllMain

 

Windows在加载DLL的时候,需要一个入口函数,就如同控制台或DOS程序需要main函数、WIN32程序需要WinMain函数一样。在前面的例子中,DLL并没有提供DllMain函数,应用工程也能成功引用DLL,这是因为Windows在找不到DllMain的时候,系统会从其它运行库中引入一个不做任何操作的缺省DllMain函数版本,并不意味着DLL可以放弃DllMain函数。

根据编写规范,Windows必须查找并执行DLL里的DllMain函数作为加载DLL的依据,它使得DLL得以保留在内存里。这个函数并不属于导出函数,而是DLL的内部函数。这意味着不能直接在应用工程中引用DllMain函数,DllMain是自动被调用的。

进程中的每个DLL模块被全局唯一的32字节的HINSTANCE句柄标识进程自己还有一个HINSTANCE句柄。所有这些模块句柄都只有在特定的进程内部有效,它们代表了DLLEXE模块在进程虚拟空间中的起始地址。在Win32中,HINSTANCEHMODULE的值是相同的,这两种类型可以替换使用。进程模块句柄几乎总是等于0x400000,而DLL模块的加载地址的缺省句柄是0x10000000。如果程序同时使用了几个DLL模块,每一个都会有不同的HINSTANCE值。这是因为在创建DLL文件时指定了不同的基地址,或者是因为加载程序对DLL代码进行了重定位。

以下是一个DllMain的例子:

#include "lib.h"
#include "windows.h"
#include "stdio.h"
BOOL APIENTRY DllMain( HANDLE hModule,    
					DWORD  ul_reason_for_call, 
					LPVOID lpReserved
					)
{
    switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		printf("\nprocess attach of dll");
		break;
	case DLL_THREAD_ATTACH:
		printf("\nthread attach of dll");
		break;
	case DLL_THREAD_DETACH:
		printf("\nthread detach of dll");
		break;
	case DLL_PROCESS_DETACH:
		printf("\nprocess detach of dll");
		break;
    }
    return TRUE;
}

int add(int x,int y)
{
	return x + y;
}

DllMain函数在DLL被加载和卸载时被调用,在单个线程启动和终止时,DLLMain函数也被调用,ul_reason_for_call指明了被调用的原因。原因共有4种,即PROCESS_ATTACHPROCESS_DETACHTHREAD_ATTACHTHREAD_DETACH,以switch语句列出。

来仔细解读一下DllMain的函数头BOOL APIENTRYDllMain( HANDLE hModule, WORD ul_reason_for_call, LPVOID lpReserved )

APIENTRY被定义为__stdcall,它意味着这个函数以标准Pascal的方式进行调用,也就是WINAPI方式。

执行的代码如下:

#include "stdafx.h"
#include "windows.h"
typedef int (* lpAddFun)(int,int);
 
int main(int argc, char* argv[])
{
  HINSTANCE hDll; 
	lpAddFun addFun;
	hDll = LoadLibrary("..\\Debug\\dllTest.dll");
	if (hDll != NULL)
	{
		//addFun = (lpAddFun)GetProcAddress(hDll,"add");	
		addFun = (lpAddFun)GetProcAddress(hDll,MAKEINTRESOURCE(1));
		//MAKEINTRESOURCE直接使用导出文件中的序号
		if(addFun!=NULL)
		{
		    int result =  addFun(2,3);    
			printf("\ncall add in dll:%d",result);
		}	
		FreeLibrary(hDll);
	}	
	getchar();
  	return 0;
}

与上一节一样,也是在同一个工作区中建立两个工程。

代码中的GetProcAddress (hDll, MAKEINTRESOURCE ( 1 ) )值得留意,它直接通过.def文件中为add函数指定的顺序号访问add函数,具体体现在MAKEINTRESOURCE ( 1 ),MAKEINTRESOURCE是一个通过序号获取函数名的宏,定义在winuser.h中。


以上是参考网上一篇文档,对DLL做一个大概的介绍,如果想要深入了解,请查阅相关资料。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值