`

DllMain详解

    博客分类:
  • csp
阅读更多
DllMain详解
源码下载:
       DLL – 动态链接库
       DllMainTest – 测试DLL的DllMain
1  DLL的进入/退出函数
1.1  DllMain简介
跟exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain。以“DllMain”为关键字,来看看MSDN帮助文档怎么介绍这个函数的。
The DllMain function is an optional method of entry into a dynamic-link library (DLL)。(简要翻译:对于一个Dll模块,DllMain函数是可选的。)这句话很重要,很多初学者可能都认为一个动态链接库肯定要有DllMain函数。其实不然,像很多仅仅包含资源信息的DLL是没有DllMain函数的。
1.2 何时调用DllMain
       系统是在什么时候调用DllMain函数的呢?静态链接时,或动态链接时调用 LoadLibrary和FreeLibrary都会调用DllMain函数。DllMain的第三个参数fdwReason指明了系统调用Dll的原因,它可能是DLL_PROCESS_ATTACH、DLL_PROCESS_DETACH、DLL_THREAD_ATTACH和 DLL_THREAD_DETACH。以下从这四种情况来分析系统何时调用了DllMain。           
1.2.1 DLL_PROCESS_ATTACH
       大家都知道,一个程序要调用Dll里的函数,首先要先把DLL文件映射到进程的地址空间。要把一个DLL文件映射到进程的地址空间,有两种方法:静态链接和动态链接的LoadLibrary或者LoadLibraryEx。
       当一个DLL文件被映射到进程的地址空间时,系统调用该DLL的DllMain函数,传递的fdwReason参数为DLL_PROCESS_ATTACH。这种调用只会发生在第一次映射时。如果同一个进程后来为已经映射进来的DLL 再次调用LoadLibrary或者LoadLibraryEx,操作系统只会增加DLL的使用次数,它不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。不同进程用LoadLibrary同一个DLL时,每个进程的第一次映射都会用DLL_PROCESS_ATTACH调用 DLL的DllMain函数。
       可参考DllMainTest的DLL_PROCESS_ATTACH_Test函数。
1.2.2 DLL_PROCESS_DETACH
       当DLL被从进程的地址空间解除映射时,系统调用了它的DllMain,传递的fdwReason值是DLL_PROCESS_DETACH。当DLL处理该值时,它应该执行进程相关的清理工作。
       那么什么时候DLL被从进程的地址空间解除映射呢?两种情况:
       ◆FreeLibrary解除DLL映射(有几个LoadLibrary,就要有几个FreeLibrary)
       ◆进程结束而解除DLL映射,在进程结束前还没有解除DLL的映射,进程结束后会解除DLL映射。(如果进程的终结是因为调用了TerminateProcess,系统就不会用DLL_PROCESS_DETACH来调用DLL的DllMain函数。这就意味着DLL 在进程结束前没有机会执行任何清理工作。)
       注意:当用DLL_PROCESS_ATTACH调用DLL的DllMain函数时,如果返回FALSE,说明没有初始化成功,系统仍会用DLL_PROCESS_DETACH调用DLL的DllMain函数。因此,必须确保没有清理那些没有成功初始化的东西。
       可参考DllMainTest的DLL_PROCESS_DETACH_Test函数。
1.2.3 DLL_THREAD_ATTACH
       当进程创建一线程时,系统查看当前映射到进程地址空间中的所有DLL文件映像,并用值DLL_THREAD_ATTACH调用DLL的DllMain函数。
新创建的线程负责执行这次的DLL的DllMain函数,只有当所有的DLL都处理完这一通知后,系统才允许进程开始执行它的线程函数。
注意跟DLL_PROCESS_ATTACH的区别,我们在前面说过,第 n(n>=2)次以后地把DLL映像文件映射到进程的地址空间时,是不再用DLL_PROCESS_ATTACH调用DllMain的。而 DLL_THREAD_ATTACH不同,进程中的每次建立线程,都会用值DLL_THREAD_ATTACH调用DllMain函数,哪怕是线程中建立线程也一样。
1.2.4 DLL_THREAD_DETACH
       如果线程调用了ExitThread来结束线程(线程函数返回时,系统也会自动调用ExitThread),系统查看当前映射到进程空间中的所有DLL文件映像,并用DLL_THREAD_DETACH来调用DllMain函数,通知所有的DLL去执行线程级的清理工作。
       注意:如果线程的结束是因为系统中的一个线程调用了TerminateThread,系统就不会用值DLL_THREAD_DETACH来调用所有DLL的DllMain函数。
1.3  为DllMain换名
在早期的SDK版本中,DllMain是叫做DllEntryPoint。其实有一件鲜为人知的事:一个Dll的入口函数名是可以自己定义的。下面我将以VC++6.0为例来演示如何更改。首先要说明一点,虽然DllMain可以换成其他函数名,但函数的参数和返回值必须和DllMain一样。而且这个函数要为__stdcall类型(DllMain本身也是__stdcall类型)。
打开VC++菜单Project\Settings\Link tab\ Output in the Category box,如下图,在Entry-point symbol中输入要替换DllMain的函数名(当然这个函数名是你程序中已经实现的函数)。Entry-point symbol是干么的呢?可以以关键字“Entry-point symbol”搜索MSDN帮助文档查看,搜索时,打钩“仅搜索标题”会更快定位。
         按OK后,如果马上编译的话会出现如下错误:
LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/Dll.dll : fatal error LNK1120: 1 unresolved externals
打开VC++菜单Project\Settings\C/C++选项卡,如下图,在Project Options:末尾的地方添加”/D”(图中蓝色高亮的地方),要注意位置,我试了,要把/D放到/GZ后面也会链接错误,我也不懂为什么,^_^。按OK,再次编译,成功。大家可以自己测试下到底有没有更改成功,什么,如果测试?打出调式信息啊。
1.4 DisableThreadLibraryCalls
看帮助就知道它是干么用的:
The DisableThreadLibraryCalls function disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the dynamic-link library (DLL) specified by hLibModule. This can reduce the size of the working code set for some applications.
分享到:
评论

相关推荐

    DllMain详解的相关资源

    Dll动态链接库有个入口函数DllMain,这是我对DllMain的详解。 DllMain的详解:见我的博客http://blog.csdn.net/benkaoya/archive/2008/06/02/2504781.aspx

    VC++动态链接库创建和调用全过程详解.doc

    《VC++动态链接库创建和调用全过程详解》这篇文档主要涵盖了动态链接库(DLL)在VC++环境下的创建和使用。DLL是一种重要的软件开发工具,它可以被多个应用程序共享,从而减少内存占用和提高程序效率。以下是文档的...

    动态链接库详解-vc中创建和使用动态库

    【动态链接库详解-VC中创建和使用动态库】 动态链接库(DLL)在Windows操作系统中是一种可重用代码的机制,允许多个程序共享同一份代码库,从而节省内存并提高程序间的协同工作能力。VC++(Visual C++)提供了创建...

    WinDBG用法详解及其插件编写方法

    此外,`.dllmain`函数是插件的入口点,它会处理WinDBG的初始化和卸载事件。 最后,将插件编译成DLL后,可以使用`.load`命令在WinDBG中加载它,然后像调用其他内置命令一样调用你的插件函数。 总的来说,掌握WinDBG...

    BHO小小整理,

    5. **DLLMain函数**:BHO的入口点通常是DLLMain函数,负责初始化和清理工作。当IE加载BHO时,会调用这个函数。 6. **OnDocumentComplete**事件:这是BHO中一个重要的方法,当IE加载完一个页面后,会触发此事件,...

    pe2-DLL.rar_This Is It

    《PE结构与DLL加载详解》 在Windows操作系统中,Portable Executable(PE)文件格式是用于存放可执行程序、动态链接库(DLL)以及其他类型模块的主要格式。本资料集主要探讨了PE结构以及DLL的加载过程,对于深入...

    详解C#byte数组怎么传入C

    2、打开dllmain.cpp,增加一个byte数组元素求和的函数: Cal(unsigned char* data,int length);编译,在工程名上右键选择“生成”;即生成Dll1.dll文件。 3、创建C#工程对,选择窗体类型工程。在界面上增加一个...

    Windows的钩子机制详解

    `DllMain`函数在DLL加载和卸载时进行初始化和清理工作。 在实际使用时,开发者需要在主应用程序中加载`Spy` DLL,并调用`StartHook`启动钩子,然后系统就会开始监控鼠标事件。每次鼠标左键被点击,`MouseProc`会被...

    基于C++中常见编译错误的总结详解

    6. **Error LNK2005**:这是一个链接错误,表明_DllMain@12已经在不同的地方定义。这可能是由于重复定义导致的。删除工程设置中的_USRDLL标志可以解决问题。 7. **R6010错误**:这个错误通常涉及运行时问题,比如...

    问题解答20210921

    【知识点详解】 1. 进程间通信:在Windows系统中,可以利用共享内存实现进程间的通信。在DLL中创建一个共享缓冲区,允许不同进程访问同一块内存,从而达到数据共享的目的。为了保证数据安全,需要进行互斥操作,...

    NSIS C++插件

    **NSIS C++ 插件开发详解** NSIS(Nullsoft Scriptable Install System)是一款流行的开源安装制作系统,它允许开发者使用简单的脚本语言创建Windows安装程序。在NSIS中,插件是一种扩展功能的方式,可以增加安装...

    IE注入例子

    **IE注入技术详解** IE注入,全称Internet Explorer注入,是一种技术手段,通过将自定义的动态链接库(DLL)加载到Internet Explorer浏览器进程中,来实现对浏览器行为的控制、扩展或调试。这种技术在软件开发、...

    InjectDll(VC源码).rar

    《DLL注入技术详解——基于VC++的实现》 DLL(Dynamic Link Library)是Windows操作系统中的一个重要组成部分,它允许程序员将代码和数据封装在一个可重用的模块中,多个程序可以同时调用这些共享资源。DLL注入是一...

    WeInject.rar

    《MFC版通用DLL注入详解》 在计算机编程领域,DLL(Dynamic Link Library)注入是一种技术,它允许一个进程将代码动态地加载到另一个正在运行的进程中。这种技术常用于调试、性能分析以及恶意软件中。本文将深入...

    DLL Memory Loader

    《DLL内存加载技术详解——以DLL Memory Loader为例》 DLL(动态链接库)是Windows操作系统中的一个重要组件,它允许程序共享代码和数据,减少系统资源的占用。在传统的DLL加载方式中,通常通过LoadLibrary和...

    PE加载器

    **PE加载器详解** PE(Portable Executable)加载器是Windows操作系统中用于处理可执行文件(如EXE、DLL)的核心组件。它负责解析PE文件结构,为程序创建内存映像,并执行初始化过程,使程序能够正确运行。本文将...

    qidong.rar_启动dll线程_线程HOOK

    《启动DLL线程与线程HOOK技术详解》 在计算机编程领域,动态链接库(DLL)和线程管理是两个非常关键的概念。DLL允许代码共享,而线程HOOK则为监控和修改其他线程行为提供了可能。"qidong.rar"这个压缩包文件,其...

    dllzhuru.rar_dll 注入_dll远程注入_vc 远程注入_远程注入

    《DLL注入技术详解——基于VC的远程注入实践》 DLL(Dynamic Link Library)注入是一种常见的系统编程技术,常用于扩展程序功能、调试、监控或恶意攻击。本篇文章将深入探讨DLL注入的基本原理,并通过VC++实例,...

    多功能DLL注入器源码 附带注释

    《多功能DLL注入器源码详解》 DLL注入技术在IT领域中是一种常见的系统级调试和功能增强手段,它允许一个进程将动态链接库(DLL)加载到另一个进程中,以实现跨进程通信、功能扩展或者监控目标进程的行为。本文将...

Global site tag (gtag.js) - Google Analytics