我已经定义了DLL导出如下:
__declspec(dllexport)
DWORD WINAPI DllBootstrap(LPVOID addr) {
return 0;
}
现在,使用DUMPBIN,符号显示如下:
1 0 0001100A ?DllBootstrap@@YGKPAX@Z = @ILT+5(?DllBootstrap@@YGKPAX@Z)
这就是内存在Visual Studio中的外观:
¡}....ReflectDLL.dll.?DllBootstrap@@YGKPAX@Z..........................................
检查PIMAGE_EXPORT_DIRECTORY.AddressOfNames
时。
我需要的是一个干净的符号,即DUMPBIN应输出如下内容:
1 0 0001100A DllBootstrap
和PIMAGE_EXPORT_DIRECTORY.AddressOfNames
应指向:
DllBootstrap..........................................
我怎样才能做到这一点?
WIN32建议:
正如@RbMm指出的那样,为了保持您的函数名称不存在并且没有名称修饰,您必须使用.DEF文件(并删除__declspec(dllexport)说明符)。然后使用下面的行创建一个DEF文件,并使用/ DEF链接器选项指定它或将其添加到Visual Studio项目中,链接器将自动拾取它:
EXPORTS DllBootstrap
如果您不想处理外部.DEF文件并且您将使用Visual C ++编译器,那么使用代码限制修饰的最简单方法是使用'extern“C”'声明您的函数。这导致装饰包括前面的下划线,并附加“@”以及参数的十进制字节数。以下代码为例:
extern "C" __declspec(dllexport)
DWORD WINAPI DllBootstrap(LPVOID addr) {
return 0;
}
生成一个导出的名称:
_DllBootstrap@4
这是使用'extern“C”'禁用C ++名称修改时装饰stdcall函数的方法。注意:WINAPI映射到__stdcall。保留'extern“C”'并将约定更改为__cdecl,您将无法获得任何装饰,但模块入口点通常应保持stdcall,因为您已在样本中列出它。
如果您仍想避免使用.DEF文件,那么您可以使用最后一个hack。将以下行添加到您的代码中:
#pragma comment(linker,"/EXPORT:DllBootstrap=_DllBootstrap@4")
这将向链接器传递一个参数,创建一个新的未修饰的名称符号,该符号映射到修饰的名称。这不是很干净,因为原始名称仍然存在于您的DLL中,但您将获得干净的导出名称。
WIN64 BUILDS(更新):
正如Hans Passant评论的那样,对于任何使用Visual C ++ 64位编译器的人来说,只有64位调用约定(stdcall,cdecl等关键字被忽略)。虽然在此编译器下仍会发生C ++重整,但不会对导出的名称进行额外修饰。在这种情况下,当样本编译为C ++代码时,'extern“C”'就足够了;如果编译为C,则不需要进行任何修改。