2009-01-12 49 views
50

我一直在尋找一種方法來獲取映射到dll中的函數名稱的所有字符串。有沒有辦法找到一個dll暴露的所有功能

我的意思是這一切,你可以調用GetProcAddress的字符串。如果你做了一個DLL的十六進制轉儲符號(字符串)在那裏,但我認爲必須有一個系統調用來獲取這些名稱。

+1

只是雞蛋裏挑骨頭,但我認爲你的意思 >但我想必須有一個系統調用 – 2009-01-13 20:19:22

+0

如果你正在尋找一種方式來做到這一點programmaticly,看我的回答進一步下降。 – Aaron 2009-01-16 04:32:57

+1

還要記住,DLL可以導出沒有字符串名稱的函數,並且必須通過它們的序號進行訪問。 – 2013-10-02 17:33:31

回答

66

如果你有MS Visual Studio中,有一個名爲DUMPBIN的命令行工具。

dumpbin /exports <nameofdll>
+2

...也被稱爲:link.exe/dump/exports – reuben 2009-01-14 06:21:24

+0

你不用甚至不需要VS.您可以下載MS Windows SDK,並在其中使用CMD Shell。很有用。 – MeanwhileInHell 2013-11-12 13:48:38

+1

太棒了。這應該被標記爲已接受的答案 – 2015-11-25 09:19:22

7

的依賴程序我用dumpbinGUI,它給你的出口從Windows資源管理器右鍵單擊列表(和更多)。 dumpbindepends都會給你列表。

10

我不知道有一個WIn32 API可以這樣做:相反,您(或其他文章中提到的其中一個工具)通過了解PE文件的二進制格式並讀取該文件來完成此操作:請參閱http://msdn.microsoft.com/en-us/magazine/cc301808.aspx (該文章提到了「PEDUMP」工具)。

0

我想你最終會解析PE文件,但demangling自己,如果你想找到在運行時或極其無用系統(「DUMPBIN」)未知DLL的函數名;魔法。

你應該更清楚你想要什麼。

BFD庫你想要做什麼(以及廚房水槽),這是一些GNU binutils的工具的主要成分。我無法確定它是否適合您的問題。

5

您需要檢查.dll文件的PE頭,因爲這是最終什麼Windows不反正。

假設你有一個指向該.dll的IMAGE_OPTIONAL_HEADER(您可以使用DBGHELP的ImageNtHeader函數的句柄加載一個.dll通過LoadLibrary或試圖自行找到它,如果你知道該.dll自己的佈局)您需要查看optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT],找到相對於帶有偏移量的可選標題的導出表,然後轉到導出表(這是一個IMAGE_EXPORT_DIRECTORY)。

對於funsies,一個向後兼容PE圖像開始時用IMAGE_DOS_HEADER;與IMAGE_NT_HEADER的偏移量爲IMAGE_DOS_HEADER::e_lfanew,並且IMAGE_OPTIONAL_HEADER被嵌入在NT標頭中。

0

你不需要任何工具,你不需要解析PE。 只需使用標準的Win32 API(d)

的代碼(C)已經在Adv.Win32發表了許多次的API NG( 消息://comp.os.ms-windows.programmer.win32)(自1992年...)

30

有三種不同類型的DLL Windows下:在DLL的導出表暴露每個可用的功能

  1. 經典的DLL。您可以使用dumpbin.exe或依賴。EXE從Visual Studio,或免費dependency walker來檢查這些類型。 Matt Pietrek寫了很多文章和實用程序來挖掘Win32 PE文件。看看他的經典MSDN Magazine articles。包含導出類的C++ DLL將導出類中的每個方法。不幸的是,它輸出了重名的名字,所以dumpbin的輸出實際上是不可讀的。您將需要使用像vC++ _ filt.exe這樣的程序來對輸出進行分解。

  2. 公開COM對象的COM DLL。這些DLL公開了一些常規的導出函數(DllRegisterServer等),使COM系統能夠實例化對象。有很多實用程序可以查看這些DLL,但除非它們具有嵌入式類型庫,否則它們可能很難檢查。 4Developers有許多優秀的COM/ActiveX工具

  3. 包含.NET程序集的.NET DLL。通常你會使用像.NET Reflector這樣的工具來挖掘這些。

11

試試這個(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

0

您也可以在Windows下使用「objdump」linux工具,但可能必須先安裝cygwin。

我用下面的命令:

# feed the output to less 
objdump -x nameOfThe.Dll| less 
# or use egrep to filter 
objdump -x /cygdrive/c/Windows/system32/user32.dll | \ 
    egrep "^\s*\[[ [:digit:]]{4}\] \w{1,}" | less 
相關問題