通过序数从dll导出函数不会隐藏函数名称

时间:2016-12-28 23:35:06

标签: windows dll export ordinal

在Visual Studio中,我想仅通过序数从dll导出函数。在源代码中,我将函数定义为:

int my_function() { return 101; }     // without declspec(dllexport)

在.def文件中:

LIBRARY MyDll
    EXPORTS
        my_function @ 1 NONAME        // NONAME, export directory will not contain function name

在主程序中,我使用它:

#pragma comment(lib, "MyDll.lib")

declspec(dllimport) int my_function();

int main(int argc, char* argv[])
{
    int a = my_function();

    return 0;
}

代码编译和链接很好。记录NONAME属性仅按序数导出函数。

MyDll的导出目录NumberOfNames设置为零,因此dll本身不包含名称信息。 exe文件按顺序值导入函数,因此exe也不包含名称信息。

我尝试了不同的配置(调试,发布),程序链接仍然很好。也许lib文件包含函数名和序数之间的某种映射?我读到lib文件包含函数thunks,所以我们可以在lib文件中有这样的东西:

my_function @ 1:
    jmp IAT[0]
my_another_function @ 2:
    jmp IAT[1]

and-file exe导入表:

OriginalFirstThunk           FirstThunk
 0x80000001 (@ 1)          0x80000001 (@ 1)   // ordinal 1 will go through IAT[0]
 0x80000002 (@ 2)          0x80000002 (@ 2)   // ordinal 2 will go through IAT[1]

内存exe导入表:

OriginalFirstThunk           FirstThunk
 0x80000001 (@ 1)             IAT[0]
 0x80000002 (@ 2)             IAT[1]

如果是这样,那么为了隐藏功能名称,我们应该只提供dll文件,这意味着用户需要使用LoadLibrary加载dll并使用GetProcessAddress?我在这里缺少什么?

1 个答案:

答案 0 :(得分:0)

来自MSDN上的Exporting Functions from a DLL by Ordinal Rather Than by Name

  

如果要优化DLL的文件大小,请在每个导出的函数上使用NONAME属性。使用NONAME属性,序数存储在DLL的导出表中,而不是函数名称中。如果您要导出许多功能,这可以节省很多。

换句话说,NONAME只影响DLL,而不影响导入库。所以你观察到的行为是按预期的。

来自documentation for EXPORTS

  

可选关键字PRIVATE可防止entryname包含在LINK生成的导入库中。

因此,如果你同时使用PRIVATE和NONAME,你应该得到你想要的结果。然而,这首先打破了提供导入库的目的,至少就该特定功能而言。如果你想要一些可以通过导入库访问的函数,以及一些只能通过GetProcAddress访问的函数,这可能会很有用。

您可能更愿意为最终用户可用于链接的功能提供别名,例如,

LIBRARY MyDll
    EXPORTS
        function1=my_function @ 1 NONAME
        function2=my_other_function @ 2 NONAME

这应该把假名" function1"和"功能2"进入导入库,以便最终用户可以使用这些名称链接到函数,同时仍然隐藏秘密名称" my_function"和" my_other_function"在导入库和DLL中。 (不是我理解为什么名字首先需要保密,而是YMMV。)

免责声明:我自己没有尝试过,这个答案完全基于文档。