动态链接库(二)

C#动态加载第三方非托管DLL,LoadLibraryEx,LoadLibrary 另外,有个问题需要注意。之所以会有此报错,是因为对于被调用DLL自身调用的“其它DLL”,会按照和DllImport同样的顺序(即exe所在目录、System32目录、环境变量目录)去寻找它们,而这些“其它DLL”你可能放在了和被调用DLL同样的目录中,而没有放在exe所在目录、System32目录、环境变量目录中,所以显然是找不到的。此时我们可以使用LoadLibraryEx()函数,通过该函数导入的DLL,如果它本身也调用了其它DLL的话,会强制先在被调用DLL所在的目录中查找它调用的“其它DLL”。 阅读详情

DLL高级技术

    1.1 显示载入DLL模块:

LoadLibrary,LoadLibraryEx.两个函数的返回值HMODULE表示文件映像被映射到的虚拟内存地址,等价于HINSTANCE(DllMain入口点函数所接收的参数),LoadLibraryEx函数有两个额外的参数:hFile(保留应为NULL),dwFlags:

    DONT_RESOLVE_DLL_REFERENCES 只映射文件映像,不调用DllMain,同时不会自动载入这个Dll中用到的其它DLL(使用这个标志调用导出函数时将面临很大的风险)。更多细节参见:LoadLibraryEx(DONT_RESOLVE_DLL_REFERENCES) is fundamentally flawed:地址:http://blogs.msdn.com/oldnewthing/archive/2005/02/14/372266.aspx

    LOAD_LIBRARY_AS_DATAFILE 可以将DLL或EXE以资源的形式映射到进程地址空间。

    LOAD_WITH_ALTERED_SEARCH_PATH 改变DLL加载时的搜索算法(GetDllDirectory,SetDllDirectory).

其它参见MSDN:http://msdn.microsoft.com/en-us/library/ms684179(VS.85).aspx 。

 

   1.2 显示地卸载DLL模块:

    BOOL FreeLibrary(HMODULE hModule);

   VOID FreeLibraryAndExitThread(HMODULE hModule,  DWORD dwExitCode );

该函数在Kernel32.dll中实现如下:

    VOID FreeLibraryAndExitThread(HMODULE hModule,  DWORD dwExitCode );

  {

      FreeLibrary(hModule);

      ExitThread(dwExitCode);

  }

该函数主要用于当我们在DLL中创建一个线程,在完成工作后,想先后调用FreeLibrary,ExitThread,这样就会出现问题,当FreeLibrary返回时调用ExitThread的代码已经不复存在了,将会挂掉整个进程。调用FreeLibraryAndExitThread时即使FreeLibrary已经撤销DLL的映射,线程仍可以继续执行并调用ExitThread(这条指令在Kernel32.dll中)。

   注意:系统会在每个进程中为每个DLL维护一个使用计数,LoadLibrary,LoadLibraryEx函数多次调用会递增这个计数(只会在同一个进程中映射一次),FreeLibrary,FreeLibraryAndExitThread会递减这个计数当为0是撤销DLL的映射。

  HMODULE hInstDll = GetModuleHandle(_TEXT("MyLib"));

  if (hInstDll == NULL )

{

   hInstDll = LoadLibrary(_TEXT("MyLib"));

}
  GetModuleHandle传入NULL会返回应用程序的可执行句柄。

  如果只有一个DLL(或EXE)的HMODULE/HINSTANCE,可以通过GetMoudleFileName获取全路径。

  GetModuleHandleEx。

  不要混用LoadLibrary,LoadLibraryEx.以LOAD_LIBRARY_AS_DATAFILE 标志载入的DLL返回句柄调用GetMoudleFileName将会返回0(并不认为是一个完全载入的DLL);

 1.3 DLL入口函数:

      DLL入口函数在执行的时候存在一些限制,这些限制与获取进程范围内的加载程序锁(loader lock)有关。具体参见Best Practices for Creating DLLs:http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx 。

     DLL_PROCESS_ATTACH:在DLL第一次被映射到进程空间时被通知;在创建新进程时,系统会分配进程地址空间并将EXE的文件映像以及所需DLL的文件映像映射到进程的地址空间中,然后系统将创建进程的主线程并用这个主线程来调用每个DLL的DllMain函数同时传入DLL_PROCESS_ATTACH,当所有已映射的DLL完成该通知的处理后,主线程才开始执行可执行模块的C/C++运行时的启动代码(startup code),然后执行可执行模块的入口点函数(_tmain或_tWinMain)。对于LoadLibrary或LoadLibraryEx载入的DLL由调用此函数的线程调用DllMain函数。

    DLL_PROCESS_DETACH:系统将DLL从进程撤销时会以此通知调用DllMain函数,当撤销的原因是进程要终止,那么调用ExitProcess函数的线程将负责调用DllMain函数,调用FreeLibrary,FreeLibraryAndExitThread撤销时由调用此函数的线程负责调用DllMain函数。在DllMain函数没有处理完DLL_PROCESS_DETACH通知之前,线程是不会从此函数中退出的,只有当所有的DLL通知处理完成后,操作系统才会真正地终止进程。用TerminateProcess函数终止进程,系统不会以此通知调用DllMain函数。

     DLL_THREAD_ATTACH:当新创建一个线程时,系统会检查所有已经映射到进程地址空间的DLL,并以此通知由新创建的线程调用DllMain函数,只有在完成所有的通知处理后,系统才会让新线程执行它的线程函数。当新DLL被映射时系统不会让已经创建的线程以此通知调用DllMain函数,主线程不会处理此通知,在进程创建的时候被映射到进程地址空间的任何DLL会收到DLL_PROCESS_ATTACH通知,但不会收到DLL_THREAD_ATTACH通知。

    DLL_THREAD_DETACH:让线程的终止的首先方式是让它的线程函数返回,这样系统会调用ExitThread来终止线程,但系不会立即终止线程,会让这个线程以此通知调用所有已映射DLL的DllMain函数完成之后,才会终止线程,TerminateThread函数跟TerminateProcess函数一样不会让线程调用DllMain函数,DLL撤销映射时系统不会让任何还在运行的线程以此通知调用DllMain函数。

   注意:以LoadLibrary,LoadLibraryEx载入的DLL系统以DLL_PROCESS_ATTACH来调用DllMain函数(不会DLL_THREAD_ATTACH),在撤销映射时以DLL_THREAD_DETACH通知来调用DllMain函数。

 

   1.4 DllMain的序列化调用:
    一个DLL的DllMain函数在同一时刻只能有一个线程调用处理。

   BOOL DisableThreadLibraryCalls(HMODULE  hModule);让系统不用DLL_THREAD_ATTACH,DLL_THREAD_DETACH通知去调用指定的DLL的DllMain函数。

 

 

 

 

   1.5 DllMain和C/C++运行库:

 

    在链接DLL的时候,链接器会将DLL的 入口点函数的地址嵌入到生成的DLL文件映像中,在默认的情况下,如果用Microsoft链接器并指定/DLL开关,那么入口点函数名是_DllMainCRTStartup,这个函数在c/c++运行库中,在链接DLL时被静态地链接到DLL的文件映像(即使用的是运行库的DLL版本)。

 

   如果我们的DLL代码中没有提供DllMain函数,我们可以使用c/c+运行库提供的DllMain函数,它的实现大致如下(如果静态链接到c/c++运行库):

 

   1.6 延迟载入DLL

     局限性:

     a.一个导出了字段(数据或全局变量)的DLL是无法延迟载入的。

     b.Kernel32.dll模块是无法延迟载入的这是因为必须在入此模块才能调用LoadLibrary和GetProcAddress。

     c.不应该在DllMain入口点函数中调用延迟载入的函数,因为这样可能会导致程序崩溃。

    进一步了解其局限性参阅:Constraints of Delay Loading DLLs:http://msdn.microsoft.com/en-us/library/yx1x886y(VS.80).aspx.

 

    1.7 函数转发器:

    //Function forwarders to function in DllWork

    #pragram comment(linker, "/export:SomeFunc=DllWork:SomeOtherFunc").

    我们必须为每个需要转发的函数单独创建一行pragram.

 

    1.8 已知的DLL

    HKLM/SYSTEM/CurrentControlSet/Control/Session Manager/KownDlls.

    当我们调用LoadLibrary,LoadLibraryEx时系统会检查我们传入的DLL的名字是否包含了.dll扩展名,如果没有,那么函数会用正常的搜索规则进行。如果指定了扩展名,那么会先将扩展名去掉,在KownsDlls注册表项中搜索,如果没有值名与之对应,那么函数将按正常的规则,否则将载入这个对应的DLL.

 

   1.9 DLL重定向:

    强制操作系统的加载程序首先从应用程序的目录中载入模块。SuperAppl.exe的重定向文件名称必须是SuperAppl.exe.local.我们可以创建一个名为.local的文件夹把自己的DLL放在这个文件夹中,让windows能够轻易的找到它们。对应注册的COM对象来说极其有用,它允许应用程序将它的COM对象DLL放在自己的目录中,这样注册的同一个COM对象的其它应用程序就不会妨碍我们的应用程序。Vista这项特性默认关闭。HKLM/Microsoft/WindowsNT/CurrentVersion/Image File Execution Options注册项中增加一个条目DWORD DevOverrideEnable值为1。

 

Isolated Applications and Side-by-side Assemblies:http://msdn.microsoft.com/en-us/library/aa375193.aspx

 

 1.10 模块的基地址重定位

     没个可执行文件的和DLL模块都有一个首先地址(preferred base address),默认DLL(0x10000000),0x00400000.可以用Dumpbin工具(加/headers开关)来查看文件映像的首先基地址。

    当一个模块无法被载入到它的首先基地址时存在以下两个缺点:

    a.加载程序必须遍历重定位段并修改模块中的大量代码。

    b.当加载程序写入到模块的代码页面中时,系统的写时复制机制会强制这些页面以系统的页交换文件作为后备存储器。

    我们可以用/FIXED开关创建一个不包含任何重定位信息的映像。我们应该使用/SUBSYSTEM:WINDOWS,5.0开关,如果连接器检测到模块没有东西需要进行重定位修正,那么它会关闭一个特殊的IMAGE_FILE_RELOCS_STRIPPED标志将模块中的重定位段省略掉。(这时WINDOWS 2000加载程序的一项新特性,5.0也不足为奇了。)。

   Rebase工具。ImageHlp API提供的RaBaseImage函数。

  1.11 模块的绑定

   采用模块绑定技术可以使应用程序更快的初始化并使用更少的存储器。

   Bind工具。ImageHlp API 提供的BindImageEx函数。

   如果加载程序发现模块已经绑定过了,所需的DLL也确实被载入到了它们的首先基地址,而且时间戳也吻合,那它实际上不需要做任何事,不必对任何模块重定位,也不必查看任何导入函数的序列地址,应用程序可以直接开始执行。

 

无人机通信安全渗透测试:从信号拦截到GPS欺骗的完整攻防框架 在物联网和智能设备普及的背景下,无线通信安全成为关键基础设施防护的核心环节。其原理在于,通过软件定义无线电等设备对空中的射频信号进行捕获、分析与模拟,从而评估通信协议在加密、认证和防重放等方面的脆弱性。这项技术的价值在于,它能主动发现并修复系统设计缺陷,避免因信号被拦截或欺骗导致设备被劫持、数据泄露等重大安全事件。其应用场景广泛,涵盖消费电子、工业控制及关键基础设施等领域。本文聚焦于无人机这一典型移动物联网终端,深入探讨如何构建一套针对其通信链路的渗透测试方法论,其中涉及信号拦截、协议逆向等关键技术,旨在为 阅读详情

相关推荐

Claude Code教程(二) | Claude Code 核心信息与使用指南

Claude Code 核心信息与使用指南

qq_20236937的博客 2181

LoadLibraryEx使用

【代码】LoadLibraryEx使用。

但行技术的博客 1104

手把手教你用Python实现双三次插值(附OpenCV对比测试)

本文深入解析了双三次插值算法的数学原理,并提供了从零开始的Python实现教程。通过与OpenCV官方实现的对比测试,详细评估了不同插值算法(包括最邻近差值、双线性插值)在图像质量与计算性能上的差异,帮助开发者掌握高质量图像缩放的核心技术。

weixin_29310605的博客 293

C++-dll动态加载与卸载(LoadLibraryEx与FreeLibrary)

dll动态加载与卸载 这里的动态加载指的是:程序编译时不需要任何dll相应的lib进行链接,程序本身通过相关函数加载和卸载dll,并使用其中的函数。 代码如下: class PluginManager { public: static bool loadPlugin(const QString& pluginPath, PluginInstanceInfo& pluginInfo); static bool freePlugin(PluginInstanceInfo&

mrbone11的博客 8641

ZEMAX优化方法---【Zemax学习】

在光学系统自动设计中,优化设计是光学设计中的重要阶段,也是ZEMAX软件的核心功能,涉及评价函数、权因子、阻尼因子等重要概念。在常用的阻尼最小二乘法优化设计的基础上,ZEMAX给我们提供了三种优化选择:Optimization(局部优化)、Global Search(全局优化)和 Hammer Optimization(锤形优化)。

yh的博客 4447

告别GIS软件!用R语言ggplot2+ggmapcn绘制出版级世界地图(附5种投影对比图)

本文提供了一份完整的实践指南,教你如何利用R语言及其强大的ggplot2生态系统,结合ggmapcn包,绘制出出版级的世界地图。文章详细对比了五种经典地图投影(如摩尔维德、罗宾森投影)的代码实现与视觉差异,并讲解了如何添加比例尺、指北针等专业元素,最终导出高清PDF,实现从数据分析到专业可视化的全流程代码化操作,彻底告别传统GIS软件。

p5l2m9n4o6q的博客 406

从CPRI到eCPRI:手把手教你用Wireshark分析基站前传协议帧结构

本文手把手教你使用Wireshark工具,深入解析从CPRI到eCPRI的基站前传协议帧结构。通过搭建分析环境、编写解析脚本,并对比两者在时延管理、帧格式及数据封装上的差异,为无线通信领域的研发与测试人员提供了一套实用的逆向分析与故障排查方法。

x8y9z0的博客 604

动态链接库(二)--动态链接库的创建

创建一个简单的动态链接库, 扩展介绍了不同编译器及调用约定导致的名字改编规则

SNAKEpc12138的博客 2436

3.2 直流无刷电机(BLDC):状态空间模型与传递函数

状态空间模型和传递函数是分析BLDC电机动态特性的重要工具。状态空间模型通过微分方程描述系统内部状态与输入输出关系,适用于多变量系统分析;传递函数则在频域表征系统特性,便于控制器设计。本文详细推导了三相坐标系和dq坐标系下的BLDC电机状态空间模型,讨论了线性化方法,并介绍了从状态空间模型到传递函数的转换过程。这些模型为BLDC电机的控制系统设计提供了理论基础。

技术工作者 243

百度AI架构师亲授:Agentic智能体在教育领域的落地(附个性化学习案例)

当我们谈论“教育智能化”时,我们真正需要的不是“更聪明的工具”,而是“能懂人的伙伴”——一个能像优秀教师那样主动观察、精准判断、动态调整的“数字助手”。Agentic智能体(智能体)正是这样的存在:它具备“自主性”(主动决策)、“反应性”(感知环境)、“目标导向”(聚焦学习目标)和“社会性”(与人/其他智能体协作),完美匹配教育场景中“个性化、动态化、协同化”的核心需求。本文将从底层逻辑到工程实现为什么Agentic是教育AI的“下一站”?(痛点与价值)Agentic智能体的核心架构是什么?

AI天才研究院 356

Win32_动态链接库(二)

1.“文件”—>"新建"—>“空项目”   #include "windows.h"   #include "stdio.h"  #pragma comment(lib,"..//Debug//XXP_DLL_Test.lib")      extern "C" __declspec(dllimport) int AddFun(int a,int b); //导入动态链接库的A

xiexiaopingroma的专栏 549

RK3588 Buildroot 新建板级DTS

在rk3588 linux开发过程中,新创建板型主要基于硬件差异化、软件适配与优化、项目定制化等多方面需求。

501846585_QQAndroid_java 1298

【LearnUnity·二】Unity C#结合C++动态链接库编程

Unity C#结合C++动态链接库编程 在使用Unity做应用开发过程中,可能会需要使用一些仅支持C++的库,或者因为底层使用C++具有更高的效率优化,而选择使用C#结合C++的方式开发。Untiy为此也提供了链接C++动态链接库的接口,方便开发者使用。 本人开发环境为:Window10,Visual Studio,Unity。 一、最简单的动态链接库使用 使用Visual Studio生成动态...

xinwuya_的博客 773

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

JNI学习—创建动态链接库(Windows&Linux)②

看着孩子一天天长大,知识一天天丰富,仿佛农名看见自己的庄家日渐成熟,父亲的心里是充满幸福、喜悦的。 一:新建项目 选择模板,点击下一步 填写项目名称和解决方案名称,vs2010使用解决方案管理项目,一个解决方案可以包含多个项目。 二:项目中导入头文件 按顺序导入 添加完头文件后,还需要添加包含头文件目录,否则会找不到头文件,include xxx.h 时 有下画红线。 选择项目,点击右键选择属性—》找到c/c++ 常规设置—》添加附加包含目录 三:新建源文件 选择源

青春斗 333

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

动态链接库基础学习二

动态加载动态链接库使程序在需要时加载动态链接库时加载。尤其是很多动态链接库需要调用时,大大的加快了程序启动的时间。比隐式连接动态链接库更节省内存资源。首先我们接着重写上次add按钮的代码: void CDllTestDlg::OnBtnAdd() {       // TODO: Add your control notification handler code here

renwotao2009的专栏 1371

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

linux动态链接库的编译及使用<二>

Linux下的.so是基于Linux下的动态链接,其功能和作用类似与windows下.dll文件。 下面是关于.so的介绍: 一、引言 通常情况下,对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要

yhcs1213的专栏 477

VC++动态链接库编程(二)之非MFC DLL

VC++动态链接库编程之非MFC DLL 2005-10-08 09:49 作者: 宋宝华 出处: 作者授权转载 责任编辑:方舟 document.write(""); 天极软件专题专区精选     到天极软件“读编

todototry的专栏 1637

静态链接库与动态链接库 (二)动态链接库的编译与使用

上一篇文章里大概描述linux下静态链接库的编译与使用,下面讲动态链接库的编译与使用方法。 1. 什么是动态链接库 所谓动态链接库,是指编译的时候不会把程序引用到的库插入到执行程序里,而是在执行时候才会去加载相关的库,所有用到此库的程序可以共享一份代码。 这样带来的好处是可执行程序所占的空间变小了,同时,如果库需要升级,你并不需要重新编译你的程序,只要把相关的库升级...

weixin_30245867的博客 186

Linux动态链接库同名符号装载问题(二)

上一篇《Linux动态链接库同名符号装载问题(一)》中提到了动态链接的一些问题,本文主要讨论动态加载时符号冲突的问题。PART1:RTLD_DEEPBIND打开动态链接导致段错误的现象可执行程序A通过dlopen动态加载library.so,有可能出现library.so中和这样的情况: 程序A中存在函数search_hash() library.so中同样存在函数search_hash() dl...

镇关西拳打鲁智深 5655

Java使用JNA调用C++动态链接库——JNA-JNI(二)

Java使用JNA调用C++动态链接库

qq_23858785的博客 3904

DLL动态链接库生成及其動態调用(二)

DLL动态链接库生成及其動態调用(二) 一、說明 對上一篇DLL的補充,上一篇是靜態鏈接,補充動態鏈接方式。相比靜態鏈接,會節省內存,但是可能使用過程有點複雜。 有朋友交了一種定義函數指針的方法,奈何還沒有消化!—q _ p— 二、注意點 #include<windows.h>,因為要用帶加載庫的一些函數; 將之前生成的.h/.dll/.lib文件需要複製到當前項目文件夾下; 需要包含.h文件(兩種路徑方式均可); 一般順序 LoadLibrary—GetProcAddress—FreeLi

weixin_45107812的博客 280

动态链接库(二)-访问MFC动态链接库c++类和资源

MFC动态链接库代码

Greless的后花园 691

VC++动态链接库(DLL)编程(二)

VC++动态链接库(DLL)编程(二) ――非MFC DLL 作者:宋宝华 e-mail:21cnbao@21cn.com4.非MFC DLL4.1一个简单的DLL  第2节给出了以静态链接库方式提供add函数接口的方法,接下来我们来看看怎样用动态链接库实现一个同样功能的add函数。  如图6,在VC++中new一个Win32 Dynamic-Link Library工程dll

wiSCADA 1819

动态链接库理解(二)

1、在(一)我们提到C++编译器在导出函数的时候,会对函数做名字改编,这样的话,我们用C++编写的dll,拿给C语言,或C#语言的客户端程序调用就会出问题。因为名字发生了改变,会找不到。 所以我们希望在输出函数名的时候,名字最好不要发生改变。但是怎么办呢? (1)只需要将(一)中的Dll1.h中的 #define DLL1_API _declspec(dllimport) 变为 #def

宁静致远的博客 696

VC++动态链接库(DLL)编程深入浅出(二)

VC++动态链接库(DLL)编程深入浅出(二) 2009-11-05 12:22 4.2 声明导出函数  DLL中导出函数的声明有两种方式:一种为4.1节例子中给出的在函数声明中加上__declspec(dllexport),这里不再举例说明;另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的...

weixin_34018202的博客 86
上一篇: VC中缺省库冲突的解决
下一篇: The Complete Guide to C++ Strings
SWenJing
博客等级 码龄18年 8粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值