2009-07-14 30 views
33

Tôi đã tìm thấy các câu hỏi tương tự nhưng không có câu trả lời cho những gì tôi đang tìm kiếm. Vì vậy, ở đây đi:Win32 API để liệt kê các hàm xuất dll?

Đối với một tệp Win32 gốc, có API Win32 để liệt kê tên hàm xuất của nó không?

Trả lời

41

dumpbin /exports là khá nhiều thứ bạn muốn, nhưng đó là công cụ dành cho nhà phát triển chứ không phải API Win32.

LoadLibraryEx với DONT_RESOLVE_DLL_REFERENCES được cảnh báo rất nhiều, nhưng sẽ hữu ích cho trường hợp cụ thể này – nó thực hiện việc nâng bản đồ DLL thành bộ nhớ (nhưng bạn không thực sự cần hoặc muốn sử dụng bất kỳ thứ gì từ thư viện) , điều này khiến bạn không thể đọc được tiêu đề: tay cầm mô-đun được trả về bởi LoadLibraryEx điểm ngay tại đó.

#include <winnt.h> 
HMODULE lib = LoadLibraryEx("library.dll", NULL, DONT_RESOLVE_DLL_REFERENCES); 
assert(((PIMAGE_DOS_HEADER)lib)->e_magic == IMAGE_DOS_SIGNATURE); 
PIMAGE_NT_HEADERS header = (PIMAGE_NT_HEADERS)((BYTE *)lib + ((PIMAGE_DOS_HEADER)lib)->e_lfanew); 
assert(header->Signature == IMAGE_NT_SIGNATURE); 
assert(header->OptionalHeader.NumberOfRvaAndSizes > 0); 
PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY)((BYTE *)lib + header-> 
    OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 
assert(exports->AddressOfNames != 0); 
BYTE** names = (BYTE**)((int)lib + exports->AddressOfNames); 
for (int i = 0; i < exports->NumberOfNames; i++) 
    printf("Export: %s\n", (BYTE *)lib + (int)names[i]); 

Hoàn toàn chưa được kiểm tra, nhưng tôi nghĩ nó ít nhiều chính xác. (Các từ cuối cùng nổi tiếng.)

+0

Làm việc cũng đủ rằng cổng nhanh chóng của tôi để Python (với ctypes) hoạt động tốt. Cảm ơn! –

+10

Điều cần lưu ý là ** gọi các hàm ** sau khi tải với cờ 'DONT_RESOLVE_DLL_REFERENCES' ** có thể làm hỏng **, vì không có' DllMain' được gọi cho mô đun được nạp. –

+0

Tại sao không chỉ bộ nhớ ánh xạ bản thân tệp thay vì DONT_RESOLVE_DLL_REFERENCES? Thậm chí có thể nhanh hơn. – masterxilo

5

Chuyển đến nghiên cứu của Microsoft và lấy Thư viện Detours. Một trong những ví dụ của nó thực hiện chính xác những gì bạn đang yêu cầu. Các thư viện toàn bộ về cơ bản làm cho detouring/định tuyến lại các cuộc gọi chức năng win32 vô cùng dễ dàng. Những thứ tuyệt vời của nó.

Detours

Edit: Cũng lưu ý rằng nếu bạn chỉ muốn nhìn vào bảng xuất khẩu, bạn có thể (ít nhất là trong studio thị giác) thiết lập các thuộc dự án của bạn để in ra các bảng xuất khẩu/nhập khẩu. Tôi không thể nhớ chính xác tùy chọn nhưng phải dễ dàng với google.

** Edit2: ** Các tùy chọn là dự án Properties-> Linker-> Debugging-> Tạo mapfile -> Yes (/ MAP)

0

Nếu bạn chỉ tìm kiếm một cách để tìm hiểu chức năng gì được xuất trong một DLL, bạn có thể sử dụng dependency walker của Microsoft (depends.exe). Điều này sẽ không giúp bạn nếu bạn thực sự cần phải khám phá các xuất khẩu lập trình, mặc dù.

1

Nếu bạn không muốn gặp rắc rối khi viết mã của riêng mình và muốn sử dụng một DLL đã tồn tại cho mục đích này, tôi khuyên bạn nên PE File Format DLL. Đi kèm với mã nguồn để bạn có thể sửa đổi nếu muốn. Không có GPL phải lo lắng.

Cũng có sẵn là một ứng dụng GUI cho biết cách sử dụng DLL.

0

Tôi có thể sai, và tôi chưa kiểm tra thành thật, nhưng tôi tin rằng có thể có một số vấn đề tương thích với việc sử dụng mã của ephemient trên mô-đun được xây dựng theo kiến ​​trúc khác với quy trình của bạn. (Một lần nữa, tôi có thể nói hoàn toàn ra khỏi ass của tôi ngay bây giờ)

Có một dự án trên github, được gọi là dll2def sử dụng cùng một kỹ thuật (mặc dù nó tải tệp vào bộ nhớ một mình), nhưng dường như có một số kiểm tra tại chỗ để tìm xuất khẩu tùy thuộc vào kiến ​​trúc của nhị phân. Mã bạn có nhiều khả năng sẽ quan tâm nhất là trong this file.

2

Mặc dù đúng là đúng là LoadLibraryEx với DONT_RESOLVE_DLL_REFERENCES có thể đơn giản hóa tác vụ này rất nhiều, bạn có thể làm cho nó đơn giản hơn nhiều so với hiển thị. Thay vì tìm và liệt kê thư mục xuất của DLL, bạn có thể sử dụng SymEnumerateSymbols để liệt kê các biểu tượng cho bạn.

Mặc dù chỉ đơn giản hơn mã của mình (không có xác nhận, nhưng chỉ có nửa tá mã) ít nhất về mặt lý thuyết sẽ mang lại thêm sự linh hoạt trong trường hợp một ngày nào đó Microsoft quyết định thay đổi định dạng thực thi/hoặc thay đổi chính xác những gì HMODULE chỉ ra, vì vậy anh ta không còn hoạt động nữa (vì hầu hết các chi tiết này không được chính thức ghi lại).

2

thử điều này:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

void EnumExportedFunctions (char *, void (*callback)(char*)); 
int Rva2Offset (unsigned int); 

typedef struct { 
    unsigned char Name[8]; 
    unsigned int VirtualSize; 
    unsigned int VirtualAddress; 
    unsigned int SizeOfRawData; 
    unsigned int PointerToRawData; 
    unsigned int PointerToRelocations; 
    unsigned int PointerToLineNumbers; 
    unsigned short NumberOfRelocations; 
    unsigned short NumberOfLineNumbers; 
    unsigned int Characteristics; 
} sectionHeader; 

sectionHeader *sections; 
unsigned int NumberOfSections = 0; 

int Rva2Offset (unsigned int rva) { 
    int i = 0; 

    for (i = 0; i < NumberOfSections; i++) { 
     unsigned int x = sections[i].VirtualAddress + sections[i].SizeOfRawData; 

     if (x >= rva) { 
      return sections[i].PointerToRawData + (rva + sections[i].SizeOfRawData) - x; 
     } 
    } 

    return -1; 
} 

void EnumExportedFunctions (char *szFilename, void (*callback)(char*)) { 
    FILE *hFile = fopen (szFilename, "rb"); 

    if (hFile != NULL) { 
     if (fgetc (hFile) == 'M' && fgetc (hFile) == 'Z') { 
      unsigned int e_lfanew = 0; 
      unsigned int NumberOfRvaAndSizes = 0; 
      unsigned int ExportVirtualAddress = 0; 
      unsigned int ExportSize = 0; 
      int i = 0; 

      fseek (hFile, 0x3C, SEEK_SET); 
      fread (&e_lfanew, 4, 1, hFile); 
      fseek (hFile, e_lfanew + 6, SEEK_SET); 
      fread (&NumberOfSections, 2, 1, hFile); 
      fseek (hFile, 108, SEEK_CUR); 
      fread (&NumberOfRvaAndSizes, 4, 1, hFile); 

      if (NumberOfRvaAndSizes == 16) { 
       fread (&ExportVirtualAddress, 4, 1, hFile); 
       fread (&ExportSize, 4, 1, hFile); 

       if (ExportVirtualAddress > 0 && ExportSize > 0) { 
        fseek (hFile, 120, SEEK_CUR); 

        if (NumberOfSections > 0) { 
         sections = (sectionHeader *) malloc (NumberOfSections * sizeof (sectionHeader)); 

         for (i = 0; i < NumberOfSections; i++) { 
          fread (sections[i].Name, 8, 1, hFile); 
          fread (&sections[i].VirtualSize, 4, 1, hFile); 
          fread (&sections[i].VirtualAddress, 4, 1, hFile); 
          fread (&sections[i].SizeOfRawData, 4, 1, hFile); 
          fread (&sections[i].PointerToRawData, 4, 1, hFile); 
          fread (&sections[i].PointerToRelocations, 4, 1, hFile); 
          fread (&sections[i].PointerToLineNumbers, 4, 1, hFile); 
          fread (&sections[i].NumberOfRelocations, 2, 1, hFile); 
          fread (&sections[i].NumberOfLineNumbers, 2, 1, hFile); 
          fread (&sections[i].Characteristics, 4, 1, hFile); 
         } 

         unsigned int NumberOfNames = 0; 
         unsigned int AddressOfNames = 0; 

         int offset = Rva2Offset (ExportVirtualAddress); 
         fseek (hFile, offset + 24, SEEK_SET); 
         fread (&NumberOfNames, 4, 1, hFile); 

         fseek (hFile, 4, SEEK_CUR); 
         fread (&AddressOfNames, 4, 1, hFile); 

         unsigned int namesOffset = Rva2Offset (AddressOfNames), pos = 0; 
         fseek (hFile, namesOffset, SEEK_SET); 

         for (i = 0; i < NumberOfNames; i++) { 
          unsigned int y = 0; 
          fread (&y, 4, 1, hFile); 
          pos = ftell (hFile); 
          fseek (hFile, Rva2Offset (y), SEEK_SET); 

          char c = fgetc (hFile); 
          int szNameLen = 0; 

          while (c != '\0') { 
           c = fgetc (hFile); 
           szNameLen++; 
          } 

          fseek (hFile, (-szNameLen)-1, SEEK_CUR); 
          char* szName = calloc (szNameLen + 1, 1); 
          fread (szName, szNameLen, 1, hFile); 

          callback (szName); 

          fseek (hFile, pos, SEEK_SET); 
         } 
        } 
       } 
      } 
     } 

     fclose (hFile); 
    } 
} 

dụ:

void mycallback (char* szName) { 
    printf ("%s\n", szName); 
} 

int main() { 
    EnumExportedFunctions ("C:\\Windows\\System32\\user32.dll", mycallback); 
    return 0; 
} 

đầu ra:

ActivateKeyboardLayout 
AddClipboardFormatListener 
AdjustWindowRect 
AdjustWindowRectEx 
AlignRects 
AllowForegroundActivation 
AllowSetForegroundWindow 
AnimateWindow 
AnyPopup 
AppendMenuA 
AppendMenuW 
ArrangeIconicWindows 
AttachThreadInput 
BeginDeferWindowPos 
BeginPaint 
BlockInput 
BringWindowToTop 
BroadcastSystemMessage 
BroadcastSystemMessageA 
BroadcastSystemMessageExA 
BroadcastSystemMessageExW 
BroadcastSystemMessageW 
BuildReasonArray 
CalcMenuBar 
.....etc 
Các vấn đề liên quan