我一直在寻找一种方法来获取映射到dll中函数名称的所有字符串.
我的意思是你可以调用GetProcAddress的所有字符串.如果你做一个dll的十六进制转储,符号(字符串)就在那里,但我认为必须有一个系统调用来获取这些名称.
如果您有MS Visual Studio,则有一个名为DUMPBIN的命令行工具.
dumpbin /exports
Windows下有三种不同类型的DLL:
经典DLL,它暴露DLL的exports表中的每个可用函数.您可以使用Visual Studio中的dumpbin.exe或depends.exe,或者使用自由依赖性walker来检查这些类型.Matt Pietrek写了许多文章和实用程序,用于挖掘Win32 PE文件.看看他的经典MSDN杂志文章.包含导出类的C++ DLL将导出类中的每个方法.不幸的是,它导出了损坏的名称,因此dumpbin的输出实际上是不可读的.您需要使用类似vc ++ _ filt.exe的程序来解压缩输出.
暴露COM对象的COM DLL.这些DLL公开了一些常规导出函数(DllRegisterServer等),使COM系统能够实例化对象.有许多实用程序可以查看这些DLL,但除非它们具有嵌入式类型库,否则它们很难检查.4开发人员拥有许多优秀的COM/ActiveX工具
包含.NET程序集的.NET DLL.通常,你会使用像.NET Reflector这样的工具来深入研究这些工具.
编辑:4Developers链接无法正常工作.
另外还有http://www.dependencywalker.com/上的DEPENDs计划.
试试这个(Linux)C代码:
#include#include #include #include #include #include unsigned int vpe2offset(void * base, unsigned int vpe) { unsigned int * ptr = base; unsigned int pe_offset; unsigned short num_sections; pe_offset = ptr[0x3c/4]; //PE header offset ptr = base + pe_offset; //PE header address num_sections = ((unsigned short*)ptr)[6/2]; //Section count ptr = ((void*)base) + 0x18 + 0x60 + 16*8 + pe_offset;//Address of first section while (num_sections--) { if (vpe >= ptr[0x0c/4] && vpe < ptr[0x0c/4] + ptr[0x10/4]) { return vpe - ptr[0x0c/4] + ptr[0x14/4]; } ptr += 0x28/4; } return 0; } void iterate_exports(void * base, int(*iterator)(char*)) { unsigned int * ptr = base; unsigned int pe_offset, exports_offset, number_of_names, address_of_names; pe_offset = ptr[0x3c/4]; ptr = base + pe_offset; exports_offset = ptr[0x78/4]; ptr = base + vpe2offset(base, exports_offset); number_of_names = ptr[0x18/4]; address_of_names = ptr[0x20/4]; ptr = base + vpe2offset(base, address_of_names); while (number_of_names-- && iterator((char*)(base + vpe2offset(base, ptr++[0])))) { /* Do nothing */ } } int print_symbol_name(char * name) { printf("%s\n", name); return 1; } int main(int argc, char const *argv[]) { int fd; struct stat st; void * base; if (argc == 1) { printf("Usage: %s \n", argv[0]); } else if (stat(argv[1], &st) == 0 && (fd = open(argv[1], O_RDONLY)) >= 0) { base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (base != MAP_FAILED) { iterate_exports(base, print_symbol_name); munmap(base, st.st_size); } else { fprintf(stderr, "Could not map \"%s\".\n", argv[1]); } close(fd); } else { fprintf(stderr, "Could not open \"%s\" for reading.\n", argv[1]); } return 0; }
它遵循PE文件中的引用,最后为每个导出的符号调用回调函数.有关PE文件格式的概述,请参阅:http://www.openrce.org/reference_library/files/reference/PE%20Format.pdf
我不知道WIn32 API可以做到这一点:相反,您(或其他帖子中提到的工具之一)通过了解PE文件的二进制格式并读取文件来完成它:请参阅http:// msdn .microsoft.com/en-us/magazine/cc301808.aspx(该文章提到了"PEDUMP"实用程序).
这需要一些工作,但您可以使用Microsoft 的DbgHelp库以编程方式执行此操作.
John Robbins调试Microsoft .Net和Microsoft Windows的应用程序是一本优秀的(如果有点旧)书,其中包含使用细节和完整源代码.并且,您可以在亚马逊上以便宜的价格购买它!
我使用dumpbinGUI,它通过在Windows资源管理器中右键单击为您提供导出列表(以及更多).dumpbin
并且depends
都会给你列表.
您需要检查.dll的PE头,因为这最终是Windows所做的.
假设你有一个指向.dll的指针IMAGE_OPTIONAL_HEADER
(如果你自己知道.dll的布局,你可以使用ImageNtHeader
带有.dll句柄的dbghelp 函数LoadLibrary
或者自己尝试找到它),你会想看看optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
,找到相对于带有偏移量的可选标题的导出表,然后遍历导出表(它是a IMAGE_EXPORT_DIRECTORY
).
对于funsies,向后兼容的PE图像以a开头IMAGE_DOS_HEADER
; 偏移到IMAGE_NT_HEADER
is IMAGE_DOS_HEADER::e_lfanew
,并IMAGE_OPTIONAL_HEADER
嵌入在NT标头中.