2019-5-27 09:45
自己顶一下,以下是引用高手的一段分析,虽然看不太懂但感觉说得有理
MistHill 6 2013-7-26 10:47
要成功调用第三方DLL里的导出函数,需要自己构建一个头文件(.h)和一个导入库文件(.lib)。
(A) 头文件
这个貌视没什么捷径,需要自己手工写。
分析dll各导出函数的输入参数和返回数据类型。视dll是由何种编程语言生成的,选择相应的分析工具效果较好,比如Delphi的用IDR。
通常利用IDA+Hex-Rays可生成C源码,再对比反汇编代码进行确认,那些不能确定的最好实际跟一下。
基本上IDA会猜错数据类型,特别是其为结构或类指针时。
(B) 导入库文件
有两个关键问题:导出符号(symbols,包括函数和数据)和调用约定(calling convention)。分两种情况来处理。
(a) 调用程序和dll使用相同的调用约定。
通常是两者都用同一编程语言和缺省调用约定时。
比如调用程序使用"__declspec(dllimport)"原形(prototype)和声明(declaration),dll使用"__declspec(dllexport)时,很简单。
在VC环境下,需要用到DUMPBIN.EXE和LIB.EXE。
写一个命令行批处理脚本,由DLL自动生成.def文件和.lib文件。forgot有个帖子dll2lib,我没法直接用,修改了一下(Dll2Lib.cmd)。.def文件很重要,情况(b)还会用到。
批处理脚本里生成.lib文件是这样的:
LIB /DEF:DllFile.def /MACHINE:IX86 /NOLOGO
(b) 调用程序和dll使用不同的调用约定。
比如用C来写调用程序,而dll是用Delphi写的,我们知道Windef.h是将PASCAL定义为__stdcall的。直接用(a)的.lib就有问题,首先要解决符号问题,其次压栈参数不能得到清理(stack clean up),调用者必然崩溃。
解决办法说穿了很简单:根据(A)的头文件写一个同名Dummy DLL(DllFile.c)。
其函数声明部分用"__declspec(dllexport) return_type __stdcall funcname(...);"的形式;
为每一个导出函数写一个对应的Dummy Function,这些函数什么都不用做,只要保证传入参数的个数和类型、返回参数类型与.h头文件一致即可。
用以下命令:
CL /O2 /MD /LD /FeDllFile /FoDllFile DllFile.c /link /DEF:DLLFile.def
即可创建DllFile.dll和DllFile.lib。使用命令之前,请注意备份或重命名你的原dll,如果同名存在会被覆盖!
新生成的Dummy DLL(DllFile.dll)是没用的,删掉。DllFile.lib才是我们需要的,它保证了导出符号和调用约定的正确。这里.def文件保证了.lib文件的ordinal与原dll一致,非常重要。