2009-07-14 9 views
33

मुझे इसी तरह के प्रश्न मिल गए लेकिन मैं जो भी ढूंढ रहा हूं उसका कोई जवाब नहीं। तो यहां जाता है:डीएनएल निर्यात कार्यों को गणना करने के लिए Win32 एपीआई?

देशी Win32 dll के लिए, क्या एक Win32 API है जो इसके निर्यात फ़ंक्शन नामों को गिनने के लिए है?

उत्तर

41

dumpbin /exports आप जो चाहते हैं वह काफी है, लेकिन यह एक डेवलपर टूल है, Win32 API नहीं।

DONT_RESOLVE_DLL_REFERENCES साथ LoadLibraryEx भारी न करने की चेतावनी है, लेकिन इस विशेष मामले – के लिए उपयोगी होता है यह करता है (लेकिन आप वास्तव में जरूरत है या लाइब्रेरी से कुछ भी उपयोग करना चाहते हैं नहीं है) स्मृति में DLL मानचित्रण के बड़े कार्य करने , जो आपके लिए हेडर पढ़ने के लिए तुच्छ बनाता है: मॉड्यूल हैंडल LoadLibraryEx अंक से ठीक है।

#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]); 

पूरी तरह से अनचाहे, लेकिन मुझे लगता है कि यह कम या ज्यादा सही है। (प्रसिद्ध अंतिम शब्द।)

+0

काफी अच्छी तरह से है कि (ctypes के साथ) अजगर करने के लिए अपने त्वरित बंदरगाह ठीक काम करता है काम किया। धन्यवाद! –

+10

यह ध्यान रखना आवश्यक है कि ** ** DONT_RESOLVE_DLL_REFERENCES' ध्वज के साथ लोड होने के बाद ** ** कॉलिंग ** को झटका लग सकता है, क्योंकि लोड मॉड्यूल के लिए 'DllMain' नहीं कहा जाता है। –

+0

क्यों न केवल DONT_RESOLVE_DLL_REFERENCES के बजाय फ़ाइल को स्मृति-मानचित्र करें? यहां तक ​​कि तेज भी हो सकता है। – masterxilo

5

माइक्रोसॉफ्ट रिसर्च पर जाएं और डेटोरस लाइब्रेरी को पकड़ें। इसके उदाहरणों में से एक बिल्कुल वही करता है जो आप पूछ रहे हैं। पूरी लाइब्रेरी मूल रूप से Win32 फ़ंक्शन कॉल को बेहद आसान/दोहराना बनाती है। इसकी सुंदर ठंडी चीजें।

Detours

संपादित करें: भी ध्यान रखें कि अगर आप सिर्फ निर्यात तालिका को देखने के लिए चाहते हैं, आप कर सकते हैं (कम से कम दृश्य स्टूडियो में) अपनी परियोजना गुण बाहर निर्यात/आयात टेबल मुद्रित करने के लिए निर्धारित किया है। मुझे सटीक विकल्प याद नहीं है लेकिन Google के लिए आसान होना चाहिए।

** EDIT2: ** विकल्प परियोजना गुण है> Linker-> Debugging-> MapFile उत्पन्न -> हां (/ एमएपी)

0

तुम सिर्फ क्या कार्यों पता लगाने के लिए एक तरह से तलाश कर रहे हैं एक डीएलएल में निर्यात कर रहे हैं, आप माइक्रोसॉफ्ट के dependency walker (depend.exe) का उपयोग कर सकते हैं। यद्यपि आपको वास्तव में निर्यात को प्रोग्रामेटिक रूप से खोजने की आवश्यकता है, तो यह आपकी सहायता नहीं करेगा।

1

यदि आप अपना कोड लिखने की परेशानी पर नहीं जाना चाहते हैं और इस उद्देश्य के लिए पहले से मौजूद एक डीएलएल का उपयोग करना चाहते हैं, तो मैं PE File Format DLL की अनुशंसा करता हूं। स्रोत कोड के साथ आता है ताकि आप चाहें तो संशोधित कर सकते हैं। चिंता करने के लिए कोई जीपीएल नहीं।

यह भी एक जीयूआई एप्लीकेशन उपलब्ध है जो दिखाता है कि डीएलएल का उपयोग कैसे करें।

0

मैं गलत हो सकता हूं, और मैंने ईमानदार होने के लिए दो बार जांच नहीं की है, लेकिन मेरा मानना ​​है कि मॉड्यूल पर एपैमेन्टेंट कोड का उपयोग करने के साथ कुछ संगतता समस्याएं हो सकती हैं जो आपकी प्रक्रिया की तुलना में एक अलग वास्तुकला के तहत बनाई गई हैं। (फिर से, मैं अभी अपने गधे से पूरी तरह से बात कर रहा हूं)

गीथब पर एक परियोजना है, जिसे dll2def कहा जाता है जो एक ही तकनीक का उपयोग करता है (हालांकि यह फ़ाइल को स्मृति में लोड करता है), लेकिन ऐसा लगता है कि कुछ बाइनरी के आर्किटेक्चर के आधार पर निर्यात खोजने के लिए जगह में चेक करता है। जिस कोड में आप सबसे ज्यादा रुचि रखते हैं वह this file में है।

2

जबकि ephemient सही है LoadLibraryExDONT_RESOLVE_DLL_REFERENCES के साथ इस कार्य को सरल बना सकता है, आप इसे दिखाए जाने से भी सरल बना सकते हैं। डीएलएल की निर्यात निर्देशिका को स्वयं ढूंढने और गणना करने के बजाय, आप अपने लिए प्रतीकों को सूचीबद्ध करने के लिए SymEnumerateSymbols का उपयोग कर सकते हैं।

हालांकि उनके कोड से केवल मामूली सरल (बिना आवेषण के, उनकी आधा दर्जन लाइन कोड है) कम से कम सैद्धांतिक रूप से थोड़ा अतिरिक्त लचीलापन देता है यदि माइक्रोसॉफ्ट को किसी दिन निष्पादन योग्य प्रारूप को थोड़ा सा बदलने का फैसला करना चाहिए, और/या वास्तव में HMODULE बिंदुओं को बदलता है, इसलिए वह अब काम नहीं करता है (क्योंकि इनमें से अधिकतर विवरण आधिकारिक रूप से दस्तावेज नहीं हैं)।

2

इस प्रयास करें:

#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); 
    } 
} 

उदाहरण:

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

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

उत्पादन:

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 
संबंधित मुद्दे