2009-12-21 85 views
2

正如我之前提到的一個問題,我正在模擬我的代碼中的GetProcAddress()函數。下面的代碼是成功的在做這個,但是它會導致應用程序崩潰,在Windows 7Windows 7上的動態加載失敗

void *GetFuncAddr(HMODULE hModule, char *fname) 
{ 
    unsigned int count = 1; 
    IMAGE_DOS_HEADER *DosHeader; 
    IMAGE_NT_HEADERS *NtHeaders; 
    IMAGE_OPTIONAL_HEADER *OptionalHeader; 
    IMAGE_DATA_DIRECTORY *DataDirectory; 
    IMAGE_EXPORT_DIRECTORY *Exp; 
    ULONG *addrof; 
    char *fullfname; 
    ULONG *faddr; 

    DosHeader = (IMAGE_DOS_HEADER *)hModule; 
    if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) 
    { 
     return NULL; 
    } 

    NtHeaders = (IMAGE_NT_HEADERS *)(((BYTE *)DosHeader) + DosHeader->e_lfanew); 
    if (NtHeaders->Signature != IMAGE_NT_SIGNATURE) 
    { 
     return NULL; 
    } 

    OptionalHeader = &NtHeaders->OptionalHeader; 
    DataDirectory = &OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 

    Exp = (IMAGE_EXPORT_DIRECTORY *)((size_t)DosHeader + DataDirectory->VirtualAddress); 

    addrof = (ULONG *)((BYTE*) hModule + Exp->addrof); 
    faddr = (ULONG*) ((BYTE*) hModule + Exp->AddressOfFunctions); 

    for(count = 0; count < Exp->NumberOfNames; count++) 
    { 
     fullfname = (char*)((BYTE*) hModule + addrof[count]);  
     if(strcmp(fullfname, fname) == 0) 
     { 
      return (void*)((BYTE*) hModule + faddr[count]); 
     } 
    } 

    return NULL; 
} 

不要緊,我使用這個應用程序崩潰試圖加載什麼功能。調用導入的函數時發生崩潰,所以我的猜測是返回的指針可能是這裏的罪魁禍首。這發生在x86和x64上。 在這段代碼中是否有任何明顯的原因?我試着設置函數返回FARPROC,但我得到了所有關於如何在((BYTE *)hModule + faddr [count])上施加返回的困惑;

無論如何,有什麼想法?解決方案? 任何幫助表示讚賞。

謝謝。傑西。

編輯我導入的某些API返回的錯誤是錯誤18,該參數不正確。

+1

首先,FARPROC是無關緊要的,因爲這是從16位時代遺留下來的時候FAR(段外)或NEAR(段間)地址。 指針的值是多少? 始終ASSERT(ptr)! – 2009-12-21 20:57:43

+0

感謝您的信息。我在調用函數的指針上聲明。如果指針爲空,我將標記錯誤並終止程序。但是,指針似乎很好 – Jessica 2009-12-21 21:02:47

+0

也許你正在被基地址隨機選中?它對你自己建造的dll是否失敗? – Eugene 2009-12-21 21:37:56

回答

4

我想你可能需要做一個額外的查找。

USHORT *ford; 
... 
ford = (USHORT*) ((BYTE*) hModule + Exp->AddressOfNameOrdinals); 

,然後由序偏移:

  return (void*)((BYTE*) hModule + faddr[ford[count]]); 

一些關於它的文章會談:http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

+0

這樣做。非常感謝。 – Jessica 2009-12-21 21:50:37

+0

很酷。我在看它的時候學到了一些東西,所以這也很好。如果你給我一個投票,我會在這個遊戲中獲得10個更多的分數:) – 2009-12-21 21:58:23

1

它看起來像你在表中假設序數#=偏移量。也許在Windows 7 DLL中不是這樣。

+0

如果你只是打印函數名稱和他們的地址,它甚至在Windows 7上似乎也沒問題。GetProcAddress返回相同的地址 – Jessica 2009-12-21 21:15:32

+0

您可能會遇到以下情況:導入GetWindowThreadProcessId時會發生什麼:使用GetProcAddress我得到0x7553ed3c作爲地址並與我的代碼我得到0x75566420。這不會從從Kernel32導入的函數發生,只有從User32和其他DLL導入的函數纔會發生這種情況。任何意見? – Jessica 2009-12-21 21:30:22

+0

稍微修改一下,它在Kernel32中偶爾會發生,就像CreateToolhelp32Snapshot的情況一樣 – Jessica 2009-12-21 21:33:03

0

如何創建句柄hModule?爲什麼你不使用GetProcAddress(你的函數似乎重複你的函數的行爲)?

+0

hModule來自LoadLibrary。而且我不想使用GetProcAddress,因此我發佈的代碼正如你所提到的那樣確實複製了功能或嘗試。 – Jessica 2009-12-21 21:31:29