C/C++导出DLL函数的一般方法
通常项目中导出DLL接口有两种方式:
1.__declspec(dllexport)导出;
2.*.def文件导出。
__declspec(dllexport)导出
在DLL导出的函数名称前使用_declspec(dllexport)关键字导出函数接口。
test_dll.h
test_dll.cpp
def文件导出
由于__declspec(dllexport)导出接口需要定义一长串的内容,所以MS引入def文件来导出函数接口。使用def文件相对简单,只需要在项目中增加一个后缀名为.def的文件,按照格式将DLL需要导出的接口定义在def文件即可。
1.定义.def文件
test_dll.def
DllName表示Dll的文件名
1[可选]指定导出的函数序号。导出多个函数时,需要开发者自定义序号,不能重复。2.添加def文件至工程3.设置工程属性
在“属性”-“链接器”-“输入”配置模块定义文件输入def文件名称。
4.编译生成DLL使用工具查看导出函数名接口,导出接口的顺序与def文件定义的序号相同。
存在问题
通过工具可以查看导出函数名,暴露接口函数功能。导出的函数名可以任意被访问和使用,即使业务功能被封装在内部代码经过加密处理,但外部接口是公开的,可以被正常调用。造成在不知情,被未经授权的开发者滥用,间接造成损失。解决方案:导出匿名接口导出匿名序号接口
匿名导出接口只需要在def文件的导出接口名称增加NONAME关键字即可,如下:
test_dll.def
NONAME表示不导出函数名称(匿名)。使用CFFExplorer工具查看导出函数接口名称,函数名称已经被隐藏掉。
访问匿名序号接口静态链接
和通常工程引用DLL的方法相同,引用.h,链接.lib,运行前将.dll文件拷贝至应用运行目录即可。
动态加载
通过动态加载的方式调用DLL接口。当导出序号时,定义函数指针变得复杂,只能通过静态反编译的方式确定参数数量和类型,定义函数指针。
注意:定义函数指针的类型声明必须与函数定义一致,否则无法正常使用。
小结
静态链接的方式不变,不影响团队内部使用。匿名接口,不知情的开发者无法调用DLL接口功能,防止DLL功能被滥用。提高DLL破解难度,调用者无法通过函数名推测函数功能,增加分析接口功能、接口间业务逻辑关系的复杂程度。
匿名导出DLL接口能够一定程度提升安全性,但使用IDA等静态反编译工具逆向代码逻辑,能够找到函数的接口参数类型,并且大致了解接口内部实现逻辑(没有函数名,逆向分析的难度已经加大),如果要进一步提升DLL的安全性,需要使用加壳工具进行保护或采用其他的安全防护手段。