我一直在寻找一种方法来获取映射到dll中函数名称的所有字符串。
我的意思是你可以调用GetProcAddress的所有字符串。如果你做一个dll的十六进制转储符号(字符串)在那里,但我认为必须有一个系统调用来获取这些名称。
答案 0 :(得分:69)
如果您有MS Visual Studio,则有一个名为DUMPBIN的命令行工具。
dumpbin /exports <nameofdll>
答案 1 :(得分:32)
Windows下有三种不同类型的DLL:
公开DLL,它暴露DLL的exports表中的每个可用函数。您可以使用Visual Studio中的dumpbin.exe或depends.exe,或免费dependency walker来检查这些类型。 Matt Pietrek写了许多文章和实用程序,用于挖掘Win32 PE文件。看看他的经典MSDN Magazine articles。包含导出类的C ++ DLL将导出类中的每个方法。不幸的是,它导出了损坏的名称,因此dumpbin的输出实际上是不可读的。您需要使用类似vc ++ _ filt.exe的程序来解压缩输出。
公开COM对象的COM DLL。这些DLL公开了一些常规导出函数(DllRegisterServer等),使COM系统能够实例化对象。有许多实用程序可以查看这些DLL,但除非它们具有嵌入式类型库,否则它们很难检查。 4Developers有许多优秀的COM / ActiveX工具
包含.NET程序集的.NET DLL。通常,你会使用像.NET Reflector这样的工具来深入研究这些工具。
编辑:4Developers链接无效。
答案 2 :(得分:24)
答案 3 :(得分:16)
试试这个(Linux)C代码:
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
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 <dll>\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
答案 4 :(得分:10)
我不知道要使用WIn32 API:相反,您(或其他帖子中提到的工具之一)通过了解PE文件的二进制格式并读取文件来执行此操作:请参阅{{ 3}}(那篇文章提到了“PEDUMP”实用程序)。
答案 5 :(得分:7)
这需要一些工作,但您可以使用Microsoft的DbgHelp库以编程方式执行此操作。
Debugging Applications for Microsoft .Net and Microsoft Windows, by John Robbins是一本优秀(如果有点旧)的书,其中包含使用细节和完整来源。并且,您可以在亚马逊上以便宜的价格购买它!
答案 6 :(得分:6)
我使用dumpbinGUI,它在Windows资源管理器中右键单击,为您提供导出列表(以及更多)。 dumpbin
和depends
也会为您提供列表。
答案 7 :(得分:5)
你需要检查.dll的PE头,因为这最终是Windows所做的。
假设你有一个指向.dll IMAGE_OPTIONAL_HEADER
的指针(你可以使用dbghelp的ImageNtHeader
函数,通过LoadLibrary
加载.dll的句柄,或者尝试自己查找你知道你自己的.dll的布局),你会想看optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
,找到相对于可选标题的导出表,其中有偏移量,然后走导出表(它是{{1} }})。
对于funsies,向后兼容的PE图像以IMAGE_EXPORT_DIRECTORY
开始; IMAGE_DOS_HEADER
的偏移量为IMAGE_NT_HEADER
,IMAGE_DOS_HEADER::e_lfanew
嵌入在NT标头中。
答案 8 :(得分:2)
有一个名为dll export viewer的程序,您可以使用:http://www.nirsoft.net/utils/dll_export_viewer.html
答案 9 :(得分:2)
答案 10 :(得分:1)
你也可以使用&#34; objdump&#34; windows下的linux工具,但你可能要先安装cygwin。
我使用以下命令:
foreach (string key in HttpContext.Request.Form.Keys)
{
}
答案 11 :(得分:0)
我想如果你想在运行时或极无用的系统(“dumpbin”)中找到未知dll的函数名,你最终会解析PE文件并自己进行解码;魔法。
你应该更清楚你想要什么。
BFD库可以做你想要的(和厨房水槽),这是几个GNU binutils工具的主要组成部分。我无法确定它是否适合你的问题。
答案 12 :(得分:0)
您不需要任何工具,也不需要解析PE。 只需使用标准的Win32 api(D)
代码(C中)已在Adv.Win32 api ng上多次发布( news://comp.os.ms-windows.programmer.win32)(自1992年起......)