使用.def文件导出DLL的好处是可以隐藏函数名,提高安全性。
首先新建DLL工程,编写函数,因为使用def导出,所以编写函数声明和定义和普通exe的编写方式一样。
MyDll.h
// MyDll.h: interface for the MyDll class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MYDLL_H__A5062BAC_C3AD_45FE_8909_494D8EBE125E__INCLUDED_)
#define AFX_MYDLL_H__A5062BAC_C3AD_45FE_8909_494D8EBE125E__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
int Max(int x, int y);
int Min(int x, int y);
int Add(int x, int y);
int Sub(int x, int y);
#endif // !defined(AFX_MYDLL_H__A5062BAC_C3AD_45FE_8909_494D8EBE125E__INCLUDED_)
MyDll.cpp
#include "stdafx.h"
#include "MyDll.h"
int Max(int x, int y)
{
return x > y ? x : y;
}
int Min(int x, int y)
{
return x < y ? x : y;
}
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
然后添加一个 test.def 文件到项目中(如果VC6打开文件或添加文件崩溃,请安装FileTool.dll 补丁)
编写如下内容
EXPORTS
Max @12
Min @15 NONAME
Add @13
Sub @16
说明:@后面的数字是函数导出序号,在DLL的导出表里有一个 AddressOfNameOrdinals 地址表,里面存的值加上导出表里的Base就是这里的导出序号了。
编译生成的DLL拿到 dependency walker 里,可以看到如下结果:
注明了 NONAME 的 Min 函数,其函数名已经隐藏起来了。
另一个关键点是,我们在 def 中指定的导出序号是不连续的,windows 计算导出函数总数是用最大序号 - 最小序号 +1,因此得到了 16 - 12 + 1 = 5 个函数,其中序号14是不存在的,所以它的入口点是NULL。