9.DLL的入口函数DllMain函数

article/2025/7/18 18:59:05

1.dll的入口函数

类似程序的入口函数main或者WinMain一样,DLL也有一个入口函数,就是DllMain

 

2.DllMain函数原型

BOOL APIENTRY DllMain( HMODULE hModule,             //指向自身的句柄DWORD  ul_reason_for_call,   //调用原因LPVOID lpReserved            //静态加载为非NULL,动态加载为NULL)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:  //进程创建的时候调用case DLL_THREAD_ATTACH:   //线程创建的时候调用case DLL_THREAD_DETACH:   //线程结束的时候调用case DLL_PROCESS_DETACH:  //进程结束的时候调用break;}return TRUE;
}

 

3.何时调用DllMain

静态链接时(通过包含头文件和lib文件的方式调用DLL)或动态链接(通过LoadLibrary和FreeLibrary的方式调用DLL)都会调用DllMain函数。DllMain的第二个参数ul_reason_for_call指明了系统调用DLL的原因,它可能是:

DLL_PROCESS_ATTACH:  // 1 //进程创建的时候调用
DLL_THREAD_ATTACH:     // 2 //线程创建的时候调用
DLL_THREAD_DETACH:    // 3 //线程结束的时候调用
DLL_PROCESS_DETACH:  // 0 //进程结束的时候调用

3.1DLL_PROCESS_ATTACH

一个程序要调用DLL里的函数,先要把DLL文件映射到进程的地址空间。要把一个DLL文件映射到进程的地址空间,有两种方法:静态链接和动态链接。每个进程第一次将一个DLL文件映射到进程的地址空间时,系统调用该DLL的DllMain函数,传递的ul_reason_for_call参数为DLL_PROCESS_ATTACH。此时动态加载lpReserved为NULL,静态为非NULL。

注意:如果同一个进程后来为已经映射进来的DLL再次调用LoadLibrary或者LoadLibraryEx,操作系统只会增加DLL的使用次数,它不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。

3.2DLL_PROCESS_DETACH

与DLL_PROCESS_ATTACH相对应,当DLL从进程的地址空间解除映射时,系统调用DllMain,传递ul_reason_for_call参数为DLL_PROCESS_DETACH。当DLL处理该值时,应该执行进程相关的清理工作。

1)FreeLibrary解除DLL映射(有几个LoadLibrary,就要有几个FreeLibrary)此刻lpReserved为NULL。

2)进程结束后会解除DLL映射。如果进程的终结调用TerminateProcess,系统不会调用DLL_PROCESS_DETACH来调用DLL的DllMain函数,这意味着DLL在进程结束前没有机会执行任何清理工作。此刻lpReserved为为NULL

3.3DLL_THREAD_ATTACH

当进程创建一线程时,系统查看当前映射到进程地址空间的所有DLL文件映像,并用值DLL_THREAD_ATTACH调用DLL的DllMain函数。新创建的线程负责执行这次的DLL的DllMain函数,只有当所有的DLL都处理完这一通知后,系统才允许进程开始执行它的线程函数。

注意:进程中的每次建立线程,都会用值DLL_THREAD_ATTACH调用DllMain函数,哪怕是线程中建立线程也一样。

3.4DLL_THREAD_DETACH

如果线程调用了ExitThread来结束线程(线程函数返回时,系统也会自动调用ExitThread),系统查看当前映射到进程空间中的所有DLL文件映像,并DLL_THREAD_DETACH来调用DllMain函数,通知所有的DLL去执行线程级的清理工作。

注意:如果线程的结束是因为系统中的一个线程调用了TerminateThread,系统就不会用值DLL_THREAD_DETACH来调用所有DLL的DllMain函数。

 

4.实例

导出DLL:

1)dllmain.cpp:

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <iostream>
using namespace std;BOOL APIENTRY DllMain( HMODULE hModule,             //指向自身的句柄DWORD  ul_reason_for_call,   //调用原因LPVOID lpReserved            //静态加载为非NULL,动态加载为NULL)
{cout << "实例句柄:" << hModule << "    调用原因:" << ul_reason_for_call << "    链接方式:" << lpReserved << endl;switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:  //进程创建的时候调用cout << "DLL_PROCESS_ATTACH" << endl;break;case DLL_THREAD_ATTACH:   //线程创建的时候调用cout << "DLL_THREAD_ATTACH" << endl;break;case DLL_THREAD_DETACH:   //线程结束的时候调用cout << "DLL_THREAD_DETACH" << endl;break;case DLL_PROCESS_DETACH:  //进程结束的时候调用cout << "DLL_PROCESS_DETACH" << endl;break;}return TRUE;
}

2).cpp文件:

// DynamicLib.cpp: 定义 DLL 应用程序的导出函数。
//#include "stdafx.h"#define _DLL_EXPORTS
#include "func.h"#include <iostream>
using namespace std;void print()
{cout << "Hello World" << endl;
}

 3)func.h文件:

#pragma once#ifdef _DLL_EXPORTS
#define DLL_API _declspec(dllexport)
#else
#define DLL_API _declspec(dllimport)
#endifextern "C" DLL_API void print();

4.1静态调用(包含头文件和lib文件的方式)

main.cpp文件:

#include <iostream>
using namespace std;
#include "func.h"#pragma comment(lib,"DynamicLib.lib")int main()
{cout << "-----------------main-----------------" << endl;print();cout << "---------------end main---------------" << endl;//system("pause");return 0;
}

为了看到完成的输出,我们利用命令提示符运行生成的.exe文件:

4.2动态调用(通过LoadLibrary的方式)

main.cpp文件:

#include <iostream>
using namespace std;
//#include "func.h"
#include <windows.h>
//#pragma comment(lib,"DynamicLib.lib")int main()
{cout << "-----------------main-----------------" << endl;typedef void(*PFUN)();HMODULE h = LoadLibrary("DynamicLib.dll");PFUN fun = (PFUN)GetProcAddress(h, "print");fun();FreeLibrary(h);cout << "---------------end main---------------" << endl;//system("pause");return 0;
}

结果:

4.3在静态调用中创建一个线程

main.cpp:

#include <iostream>
using namespace std;
#include "func.h"
#include <windows.h>
#pragma comment(lib,"DynamicLib.lib")CRITICAL_SECTION g_cs;DWORD WINAPI ThreadFun(LPVOID lpThreadParameter
)
{cout << "-----------------thread---------------" << endl;cout << "Hello World" << endl;cout << "-------------- end thread-------------" << endl;return 0;
}int main()
{InitializeCriticalSection(&g_cs);cout << "-----------------main-----------------" << endl;print();cout << "---------------end main---------------" << endl;HANDLE hthread = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);WaitForSingleObject(hthread, INFINITE);CloseHandle(hthread);DeleteCriticalSection(&g_cs);//system("pause");return 0;
}

结果:

 

5.总结

1)创建进程调用DLL_PROCESS_ATTACH;进程结束调用DLL_PROCESS_DETACH

2)创建线程调用DLL_THREAD_ATTACH;线程结束调用DLL_THREAD_DETACH

3)静态调用链接方式(参数lpReserved)为非空;动态调用链接方式(参数lpReserved)为空


http://chatgpt.dhexx.cn/article/Q0Rm3nIY.shtml

相关文章

导致DllMain中死锁的关键隐藏因子

原文地址&#xff1a;https://blog.csdn.net/hczhiyue/article/details/18505087 有了前面两节的基础&#xff0c;我们现在切入正题&#xff1a;研究下DllMain为什么会因为不当操作导致死锁的问题。首先我们看一段比较经典的“DllMain中死锁”代码。 //主线程中 HMODULE h …

DllMain详解

DllMain详解 源码下载&#xff1a; DLL – 动态链接库 DllMainTest – 测试DLL的DllMain 1 DLL的进入/退出函数 1.1 DllMain简介 跟exe有个main或者WinMain入口函数一样&#xff0c;DLL也有一个入口函数&#xff0c;就是DllMain。以“DllMain”为关键字&#xff0c;来看看MSD…

Flash 加密和破解

关于Flash&#xff08;swf&#xff09;&#xff0c;我们需要明确一点&#xff1a; ***Flash字节码的意义都是公开的 所以如果cracker真的有足够的耐心他最终还是可以破解掉你的Flash。我们能做的只是尽量提高Flash被破解的门槛让cracker破解它需要消耗的时间大于自己更新版本的…

flashfxp是ftp软件吗,你知道flashfxp是ftp软件吗

flashfxp是ftp软件吗&#xff1f;当然。ftp是一种文件传输协议&#xff0c;用于互联网双向传输&#xff0c;控制文件下载空间在服务器复制文件从本地计算机或本地上传文件复制到服务器上。而FlashFXP是一款功能强大的FXP/FTP软件&#xff0c;集成了其它优秀的FTP软件的优点&…

pfx证书解析公钥私钥

从pfx中获取CA证书 openssl pkcs12 -in test.pfx -nodes -out server.pem 输入证书密码 提取公钥 X.509格式 openssl x509 -in server.pem -out public.cer RSA格式 openssl rsa -in server.pem -outform PEM -pubout -out public.pem 提取私钥 openssl rsa -in server…

提权学习:第三方软件提权(FlashFXP 替换文件漏洞提权)

当你的才华 还撑不起你的野心时 那你就应该静下心来学习 目录 FlashFXP 替换文件漏洞提权 0x01 前言 介绍 用途 特点 0x02 环境配置 0x03 FlashFXP 提权思维导图 0x04 操作演示 FlashFXP 替换文件漏洞提权 0x01 前言 介绍 FlashFXP是一个功能强大的 FXP/FTP 软件&…

用FlashFXP上传文件到SSH服务器,附FlashFXP显示中文乱码的解决方法

用SSH Secure Shell能上传文件&#xff0c;又能输入命令&#xff0c;而且上传文件的时候不容易无故断开连接。但是它缺少续传的功能&#xff0c;不太适合上传比较大的文件&#xff1b;而且它在与linux系统SSH登陆时不方便支持中文&#xff0c;所以这里我向大家推荐FlashFXP来实…

flashfxp链接Linux

使用FLASHFXP链接我们的Linux操作系统&#xff0c;可以方便实现文件的上传下载到Linux中。在我们的Linux能成功链接网络后&#xff0c;利用ifconfig命令设置ip、掩码、网关。 设置ip与掩码&#xff1a;ifconfig eth0 192.168.1.114 netmask 255.255.255.0&#xff0c;设置网关…

FlashFXP使用阿里云ECS私钥登录

前言 最近购买了一个阿里云服务器主机&#xff0c;需要使用到FTP上传文件到服务器&#xff0c;因为我一直习惯使用FlashFXP上传文件&#xff0c;使用的是SFTP,所以没有在额外的安装FTP的服务&#xff0c;但是发现阿里云的ECS在SFTP模式下直接使用密码和用户名登录会报错。下面是…

NET主流ORM框架分析

接上文我们测试了各个ORM框架的性能&#xff0c;大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异。这里和大家分享下我对ORM框架的理解及一些使用经验。 ORM框架工作原理 所有的ORM框架的工作原理都离不开下面这张图&#xff0c;只是每个框架的实现程度不…

Linux USB总线驱动框架分析

1、USB驱动引入 USB&#xff08;全称 Universal Serial Bus&#xff0c;通用串行总线&#xff09;&#xff0c;已经成为PC及嵌入式设备中最常用、最便捷的通信接口。Linux USB子系统较为庞大&#xff0c;本文主要对Linux系统下的USB总线驱动框架进行概述&#xff0c;重点的细节…

Django框架详解

一、MVC框架 1、MVC框架核心思想&#xff1a; 分工和解耦 2、web MVC举例&#xff1a; 以通过浏览器注册用户信息为例&#xff1a; M:Model,模型&#xff0c; 和数据库进行交互。V:View,视图&#xff0c; 产生html页面。C:Controller,控制器, 接收请求&#xff0c;进行处…

几种数据可视化框架分析

根据下面各个框架本身的特性&#xff0c;以及各自的优缺点&#xff0c;推荐使用D3或者ECharts作为数据可视化的首选框架&#xff0c;某些小特性可以辅用其他小框架实现。具体每个框架的说明和分析如下&#xff1a; D3.js D3是指数据驱动文档(Data-Driven Documents)。D3.js是一…

常见威胁建模框架分析与比较

1 概述 威胁建模的方法最初是为了帮助开发更多的安全的操作系统&#xff0c;但已经开发的大量威胁建模方法&#xff0c;有些只关注软件发展&#xff0c;有些仅涵盖业务或组织的风险和威胁&#xff0c;另有一些可能是技术性的&#xff0c;不同的威胁模型都在基于不同的目的而开…

某商城框架分析

开篇 最近做了一个商城系统,从系统的需求,到系统的选型以及框架和各种技术的研究和使用,我都参与其中,所以,分享一下这个系统. 框架 框架如下: 说明: 表现层 用户分为两种&#xff0c;PC端用户和移动端用户; 其中PC端包括 商城首页,商品类目,购物车,订单,商品展示,会员中心等…

Cgroup框架分析

cgroups概念扫盲 关于cgroups本文主要分析的是cgroups整体框架&#xff0c;不涉及对各个子系统的介绍和cgroupsfs的介绍&#xff0c;在分析cgroup整体框架的时候&#xff0c;首先我们需要对cgroups中的一些概念有所深刻认识&#xff0c;只有在这个基础上&#xff0c;才能明白为…

音视频常见播放器框架分析

音视频面试必问&#xff1a;如何设计一个播放器 1.常见播放器框架分析 2.如何解决播放端延迟的问题 3.音视频如何做同步 4.快进、快退、逐帧播放如何实现 音视频开发技术精讲《常见播放器框架分析》 播放器框架 SDL2播放音频 使用SDL播放解码后的音频数据&#xff0c;SDL播放…

商业分析经典框架

商业分析经典框架 文章目录 商业分析经典框架1.行业怎么盈利现状分析PEST分析产业链分析 2.行业里谁在挣钱竞争分析标杆公司分析竞争格局分析细分机会分析 3.企业还能盈利么发展分析商业化模式演变新技术/产品新用户新市场 总结 1.行业怎么盈利 现状分析 PEST分析 这个行业在…

Linux内核4.14版本——alsa框架分析(1)—alsa简介

目录 一&#xff0c;ALSA声音编程介绍 二&#xff0c;ALSA历史 三&#xff0c;数字音频基础 四&#xff0c;ALSA基础 五&#xff0c;ALSA体系结构 六&#xff0c;设备命名 七&#xff0c;声音缓存和数据传输 八&#xff0c;Over and Under Run 九&#xff0c;一个典型…

sFuzz源代码框架分析

sFuzz是发表在软件工程顶会ICSE2020年论文&#xff08;sFuzz&#xff1a;An Efficient Adaptive Fuzzer for Solidity Smart Contracts&#xff09;中实现的工具。sFuzz通过基于距离的启发式策略的模糊测试技术实现对合约漏洞检测。 sFuzz基于C实现&#xff0c;集成了以太坊和模…