2009-12-21 84 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